// Zombie Monster for KF Invasion gametype class NiceZombieClot extends NiceZombieClotBase; #exec OBJ LOAD FILE=KF_Freaks_Trip.ukx #exec OBJ LOAD FILE=KF_Specimens_Trip_T.utx #exec OBJ LOAD FILE=MeanZedSkins.utx function ClawDamageTarget() { local vector PushDir; local KFPawn KFP; local float UsedMeleeDamage; if( MeleeDamage > 1 ) { UsedMeleeDamage = (MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1)); } else { UsedMeleeDamage = MeleeDamage; } // If zombie has latched onto us... if ( MeleeDamageTarget( UsedMeleeDamage, PushDir)) { KFP = KFPawn(Controller.Target); PlaySound(MeleeAttackHitSound, SLOT_Interact, 2.0); if( !bDecapitated && KFP != none ) { if( KFPlayerReplicationInfo(KFP.PlayerReplicationInfo) == none || KFP.GetVeteran().static.CanBeGrabbed(KFPlayerReplicationInfo(KFP.PlayerReplicationInfo), self)) { if( DisabledPawn != none ) { DisabledPawn.bMovementDisabled = false; } KFP.DisableMovement(GrappleDuration); DisabledPawn = KFP; } } } } function RangedAttack(Actor A) { if ( bShotAnim || Physics == PHYS_Swimming) return; else if ( CanAttack(A) ) { bShotAnim = true; SetAnimAction('Claw'); return; } } simulated event SetAnimAction(name NewAction) { local int meleeAnimIndex; if( NewAction=='' ) Return; if(NewAction == 'Claw') { meleeAnimIndex = Rand(3); NewAction = meleeAnims[meleeAnimIndex]; } ExpectingChannel = DoAnimAction(NewAction); if( AnimNeedsWait(NewAction) ) { bWaitForAnim = true; } if( Level.NetMode!=NM_Client ) { AnimAction = NewAction; bResetAnimAct = True; ResetAnimActTime = Level.TimeSeconds+0.3; } } simulated function bool AnimNeedsWait(name TestAnim) { if( TestAnim == 'KnockDown' || TestAnim == 'DoorBash' ) { return true; } return false; } simulated function int DoAnimAction( name AnimName ) { if( AnimName=='ClotGrapple' || AnimName=='ClotGrappleTwo' || AnimName=='ClotGrappleThree' ) { AnimBlendParams(1, 1.0, 0.1,, FireRootBone); PlayAnim(AnimName,, 0.1, 1); // Randomly send out a message about Clot grabbing you(10% chance) if ( FRand() < 0.10 && LookTarget != none && KFPlayerController(LookTarget.Controller) != none && VSizeSquared(Location - LookTarget.Location) < 2500 /* (MeleeRange + 20)^2 */ && Level.TimeSeconds - KFPlayerController(LookTarget.Controller).LastClotGrabMessageTime > ClotGrabMessageDelay && KFPlayerController(LookTarget.Controller).SelectedVeterancy != class'KFVetBerserker' ) { PlayerController(LookTarget.Controller).Speech('AUTO', 11, ""); KFPlayerController(LookTarget.Controller).LastClotGrabMessageTime = Level.TimeSeconds; } bGrappling = true; GrappleEndTime = Level.TimeSeconds + GrappleDuration; return 1; } return super.DoAnimAction( AnimName ); } simulated function Tick(float DeltaTime) { super.Tick(DeltaTime); if( bShotAnim && Role == ROLE_Authority ) { if( LookTarget!=none ) { Acceleration = AccelRate * Normal(LookTarget.Location - Location); } } if( Role == ROLE_Authority && bGrappling ) { if( Level.TimeSeconds > GrappleEndTime ) { bGrappling = false; } } // if we move out of melee range, stop doing the grapple animation if( bGrappling && LookTarget != none ) { if( VSize(LookTarget.Location - Location) > MeleeRange + CollisionRadius + LookTarget.CollisionRadius ) { bGrappling = false; AnimEnd(1); } } } function RemoveHead() { Super.RemoveHead(); MeleeAnims[0] = 'Claw'; MeleeAnims[1] = 'Claw'; MeleeAnims[2] = 'Claw2'; MeleeDamage *= 2; MeleeRange *= 2; if( DisabledPawn != none ) { DisabledPawn.bMovementDisabled = false; DisabledPawn = none; } } function Died(Controller Killer, class damageType, vector HitLocation) { if( DisabledPawn != none ) { DisabledPawn.bMovementDisabled = false; DisabledPawn = none; } super.Died(Killer, damageType, HitLocation); } simulated function Destroyed() { super.Destroyed(); if( DisabledPawn != none ) { DisabledPawn.bMovementDisabled = false; DisabledPawn = none; } } static simulated function PreCacheStaticMeshes(LevelInfo myLevel) {//should be derived and used. Super.PreCacheStaticMeshes(myLevel); /* myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_1'); myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_2'); myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_3'); myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_4'); myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_5'); myLevel.AddPrecacheStaticMesh(StaticMesh'kf_gore_trip_sm.clot.clothead_piece_6'); */ } static simulated function PreCacheMaterials(LevelInfo myLevel) {//should be derived and used. myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.clot_cmb'); myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.clot_env_cmb'); myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.clot_diffuse'); myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.clot_spec'); } defaultproperties { idleInsertFrame=0.468000 EventClasses(0)="NicePack.NiceZombieClot" MoanVoice=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Talk' MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_HitPlayer' JumpSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Jump' DetachedArmClass=Class'KFChar.SeveredArmClot' DetachedLegClass=Class'KFChar.SeveredLegClot' DetachedHeadClass=Class'KFChar.SeveredHeadClot' HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Pain' DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Death' ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge' ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge' ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge' ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge' AmbientSound=Sound'KF_BaseClot.Clot_Idle1Loop' Mesh=SkeletalMesh'KF_Freaks_Trip.CLOT_Freak' Skins(0)=Combiner'KF_Specimens_Trip_T.clot_cmb' }