NicePack/sources/Zeds/Nice/NiceZombieFleshpoundController.uc

198 lines
5.7 KiB
Ucode

class NiceZombieFleshpoundController extends NiceMonsterController;
var float RageAnimTimeout; // How long until the RageAnim is completed; Hack so the server doesn't get stuck in idle when its doing the Rage anim
var bool bDoneSpottedCheck;
var float RageFrustrationTimer; // Tracks how long we have been walking toward a visible enemy
var float RageFrustrationThreshhold; // Base value for how long the FP should walk torward an enemy without reaching them before getting frustrated and raging
simulated function PostBeginPlay(){
super.PostBeginPlay();
RageFrustrationTimer = 0;
}
function Tick(float Delta){
local bool bSeesPlayers;
local Controller PC;
local KFHumanPawn Human;
local NiceZombieFleshPound ZFP;
super.Tick(Delta);
bSeesPlayers = false;
for(PC = Level.ControllerList;PC != none;PC = PC.NextController){
Human = KFHumanPawn(PC.Pawn);
if(Human != none && Human.Health > 0 && !Human.bPendingDelete && CanSee(Human)){
bSeesPlayers = true;
break;
}
}
if(bSeesPlayers){
if(RageFrustrationTimer < RageFrustrationThreshhold){
RageFrustrationTimer += Delta;
if(RageFrustrationTimer >= RageFrustrationThreshhold){
ZFP = NiceZombieFleshPound(Pawn);
if(ZFP != none && !ZFP.bChargingPlayer){
ZFP.StartChargingFP(Pawn(focus));
ZFP.bFrustrated = true;
}
}
}
}
else
RageFrustrationTimer = 0;
}
// Never do that, you too cool
function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}
state ZombieHunt
{
event SeePlayer(Pawn SeenPlayer)
{
if ( !bDoneSpottedCheck && PlayerController(SeenPlayer.Controller) != none )
{
// 25% chance of first player to see this Fleshpound saying something
if ( !KFGameType(Level.Game).bDidSpottedFleshpoundMessage && FRand() < 0.25 )
{
PlayerController(SeenPlayer.Controller).Speech('AUTO', 12, "");
KFGameType(Level.Game).bDidSpottedFleshpoundMessage = true;
}
bDoneSpottedCheck = true;
}
super.SeePlayer(SeenPlayer);
}
}
function TimedFireWeaponAtEnemy()
{
if ( (Enemy == none) || FireWeaponAt(Enemy) )
SetCombatTimer();
else
SetTimer(0.01, True);
}
state SpinAttack
{
ignores EnemyNotVisible;
// Don't do this in this state
function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}
function DoSpinDamage()
{
local Actor A;
//log("FLESHPOUND DOSPINDAMAGE!");
foreach CollidingActors(class'actor', A, (NiceZombieFleshpound(pawn).MeleeRange * 1.5)+pawn.CollisionRadius, pawn.Location)
NiceZombieFleshpound(pawn).SpinDamage(A);
}
Begin:
WaitForAnim:
While( KFM.bShotAnim )
{
Sleep(0.1);
DoSpinDamage();
}
WhatToDoNext(152);
if ( bSoaking )
SoakStop("STUCK IN SPINATTACK!!!");
}
state ZombieCharge
{
function bool StrafeFromDamage(float Damage, class<DamageType> DamageType, bool bFindDest)
{
return false;
}
// I suspect this function causes bloats to get confused
function bool TryStrafe(vector sideDir)
{
return false;
}
function Timer()
{
Disable('NotifyBump');
Target = Enemy;
TimedFireWeaponAtEnemy();
}
WaitForAnim:
if ( Monster(Pawn).bShotAnim )
{
Goto('Moving');
}
if ( !FindBestPathToward(Enemy, false,true) )
GotoState('ZombieRestFormation');
Moving:
MoveToward(Enemy);
WhatToDoNext(17);
if ( bSoaking )
SoakStop("STUCK IN CHARGING!");
}
// Used to set a timeout for the WaitForAnim state. This is a bit of a hack fix
// for the FleshPound getting stuck in its idle anim on a dedicated server when it
// is supposed to be raging. For some reason, on a dedicated server only, it
// never gets an animend call for the PoundRage anim, instead the anim gets
// interrupted by the PoundIdle anim. If we figure that bug out, we can
// probably take this out in the future. But for now the fix works - Ramm
function SetPoundRageTimout(float NewRageTimeOut)
{
RageAnimTimeout = NewRageTimeOut;
}
state WaitForAnim
{
Ignores SeePlayer,HearNoise,Timer,EnemyNotVisible,NotifyBump;
// Don't do this in this state
function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}
function BeginState()
{
bUseFreezeHack = False;
}
// The rage anim has ended, clear the flags and let the AI do its thing
function RageTimeout()
{
if( bUseFreezeHack )
{
if( Pawn!=none )
{
Pawn.AccelRate = Pawn.Default.AccelRate;
Pawn.GroundSpeed = Pawn.Default.GroundSpeed;
}
bUseFreezeHack = False;
AnimEnd(0);
}
}
function Tick( float Delta )
{
Global.Tick(Delta);
if( RageAnimTimeout > 0 )
{
RageAnimTimeout -= Delta;
if( RageAnimTimeout <= 0 )
{
RageAnimTimeout = 0;
RageTimeout();
}
}
if( bUseFreezeHack )
{
MoveTarget = none;
MoveTimer = -1;
Pawn.Acceleration = vect(0,0,0);
Pawn.GroundSpeed = 1;
Pawn.AccelRate = 0;
}
}
function EndState()
{
if( Pawn!=none )
{
Pawn.AccelRate = Pawn.Default.AccelRate;
Pawn.GroundSpeed = Pawn.Default.GroundSpeed;
}
bUseFreezeHack = False;
}
Begin:
While( KFM.bShotAnim )
{
Sleep(0.15);
}
WhatToDoNext(99);
}
defaultproperties
{
RageFrustrationThreshhold=10.000000
}