// Zombie Monster for KF Invasion gametype class ZombieCrawler extends ZombieCrawlerBase abstract; #exec OBJ LOAD FILE=PlayerSounds.uax //---------------------------------------------------------------------------- // NOTE: All Variables are declared in the base class to eliminate hitching //---------------------------------------------------------------------------- function bool DoPounce() { if ( bZapped || bIsCrouched || bWantsToCrouch || (Physics != PHYS_Walking) || VSize(Location - Controller.Target.Location) > (MeleeRange * 5) ) return false; Velocity = Normal(Controller.Target.Location-Location)*PounceSpeed; Velocity.Z = JumpZ; SetPhysics(PHYS_Falling); ZombieSpringAnim(); bPouncing=true; return true; } simulated function ZombieSpringAnim() { SetAnimAction('ZombieSpring'); } event Landed(vector HitNormal) { bPouncing=false; super.Landed(HitNormal); } event Bump(actor Other) { // TODO: is there a better way if(bPouncing && KFHumanPawn(Other)!=none ) { KFHumanPawn(Other).TakeDamage(((MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1))), self ,self.Location,self.velocity, class 'KFmod.ZombieMeleeDamage'); if (KFHumanPawn(Other).Health <=0) { //TODO - move this to humanpawn.takedamage? Also see KFMonster.MeleeDamageTarget KFHumanPawn(Other).SpawnGibs(self.rotation, 1); } //After impact, there'll be no momentum for further bumps bPouncing=false; } } // Blend his attacks so he can hit you in mid air. simulated function int DoAnimAction( name AnimName ) { if( AnimName=='InAir_Attack1' || AnimName=='InAir_Attack2' ) { AnimBlendParams(1, 1.0, 0.0,, FireRootBone); PlayAnim(AnimName,, 0.0, 1); return 1; } if( AnimName=='HitF' ) { AnimBlendParams(1, 1.0, 0.0,, NeckBone); PlayAnim(AnimName,, 0.0, 1); return 1; } if( AnimName=='ZombieSpring' ) { PlayAnim(AnimName,,0.02); return 0; } return Super.DoAnimAction(AnimName); } simulated event SetAnimAction(name NewAction) { local int meleeAnimIndex; if( NewAction=='' ) Return; if(NewAction == 'Claw') { meleeAnimIndex = Rand(2); if( Physics == PHYS_Falling ) { NewAction = MeleeAirAnims[meleeAnimIndex]; } else { NewAction = meleeAnims[meleeAnimIndex]; } CurrentDamtype = ZombieDamType[meleeAnimIndex]; } ExpectingChannel = DoAnimAction(NewAction); if( AnimNeedsWait(NewAction) ) { bWaitForAnim = true; } if( Level.NetMode!=NM_Client ) { AnimAction = NewAction; bResetAnimAct = True; ResetAnimActTime = Level.TimeSeconds+0.3; } } // The animation is full body and should set the bWaitForAnim flag simulated function bool AnimNeedsWait(name TestAnim) { if( TestAnim == 'ZombieSpring' || TestAnim == 'DoorBash' ) { return true; } return false; } function bool FlipOver() { Return False; } static simulated function PreCacheMaterials(LevelInfo myLevel) {//should be derived and used. myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.crawler_cmb'); myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.crawler_env_cmb'); myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.crawler_diff'); } defaultproperties { //------------------------------------------------------------------------------- // NOTE: Most Default Properties are set in the base class to eliminate hitching //------------------------------------------------------------------------------- EventClasses(0)="KFChar.ZombieCrawler_STANDARD" ControllerClass=Class'KFChar.CrawlerController' }