Blitzkrieg Posted May 26, 2021 Posted May 26, 2021 (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 May 26, 2021 by Blitzkrieg Hopefully fixed the spoilers. 1 3 Quote
KejbL Posted May 27, 2021 Posted May 27, 2021 (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 May 27, 2021 by KabLe21 Quote
Recommended Posts
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.