Jump to content

Recommended Posts

Posted (edited)

This thread is about  first stage Scarlet Van Halisha ( on foot -NPCID: 29046, class: follower_of_frintessa).

Many think that the walking boss is two different NPCs, but it's actually one.

It simply has two sets of animations, one set without wings on its back, and one set with wings.

 

 

How the boss utilizes the different sets of animations

 

Frst of all, we inspect lineagemonster3.int:

 

[follower_of_frintessa]

 

Spoiler

WalkAnimName[0]=Run_1HS
RunAnimName[0]=Run_1HS   
WaitAnimName[0]=AtkWait_1HS
AtkWaitAnimName[0]=AtkWait_1HS
Atk01AnimName[0]=Atk01_1HS
Atk02AnimName[0]=Atk01_1HS
Atk03AnimName[0]=Atk01_1HS
SpAtk01AnimName[0]=SpAtk01_1HS
SpAtk02AnimName[0]=SpAtk02_1HS
SpAtk03AnimName[0]=SpAtk03_1HS
CastShortAnimName[0]=SpAtk01_1HS
CastMidAnimName[0]=SpAtk01_1HS
CastLongAnimName[0]=SpAtk01_1HS
CastEndAnimName[0]=AtkWait_1HS
MagicShotAnimName[0]=SpAtk02_1HS
MagicThrowAnimName[0]=SpAtk02_1HS
MagicNoTargetAnimName[0]=SpAtk02_1HS
DeathAnimName[0]=Death
DeathWaitAnimName[0]=Deathwait

 

WalkAnimName[1]=Run_1HS
RunAnimName[1]=Run_1HS   
WaitAnimName[1]=AtkWait_1HS
AtkWaitAnimName[1]=AtkWait_1HS
Atk01AnimName[1]=Atk01_1HS
Atk02AnimName[1]=Atk01_1HS
Atk03AnimName[1]=Atk01_1HS
SpAtk01AnimName[1]=SpAtk01_1HS
SpAtk02AnimName[1]=Atk01_1HS
SpAtk03AnimName[1]=SpAtk03_1HS
CastShortAnimName[1]=SpAtk01_1HS
CastMidAnimName[1]=SpAtk01_1HS
CastLongAnimName[1]=SpAtk01_1HS
CastEndAnimName[1]=AtkWait_1HS
MagicShotAnimName[1]=SpAtk02_1HS
MagicThrowAnimName[1]=SpAtk02_1HS
MagicNoTargetAnimName[1]=SpAtk02_1HS
DeathAnimName[1]=Death
DeathWaitAnimName[1]=Deathwait

 

WalkAnimName[2]=Run_2HS
RunAnimName[2]=Run_2HS 
WaitAnimName[2]=AtkWait_2HS
AtkWaitAnimName[2]=AtkWait_2HS
Atk01AnimName[2]=Atk01_2HS
Atk02AnimName[2]=Atk01_2HS
Atk03AnimName[2]=Atk01_2HS
SpAtk01AnimName[2]=SpAtk01_2HS
SpAtk02AnimName[2]=Atk01_2HS
SpAtk03AnimName[2]=SpAtk03_2HS
SpAtk04AnimName[2]=SpAtk04_2HS
SpAtk05AnimName[2]=SpAtk05_2HS
CastShortAnimName[2]=SpAtk01_2HS
CastMidAnimName[2]=SpAtk01_2HS
CastLongAnimName[2]=SpAtk01_2HS
CastEndAnimName[2]=AtkWait_2HS
MagicShotAnimName[2]=SpAtk02_2HS
MagicThrowAnimName[2]=SpAtk02_2HS
MagicNoTargetAnimName[2]=SpAtk02_2HS
DeathAnimName[2]=Death
DeathWaitAnimName[2]=DeathWait

 

NpcSocialAnimName[0]=social02
NpcSocialAnimName[1]=Death
NpcSocialAnimName[2]=DeathWait
NpcSocialAnimName[3]=SpAtk05_2HS

 

Animations ending with _1HS are the ones without wings, whereas Animations ending with _2HS have the wings sticking out.
Animations with [0] index are used when the boss doesn't hold any weapon (I think).
Animations with [1] index are used when the boss holds a weapon with handess =1
Animations with [2] index are used when the boss holds a weapon with handess = 2 

The initial weapon that the boss is holding (slot_rhand=[follower_of_frintessa_calibur])  has 8204 ID and has indeed handess = 1
Through AI the boss changes weapon: EquipItem (@sword_of_frintessa). This weapon has 7903 ID and as expected, handess = 2.

 


How the boss gets bigger through the transition

 

In AI we can see the following line:


AddUseSkillDesire(myself.sm, @s_frintessa_daemon_morph1, @ST_HEAL, @AMT_MOVE_TO_TARGET, 1000000);

 

s_frintessa_daemon_morph1 has a skill ID of 5017. In mobskillanimgrp.dat we can find the following:


29046    5017    social02    a,s_frintessa_daemon_morph1\0    a,follower_of_frintessa\0    a,LineageMonster3.follower_of_frintessa\0

 

Studying this specific animation with l2editor, we can see that it uses the bonescale animnotify. Photo

 


How the boss utilizes the rush/charge skill

 

The boss normally has a forward charge skill (ID: 5015, effect: {i_fly_self;straight;pull;400} ) that consists of 3 phases: Initial animation, boss disappearance and lastly landing animation.

 

In skillgrp.dat we can see that the animation letter that is asigned to skill 5015 is "A". This means the following:
combo_begin    name=[A]    anim0=[CastShortAnimName]    anim1=[CastEndAnimName]    anim2=[MagicNoTargetAnimName]    loop=1    combo_end
We can observe the 3 stages that were described before.

The names of these animations correspond to the animations in lineagemonster3.int, so basically: SpAtk01_2HS, AtkWait_2HS and SpAtk02_2HS.

 

In order to make the boss disappear in the second part of the animation (AtkWait_2HS), bhidden unrealscipt variable is used in the npc's class. Here's the full class script so you can study it yourselves:

 

[follower_of_frintessa]
 

Spoiler

class follower_of_frintessa extends LineagePawn;

var Emitter    Effect0;        // disappear effect
var Emitter Effect1;        // ground effect
var Emitter Effect2;        // body effect
var    Emitter    Effect3;        // first hit effect
var Emitter    Effect4;        // second hit effect

var float    EffectTimer0;    // disappear effect timer
var float    EffectTimer1;    // ground effect timer
var float    EffectTimer2;    // body effect timer
var float    EffectTimer3;    // first hit effect timer
var float    EffectTimer4;    // second hit effect timer

var bool    PrepareHidden;
var bool    Transformed;

var    vector    EffectLocation;
var    rotator    EffectRotation;

var float    DashTimer;

simulated event ClearL2Game()
{
    if(Effect0 != None)
    {
        Effect0.NDestroy();
        Effect0 = None;
    }
    
    if(Effect1 != None)
    {
        Effect1.NDestroy();
        Effect1 = None;
    }
    
    if(Effect2 != None)
    {
        Effect2.NDestroy();
        Effect2 = None;
    }
    
    if(Effect3 != None)
    {
        Effect3.NDestroy();
        Effect3 = None;
    }
    
    if(Effect4 != None)
    {
        Effect4.NDestroy();
        Effect4 = None;
    }
}

simulated function Destroyed()
{
    Super.Destroyed();    
    ClearL2Game();
}

simulated event AnimBegin(name SequenceName)
{
    local vector loc;

   
    if((SequenceName == 'AtkWait_1HS' || SequenceName == 'AtkWait_2HS') && PrepareHidden)
    {
        bHidden = True;
        PrepareHidden = False;
        bReadyToWarp = True;
    }
    
    
    if(SequenceName == 'SpAtk01_1HS' || SequenceName == 'SpAtk01_2HS')
    {
        bHidden = False;
        EffectTimer0 = 0.4;
        EffectTimer1 = 0.7;
        EffectTimer3 = 1.1;
        EffectTimer4 = 1.2;
        PrepareHidden = True;
        bIgnoreToWarp = True;
        DashTimer = 2.0;
    }
    
    
    if(SequenceName == 'SpAtk02_1HS')
    {
        bHidden = False;
        loc = Location - 70.f * Rotator2Vector(Rotation);
        Effect0 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ca', Self, '', loc, Rotation);
    }
    
    if(SequenceName == 'SpAtk02_2HS')
    {
        bHidden = False;
        loc = Location - 70.f * Rotator2Vector(Rotation);
        Effect0 = Spawn(class'LineageEffect.mb_frintessa_charge_b_ca', Self, '', loc, Rotation);
    }
    
    
    if(SequenceName == 'Social02')
    {
        Transformed = True;
        EffectTimer2 = 3.7;
    }
}

simulated function Tick(float DeltaTime)
{
    local vector    loc;
    local rotator    rot;
    
    if(PrepareHidden)
    {
        EffectLocation = Location;
        if(IsWarpDest)
            EffectRotation = Vector2Rotator(WarpDest-Location);
        else
            EffectRotation = Rotation;
    }
    
    if(bReadyToWarp && IsWarpDest)
    {
        bReadyToWarp = False;
        SetLocation(WarpDest);
        IsWarpDest = False;
    }
        
    if(EffectTimer0 > 0)
    {
        EffectTimer0 -= DeltaTime;
        if(EffectTimer0 <= 0)
        {
            loc = EffectLocation + 70.f * Rotator2Vector(EffectRotation);
            rot = EffectRotation;
            if(Transformed)
                Effect0 = Spawn(class'Lineageeffect.mb_frintessa_charge_b_ca', Self, '', loc, rot);
            else
                Effect0 = Spawn(class'Lineageeffect.mb_frintessa_charge_a_ca', Self, '', loc, rot);
        }
    }
    
    if(EffectTimer1 > 0)
    {
        EffectTimer1 -= DeltaTime;
        if(EffectTimer1 <= 0)
        {
            loc = EffectLocation + 200.f * Rotator2Vector(EffectRotation);
            loc.Z -= CollisionHeight;
            
            rot = EffectRotation;
            rot.Yaw += 16384;
            
            if(Transformed)
                Effect1 = Spawn(class'LineageEffect.mb_frintessa_charge_b_ra', Self, '', loc, rot);
            else
                Effect1 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ra', Self, '', loc, rot);
        }
    }
    
    if(EffectTimer2 > 0)
    {
        EffectTimer2 -= DeltaTime;
        if(EffectTimer2 <= 0)
        {
            Effect2 = Spawn(class'LineageEffect.mb_frintessa_body_a', Self, '', Location, Rotation);
            if(Effect2 != None)
            {
                AttachToBone(Effect2, 'bip01 spine1');
                Effect2.SetRelativeRotation(rot(32768, 16384, 49152));
                Effect2.SetDrawScale(0.9);
            }
        }
    }
    
    if(EffectTimer3 > 0)
    {
        EffectTimer3 -= DeltaTime;
        if(EffectTimer3 <= 0)
        {
            if(Transformed)
            {
                loc = EffectLocation + 300.f * Rotator2Vector(EffectRotation);
                loc.Z -= CollisionHeight;
                
                rot = EffectRotation;
                rot.Yaw += 16384;
                
                Effect3 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ta', Self, '', loc, rot);
            }
            else
            {
                loc = EffectLocation + 250.f * Rotator2Vector(EffectRotation);
                loc.Z -= CollisionHeight;
                
                rot = EffectRotation;
                rot.Yaw += 16384;
                
                Effect3 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ta', Self, '', loc, rot);
            }
        }
    }
    
    if(EffectTimer4 > 0)
    {
        EffectTimer4 -= DeltaTime;
        if(EffectTimer4 <= 0)
        {
            if(Transformed)
            {
                loc = EffectLocation + 300.f * Rotator2Vector(EffectRotation);
                loc.Z -= CollisionHeight;
                
                rot = EffectRotation;
                rot.Yaw += 16384;
                
                Effect3 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ta', Self, '', loc, rot);
            }
            else
            {
                loc = EffectLocation + 250.f * Rotator2Vector(EffectRotation);
                loc.Z -= CollisionHeight;
                
                rot = EffectRotation;
                rot.Yaw += 16384;
                
                Effect3 = Spawn(class'LineageEffect.mb_frintessa_charge_a_ta', Self, '', loc, rot);
            }
        }
    }
    
    if(DashTimer > 0)
    {
        DashTimer -= DeltaTime;
        if(DashTimer <= 0)
        {
            DashTimer = 0;
            bHidden = False;
        }
    }
    else
    {
        bHidden = False;
    }
}

defaultproperties
{
    WeaponScale=1.25
    GroundMaxSpeed=60.00
    GroundMinSpeed=60.00
    bReadyToWarp=False
    ControllerClass=Class'LineageMonster.HerdMonster'
    bActorShadows=False
    DrawScale=1.25
    CollisionRadius=45.00
    CollisionHeight=90.70
}

 



 
What about the debris falling after the raid ended?


Interestingly the teleport cube  is responsible for this. Here's its script:
 

Spoiler

class teleport_npc_frin extends LineagePawn;

var actor        ViewEmitter;
var string        EmitterClass;

var    Emitter        StoneEffect[21];
var    float        StoneEffectInitialDelay[21];
var float        StoneEffectResetTimer;
var vector        StoneEffectLocation[21];

simulated function PostBeginPlay()
{    
    local class<Emitter> tempClass;

    Super.PostBeginPlay();

    tempClass = class<Emitter>( DynamicLoadObject( EmitterClass, class'Class') );
    if(tempClass != None)
    {
        ViewEmitter = Spawn(tempClass,Self,'',Location,Rotation);
        ViewEmitter.SetPhysics(PHYS_Trailer);
        ViewEmitter.bTrailerSameRotation=false;
        ViewEmitter.bTrailerPrePivot=true;
        ViewEmitter.SetBase( Self,vect(0,0,1));
    }        
}

simulated event Detach(Actor Other )
{
    if(ViewEmitter == Other)
        ViewEmitter = None;
    Super.Detach(Other);
}


simulated function Destroyed()
{
    local int i;
    
    Super.Destroyed();

    if(ViewEmitter != None)
    {
        ViewEmitter.NDestroy();
        ViewEmitter = None;
    }
    
    for(i = 0; i < 21; ++i)
    {
        if(StoneEffect[i] != None)
        {
            StoneEffect[i].NDestroy();
            StoneEffect[i] = None;
        }
    }
}

// no mesh -> no bone
event GetEffTargetLocation(out vector LocVector)
{
    LocVector = Location;
}

simulated function Tick(float DeltaTime)
{
    local int    i;
    local int    Index;
    
    if(StoneEffectResetTimer >= 10)
    {
        for(i = 0; i < 21; ++i)
        {
            StoneEffectInitialDelay[i] = FRand() * 10;
            if(StoneEffect[i] != None)
            {
                StoneEffect[i].Kill();
                StoneEffect[i] = None;
            }
        }
        
        while(StoneEffectResetTimer >= 10)
        {
            StoneEffectResetTimer -= 10;
        }
    }
    
    for(i = 0; i < 21; ++i)
    {
        if(StoneEffect[i] == None && StoneEffectInitialDelay[i] != -1 && StoneEffectInitialDelay[i] <= StoneEffectResetTimer)
        {    
            Index = 5 * FRand();

            switch(Index)
            {
            case 0:    StoneEffect[i] = Spawn(class'LineageEffect.mb_frintessa_drop_b', Self, '', StoneEffectLocation[i], rot(0,0,0));    break;
            case 1:    StoneEffect[i] = Spawn(class'LineageEffect.mb_frintessa_drop_c', Self, '', StoneEffectLocation[i], rot(0,0,0));    break;
            case 2:    StoneEffect[i] = Spawn(class'LineageEffect.mb_frintessa_drop_d', Self, '', StoneEffectLocation[i], rot(0,0,0));    break;
            case 3:    StoneEffect[i] = Spawn(class'LineageEffect.mb_frintessa_drop_e', Self, '', StoneEffectLocation[i], rot(0,0,0));    break;
            case 4:    StoneEffect[i] = Spawn(class'LineageEffect.mb_frintessa_drop_f', Self, '', StoneEffectLocation[i], rot(0,0,0));    break;
            }
            
            StoneEffectInitialDelay[i] = -1;
        }
    }
    
    StoneEffectResetTimer += DeltaTime;
}

defaultproperties
{
    EmitterClass="Lineageeffect.teleport_map_a"
    StoneEffectResetTimer=10.00
    StoneEffectLocation(0)=(X=174998.00,Y=-88423.00,Z=-5112.00),
    StoneEffectLocation(1)=(X=174571.00,Y=-89292.00,Z=-5104.00),
    StoneEffectLocation(2)=(X=174573.00,Y=-88995.00,Z=-5112.00),
    StoneEffectLocation(3)=(X=174571.00,Y=-88697.00,Z=-5112.00),
    StoneEffectLocation(4)=(X=174292.00,Y=-86342.00,Z=-5104.00),
    StoneEffectLocation(5)=(X=173457.00,Y=-87617.00,Z=-5112.00),
    StoneEffectLocation(6)=(X=173830.00,Y=-87810.00,Z=-5112.00),
    StoneEffectLocation(7)=(X=173471.00,Y=-88409.00,Z=-5112.00),
    StoneEffectLocation(8)=(X=173872.00,Y=-88268.00,Z=-5112.00),
    StoneEffectLocation(9)=(X=173893.00,Y=-88696.00,Z=-5112.00),
    StoneEffectLocation(10)=(X=179893.00,Y=-88990.00,Z=-5112.00),
    StoneEffectLocation(11)=(X=173897.00,Y=-89299.00,Z=-5104.00),
    StoneEffectLocation(12)=(X=174279.00,Y=-89791.00,Z=-5016.00),
    StoneEffectLocation(13)=(X=174589.00,Y=-88269.00,Z=-5112.00),
    StoneEffectLocation(14)=(X=174637.00,Y=-87812.00,Z=-5112.00),
    StoneEffectLocation(15)=(X=175026.00,Y=-87604.00,Z=-5112.00),
    StoneEffectLocation(16)=(X=174914.00,Y=-86685.00,Z=-5104.00),
    StoneEffectLocation(17)=(X=172843.00,Y=-87111.00,Z=-5104.00),
    StoneEffectLocation(18)=(X=172797.00,Y=-88965.00,Z=-5104.00),
    StoneEffectLocation(19)=(X=175661.00,Y=-88584.00,Z=-5104.00),
    StoneEffectLocation(20)=(X=175610.00,Y=-86967.00,Z=-5104.00),
    GroundSpeed=120.00
    ControllerClass=Class'HerdNpc'
    DrawType=15
    CollisionRadius=40.00
    CollisionHeight=80.00
}

 

Edited by Blitzkrieg
Hopefully fixed the spoilers.
  • Like 1
  • Upvote 3
Posted (edited)

i have problem with halisha when transform feet stuck to textures :P cant u fix it ? :D when i die later all OK or give restart ....

Edited by KabLe21

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...