205 lines
6.0 KiB
Ucode
205 lines
6.0 KiB
Ucode
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> 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)
|
|
}
|