370 lines
8.8 KiB
Ucode
370 lines
8.8 KiB
Ucode
// Zombie Monster for KF Invasion gametype
|
|
// GOREFAST.
|
|
// He's speedy, and swings with a Single enlongated arm, affording him slightly more range
|
|
class ZombieGoreFast extends ZombieGoreFastBase
|
|
abstract;
|
|
|
|
#exec OBJ LOAD FILE=PlayerSounds.uax
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NOTE: All Variables are declared in the base class to eliminate hitching
|
|
//----------------------------------------------------------------------------
|
|
|
|
simulated function PostNetReceive()
|
|
{
|
|
if( !bZapped )
|
|
{
|
|
if (bRunning)
|
|
MovementAnims[0]='ZombieRun';
|
|
else MovementAnims[0]=default.MovementAnims[0];
|
|
}
|
|
}
|
|
|
|
// This zed has been taken control of. Boost its health and speed
|
|
function SetMindControlled(bool bNewMindControlled)
|
|
{
|
|
if( bNewMindControlled )
|
|
{
|
|
NumZCDHits++;
|
|
|
|
// if we hit him a couple of times, make him rage!
|
|
if( NumZCDHits > 1 )
|
|
{
|
|
if( !IsInState('RunningToMarker') )
|
|
{
|
|
GotoState('RunningToMarker');
|
|
}
|
|
else
|
|
{
|
|
NumZCDHits = 1;
|
|
if( IsInState('RunningToMarker') )
|
|
{
|
|
GotoState('');
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( IsInState('RunningToMarker') )
|
|
{
|
|
GotoState('');
|
|
}
|
|
}
|
|
|
|
if( bNewMindControlled != bZedUnderControl )
|
|
{
|
|
SetGroundSpeed(OriginalGroundSpeed * 1.25);
|
|
Health *= 1.25;
|
|
HealthMax *= 1.25;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NumZCDHits=0;
|
|
}
|
|
|
|
bZedUnderControl = bNewMindControlled;
|
|
}
|
|
|
|
// Handle the zed being commanded to move to a new location
|
|
function GivenNewMarker()
|
|
{
|
|
if( bRunning && NumZCDHits > 1 )
|
|
{
|
|
GotoState('RunningToMarker');
|
|
}
|
|
else
|
|
{
|
|
GotoState('');
|
|
}
|
|
}
|
|
|
|
function RangedAttack(Actor A)
|
|
{
|
|
Super.RangedAttack(A);
|
|
if( !bShotAnim && !bDecapitated && VSize(A.Location-Location)<=700 )
|
|
GoToState('RunningState');
|
|
}
|
|
|
|
state RunningState
|
|
{
|
|
// Set the zed to the zapped behavior
|
|
simulated function SetZappedBehavior()
|
|
{
|
|
Global.SetZappedBehavior();
|
|
GoToState('');
|
|
}
|
|
|
|
// Don't override speed in this state
|
|
function bool CanSpeedAdjust()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
if( bZapped )
|
|
{
|
|
GoToState('');
|
|
}
|
|
else
|
|
{
|
|
SetGroundSpeed(OriginalGroundSpeed * 1.875);
|
|
bRunning = true;
|
|
if( Level.NetMode!=NM_DedicatedServer )
|
|
PostNetReceive();
|
|
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
}
|
|
}
|
|
|
|
function EndState()
|
|
{
|
|
if( !bZapped )
|
|
{
|
|
SetGroundSpeed(GetOriginalGroundSpeed());
|
|
}
|
|
bRunning = False;
|
|
if( Level.NetMode!=NM_DedicatedServer )
|
|
PostNetReceive();
|
|
|
|
RunAttackTimeout=0;
|
|
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
}
|
|
|
|
function RemoveHead()
|
|
{
|
|
GoToState('');
|
|
Global.RemoveHead();
|
|
}
|
|
|
|
function RangedAttack(Actor A)
|
|
{
|
|
local float ChargeChance;
|
|
|
|
// Decide what chance the gorefast has of charging during an attack
|
|
if( Level.Game.GameDifficulty < 2.0 )
|
|
{
|
|
ChargeChance = 0.1;
|
|
}
|
|
else if( Level.Game.GameDifficulty < 4.0 )
|
|
{
|
|
ChargeChance = 0.2;
|
|
}
|
|
else if( Level.Game.GameDifficulty < 5.0 )
|
|
{
|
|
ChargeChance = 0.3;
|
|
}
|
|
else // Hardest difficulty
|
|
{
|
|
ChargeChance = 0.4;
|
|
}
|
|
|
|
if ( bShotAnim || Physics == PHYS_Swimming)
|
|
return;
|
|
else if ( CanAttack(A) )
|
|
{
|
|
bShotAnim = true;
|
|
|
|
// Randomly do a moving attack so the player can't kite the zed
|
|
if( FRand() < ChargeChance )
|
|
{
|
|
SetAnimAction('ClawAndMove');
|
|
RunAttackTimeout = GetAnimDuration('GoreAttack1', 1.0);
|
|
}
|
|
else
|
|
{
|
|
SetAnimAction('Claw');
|
|
Controller.bPreparingMove = true;
|
|
Acceleration = vect(0,0,0);
|
|
// Once we attack stop running
|
|
GoToState('');
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
simulated function Tick(float DeltaTime)
|
|
{
|
|
// Keep moving toward the target until the timer runs out (anim finishes)
|
|
if( RunAttackTimeout > 0 )
|
|
{
|
|
RunAttackTimeout -= DeltaTime;
|
|
|
|
if( RunAttackTimeout <= 0 && !bZedUnderControl )
|
|
{
|
|
RunAttackTimeout = 0;
|
|
GoToState('');
|
|
}
|
|
}
|
|
|
|
// Keep the gorefast moving toward its target when attacking
|
|
if( Role == ROLE_Authority && bShotAnim && !bWaitForAnim )
|
|
{
|
|
if( LookTarget!=None )
|
|
{
|
|
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
|
}
|
|
}
|
|
|
|
global.Tick(DeltaTime);
|
|
}
|
|
|
|
|
|
Begin:
|
|
GoTo('CheckCharge');
|
|
CheckCharge:
|
|
if( Controller!=None && Controller.Target!=None && VSize(Controller.Target.Location-Location)<700 )
|
|
{
|
|
Sleep(0.5+ FRand() * 0.5);
|
|
//log("Still charging");
|
|
GoTo('CheckCharge');
|
|
}
|
|
else
|
|
{
|
|
//log("Done charging");
|
|
GoToState('');
|
|
}
|
|
}
|
|
|
|
// State where the zed is charging to a marked location.
|
|
state RunningToMarker extends RunningState
|
|
{
|
|
simulated function Tick(float DeltaTime)
|
|
{
|
|
// Keep moving toward the target until the timer runs out (anim finishes)
|
|
if( RunAttackTimeout > 0 )
|
|
{
|
|
RunAttackTimeout -= DeltaTime;
|
|
|
|
if( RunAttackTimeout <= 0 && !bZedUnderControl )
|
|
{
|
|
RunAttackTimeout = 0;
|
|
GoToState('');
|
|
}
|
|
}
|
|
|
|
// Keep the gorefast moving toward its target when attacking
|
|
if( Role == ROLE_Authority && bShotAnim && !bWaitForAnim )
|
|
{
|
|
if( LookTarget!=None )
|
|
{
|
|
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
|
}
|
|
}
|
|
|
|
global.Tick(DeltaTime);
|
|
}
|
|
|
|
|
|
Begin:
|
|
GoTo('CheckCharge');
|
|
CheckCharge:
|
|
if( bZedUnderControl || (Controller!=None && Controller.Target!=None && VSize(Controller.Target.Location-Location)<700) )
|
|
{
|
|
Sleep(0.5+ FRand() * 0.5);
|
|
GoTo('CheckCharge');
|
|
}
|
|
else
|
|
{
|
|
GoToState('');
|
|
}
|
|
}
|
|
|
|
// Overridden to handle playing upper body only attacks when moving
|
|
simulated event SetAnimAction(name NewAction)
|
|
{
|
|
local int meleeAnimIndex;
|
|
local bool bWantsToAttackAndMove;
|
|
|
|
if( NewAction=='' )
|
|
Return;
|
|
|
|
bWantsToAttackAndMove = NewAction == 'ClawAndMove';
|
|
|
|
if( NewAction == 'Claw' )
|
|
{
|
|
meleeAnimIndex = Rand(3);
|
|
NewAction = meleeAnims[meleeAnimIndex];
|
|
CurrentDamtype = ZombieDamType[meleeAnimIndex];
|
|
}
|
|
|
|
if( bWantsToAttackAndMove )
|
|
{
|
|
ExpectingChannel = AttackAndMoveDoAnimAction(NewAction);
|
|
}
|
|
else
|
|
{
|
|
ExpectingChannel = DoAnimAction(NewAction);
|
|
}
|
|
|
|
if( !bWantsToAttackAndMove && AnimNeedsWait(NewAction) )
|
|
{
|
|
bWaitForAnim = true;
|
|
}
|
|
else
|
|
{
|
|
bWaitForAnim = false;
|
|
}
|
|
|
|
if( Level.NetMode!=NM_Client )
|
|
{
|
|
AnimAction = NewAction;
|
|
bResetAnimAct = True;
|
|
ResetAnimActTime = Level.TimeSeconds+0.3;
|
|
}
|
|
}
|
|
|
|
// Handle playing the anim action on the upper body only if we're attacking and moving
|
|
simulated function int AttackAndMoveDoAnimAction( name AnimName )
|
|
{
|
|
local int meleeAnimIndex;
|
|
|
|
if( AnimName == 'ClawAndMove' )
|
|
{
|
|
meleeAnimIndex = Rand(3);
|
|
AnimName = meleeAnims[meleeAnimIndex];
|
|
CurrentDamtype = ZombieDamType[meleeAnimIndex];
|
|
}
|
|
|
|
if( AnimName=='GoreAttack1' || AnimName=='GoreAttack2' )
|
|
{
|
|
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
|
PlayAnim(AnimName,, 0.1, 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
return super.DoAnimAction( AnimName );
|
|
}
|
|
|
|
simulated function HideBone(name boneName)
|
|
{
|
|
// Gorefast does not have a left arm and does not need it to be hidden
|
|
if (boneName != LeftFArmBone)
|
|
{
|
|
super.HideBone(boneName);
|
|
}
|
|
}
|
|
|
|
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
|
{//should be derived and used.
|
|
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.gorefast_cmb');
|
|
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.gorefast_env_cmb');
|
|
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.gorefast_diff');
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
//-------------------------------------------------------------------------------
|
|
// NOTE: Most Default Properties are set in the base class to eliminate hitching
|
|
//-------------------------------------------------------------------------------
|
|
|
|
EventClasses(0)="KFChar.ZombieGorefast_STANDARD"
|
|
ControllerClass=Class'KFChar.GorefastController'
|
|
|
|
// The gorefasts left arm is already set to gibbed so that shooting his nub will not create severed limbs
|
|
bLeftArmGibbed=true
|
|
}
|