class ZombieClotOS extends KFMonsterOS; //TODO: Break grapple immediately on death var KFPawn DisabledPawn; // The pawn that has been disabled by this zombie's grapple var bool bGrappling; // This zombie is grappling someone var float GrappleEndTime; // When the current grapple should be over var() float GrappleDuration; // How long a grapple by this zombie should last var float ClotGrabMessageDelay; // Amount of time between a player saying "I've been grabbed" message replication { reliable if(bNetDirty && Role == ROLE_Authority) bGrappling; } function BreakGrapple() { if( DisabledPawn != none ) { DisabledPawn.bMovementDisabled = false; DisabledPawn = none; } } 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 ( MeleeDamageTarget( UsedMeleeDamage, PushDir)) { KFP = KFPawn(Controller.Target); if( !bDecapitated && KFP != none ) { if ( KFPlayerReplicationInfo(KFP.PlayerReplicationInfo).ClientVeteranSkill != class'KFVetBerserker') { if( DisabledPawn != none ) DisabledPawn.bMovementDisabled = false; KFP.DisableMovement(GrappleDuration); DisabledPawn = KFP; } } } } function DoorAttack(Actor A) { if ( bShotAnim || Physics == PHYS_Swimming) return; else if ( CanAttack(A) ) { bShotAnim = true; SetAnimAction('Claw2'); PlaySound(sound'Claw2s', SLOT_None); return; } } function RangedAttack(Actor A) { if ( bShotAnim || Physics == PHYS_Swimming) return; else if ( CanAttack(A) ) { bShotAnim = true; SetAnimAction('Claw'); Acceleration = Normal(A.Location-Location)*600; Controller.GoToState('WaitForAnim'); Controller.MoveTarget = A; Controller.MoveTimer = 1.5; } } simulated event SetAnimAction(name NewAction) { local int meleeAnimIndex; if( NewAction=='' ) return; if(NewAction == 'Claw') { meleeAnimIndex = Rand(3); NewAction = meleeAnims[2]; CurrentDamtype = ZombieDamType[meleeAnimIndex]; } ExpectingChannel = DoAnimAction(NewAction); if( AnimNeedsWait(NewAction) ) bWaitForAnim = true; else bWaitForAnim = false; if( Level.NetMode!=NM_Client ) { AnimAction = NewAction; bResetAnimAct = true; ResetAnimActTime = Level.TimeSeconds+0.3; } } simulated function int DoAnimAction( name AnimName ) { if( AnimName=='ClotGrapple' ) { if ( FRand() < 0.10 && LookTarget != none && KFPlayerController(LookTarget.Controller) != none && VSizeSquared(Location - LookTarget.Location) < 2500 && 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; } } return super.DoAnimAction( AnimName ); } function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HitIndex) { super.takeDamage(Damage, instigatedBy, hitLocation, momentum, damageType); //Fixed log spam if( (Health < 0 || Damage > Health) && DisabledPawn != None) DisabledPawn.bMovementDisabled = false; } 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; } } static simulated function PreCacheStaticMeshes(LevelInfo myLevel) { super.PreCacheStaticMeshes(myLevel); } static simulated function PreCacheMaterials(LevelInfo myLevel) { myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Clot.ClotSkin'); } defaultproperties { GrappleDuration=1.000000 ClotGrabMessageDelay=12.000000 MeleeAnims(2)="ClotGrapple" MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.clot.Clot_Speech' bCannibal=True MeleeDamage=6 damageForce=5000 KFRagdollName="ClotRag" JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieJump' CrispUpThreshhold=9 PuntAnim="ClotPunt" AdditionalWalkAnims(0)="ClotWalk" Intelligence=BRAINS_Mammal bUseExtendedCollision=True ColOffset=(Z=48.000000) ColRadius=25.000000 ColHeight=5.000000 OnlineHeadshotOffset=(X=21.000000,Y=-7.000000,Z=43.000000) OnlineHeadshotScale=1.200000 MotionDetectorThreat=0.340000 HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombiePain' DeathSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombieDeath' ScoringValue=7 MeleeRange=20.000000 GroundSpeed=105.000000 WaterSpeed=105.000000 JumpZ=340.000000 HealthMax=130.000000 Health=130 HeadHeight=5.000000 MenuName="Clot 2.5" MovementAnims(0)="ClotWalk" WalkAnims(0)="ClotWalk" WalkAnims(1)="ClotWalk" WalkAnims(2)="ClotWalk" WalkAnims(3)="ClotWalk" AmbientSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieBreath' Mesh=SkeletalMesh'KFCharacterModelsOldSchool.InfectedWhiteMale1' Skins(0)=Texture'KFOldSchoolZeds_Textures.clot.ClotSkin' RotationRate=(Yaw=45000,Roll=0) }