243 lines
6.5 KiB
Ucode
243 lines
6.5 KiB
Ucode
Class Ext_T_ZEDHelper extends Info
|
|
transient
|
|
DependsOn(Ext_TraitZED_Summon)
|
|
config(ServerExt);
|
|
|
|
var config array<FZEDTypes> ZedTypes; // Dummy hack, not really config but merely just for being able to set class on defaults.
|
|
|
|
var() float FriendlyScalar;
|
|
var Pawn PawnOwner;
|
|
var byte CurLevel,RespawnHelperTime,NoLiveCounter;
|
|
var KFPawn_Monster LiveHelper;
|
|
var class<KFPawn_Monster> PrevMonster;
|
|
var float PrevMonsterHP;
|
|
|
|
var float HPScale,DamageScale;
|
|
var int OldKillsValue;
|
|
var bool bNeedsKillZed,bIsExtra;
|
|
|
|
function PostBeginPlay()
|
|
{
|
|
PawnOwner = Pawn(Owner);
|
|
bNeedsKillZed = true;
|
|
if( PawnOwner==None )
|
|
Destroy();
|
|
else
|
|
{
|
|
OldKillsValue = PawnOwner.PlayerReplicationInfo.Kills;
|
|
SetTimer(1+(FRand()*0.1),true);
|
|
}
|
|
}
|
|
function Timer()
|
|
{
|
|
if( PawnOwner==None || PawnOwner.Health<=0 || PawnOwner.PlayerReplicationInfo==None )
|
|
Destroy();
|
|
else if( bNeedsKillZed )
|
|
{
|
|
if( RespawnHelperTime>1 )
|
|
--RespawnHelperTime;
|
|
if( OldKillsValue==PawnOwner.PlayerReplicationInfo.Kills )
|
|
return;
|
|
bNeedsKillZed = false;
|
|
}
|
|
else if( RespawnHelperTime>0 )
|
|
{
|
|
if( --RespawnHelperTime==0 )
|
|
SpawnHelper();
|
|
}
|
|
else if( LiveHelper==None || LiveHelper.Health<=0 )
|
|
{
|
|
OldKillsValue = PawnOwner.PlayerReplicationInfo.Kills;
|
|
bNeedsKillZed = true;
|
|
RespawnHelperTime = 60;
|
|
}
|
|
else if( !HasLiveZeds() )
|
|
{
|
|
if( NoLiveCounter==0 )
|
|
{
|
|
PrevMonster = LiveHelper.Class;
|
|
PrevMonsterHP = (float(LiveHelper.Health) / LiveHelper.HealthMax);
|
|
LiveHelper.Died(None,class'KFDT_Healing',vect(0,0,0));
|
|
RespawnHelperTime = 5;
|
|
}
|
|
else --NoLiveCounter;
|
|
}
|
|
else NoLiveCounter = 5;
|
|
}
|
|
function Destroyed()
|
|
{
|
|
if( LiveHelper!=None && LiveHelper.Health>0 )
|
|
LiveHelper.Died(None,class'DmgType_Suicided',vect(0,0,0));
|
|
}
|
|
final function bool HasLiveZeds()
|
|
{
|
|
local KFPawn_Monster M;
|
|
|
|
if( KFGameReplicationInfo(WorldInfo.GRI).WaveNum>KFGameReplicationInfo(WorldInfo.GRI).WaveMax ) // No pets on possible bonus waves.
|
|
return false;
|
|
|
|
foreach WorldInfo.AllPawns(Class'KFPawn_Monster',M)
|
|
if( M.Health>0 && M.GetTeamNum()!=0 )
|
|
return true;
|
|
return false;
|
|
}
|
|
final function SpawnHelper()
|
|
{
|
|
local class<KFPawn_Monster> MC;
|
|
local byte i;
|
|
local vector V;
|
|
local rotator R;
|
|
local Controller C;
|
|
local Ext_T_MonsterPRI PRI;
|
|
local AkBaseSoundObject TempSound;
|
|
local bool bFinalWave;
|
|
|
|
if( PawnOwner.PlayerReplicationInfo==None || !HasLiveZeds() )
|
|
{
|
|
RespawnHelperTime = 3;
|
|
return;
|
|
}
|
|
NoLiveCounter = 5;
|
|
bFinalWave = KFGameReplicationInfo(WorldInfo.GRI).IsFinalWave();
|
|
if( bFinalWave && Class<KFPawn_MonsterBoss>(PrevMonster)!=None )
|
|
PrevMonster = None;
|
|
MC = (PrevMonster!=None ? PrevMonster : PickRandomMonster(CurLevel,bFinalWave));
|
|
|
|
if( MC!=None )
|
|
{
|
|
R.Yaw = Rand(65536);
|
|
if( MC.Default.SoundGroupArch!=None )
|
|
{
|
|
// Make no entrance roam (for FP's and Scrakes).
|
|
TempSound = MC.Default.SoundGroupArch.EntranceSound;
|
|
MC.Default.SoundGroupArch.EntranceSound = None;
|
|
}
|
|
for( i=0; i<40; ++i )
|
|
{
|
|
V = PawnOwner.Location;
|
|
V.X += (FRand()*300.f-150.f);
|
|
V.Y += (FRand()*300.f-150.f);
|
|
if( !PawnOwner.FastTrace(V,PawnOwner.Location) )
|
|
continue;
|
|
LiveHelper = Spawn(MC,,,V,R);
|
|
if( LiveHelper!=None )
|
|
break;
|
|
}
|
|
if( MC.Default.SoundGroupArch!=None )
|
|
MC.Default.SoundGroupArch.EntranceSound = TempSound;
|
|
}
|
|
if( LiveHelper==None )
|
|
RespawnHelperTime = 2;
|
|
else
|
|
{
|
|
// Downscale.
|
|
LiveHelper.SetDrawScale(LiveHelper.DrawScale*FriendlyScalar);
|
|
LiveHelper.SetCollisionSize(LiveHelper.GetCollisionRadius()*FriendlyScalar,LiveHelper.GetCollisionHeight()*FriendlyScalar);
|
|
|
|
// Setup AI
|
|
C = Spawn(LiveHelper.ControllerClass);
|
|
if( KFAIController(C)!=None )
|
|
{
|
|
KFAIController(C).bCanTeleportCloser = false;
|
|
KFAIController(C).DefaultCommandClass = class'Ext_AICommandBasePet';
|
|
KFAIController(C).StuckCheckInterval = 100000.f; // ~27 hours
|
|
KFAIController(C).LastStuckCheckTime = WorldInfo.TimeSeconds;
|
|
}
|
|
LiveHelper.SpecialMoveHandler.SpecialMoveClasses[SM_Taunt] = class'Ext_AINoTaunt';
|
|
C.Possess(LiveHelper,false);
|
|
|
|
// Set HP.
|
|
LiveHelper.HealthMax = Clamp(LiveHelper.Default.Health,180,900)*HPScale;
|
|
LiveHelper.Health = LiveHelper.HealthMax;
|
|
LiveHelper.DamageScaling = DamageScale;
|
|
LiveHelper.SetWeakGrabCoolDown(28800.f); // Never get grabbed (for 80 hours).
|
|
LiveHelper.bWeakZedGrab = true;
|
|
LiveHelper.bCanGrabAttack = false;
|
|
|
|
// Scale by previous zed HP.
|
|
if( PrevMonster!=None )
|
|
{
|
|
LiveHelper.Health *= PrevMonsterHP;
|
|
PrevMonster = None;
|
|
}
|
|
|
|
// Setup PRI.
|
|
if( C.PlayerReplicationInfo!=None )
|
|
C.PlayerReplicationInfo.Destroy();
|
|
PRI = Spawn(class'Ext_T_MonsterPRI',LiveHelper);
|
|
LiveHelper.PlayerReplicationInfo = PRI;
|
|
C.PlayerReplicationInfo = PRI;
|
|
PRI.PawnOwner = LiveHelper;
|
|
PRI.HealthMax = LiveHelper.HealthMax;
|
|
PRI.MonsterName = Class'KFExtendedHUD'.Static.GetNameOf(MC);
|
|
PRI.OwnerPRI = PawnOwner.PlayerReplicationInfo;
|
|
PRI.MonsterType = MC;
|
|
PRI.PlayerName = PawnOwner.PlayerReplicationInfo.PlayerName$"'s "$PRI.MonsterName;
|
|
PRI.OwnerController = PawnOwner.Controller;
|
|
if( PawnOwner.PlayerReplicationInfo.Team!=None )
|
|
PawnOwner.PlayerReplicationInfo.Team.AddToTeam(C);
|
|
PRI.Timer();
|
|
if( WorldInfo.NetMode!=NM_DedicatedServer )
|
|
PRI.NotifyOwner();
|
|
}
|
|
}
|
|
|
|
final function SetDamageScale( float Sc )
|
|
{
|
|
DamageScale = Default.DamageScale*Sc;
|
|
if( LiveHelper!=None )
|
|
LiveHelper.DamageScaling = DamageScale;
|
|
}
|
|
final function SetHealthScale( float Sc )
|
|
{
|
|
HPScale = Default.HPScale*Sc;
|
|
}
|
|
|
|
static final function LoadMonsterList()
|
|
{
|
|
local int i,j;
|
|
local array<string> SA;
|
|
local class<KFPawn_Monster> C;
|
|
|
|
Default.ZedTypes.Length = class'Ext_TraitZED_Summon'.Default.ZedTypes.Length;
|
|
|
|
for( i=0; i<Default.ZedTypes.Length; ++i )
|
|
{
|
|
SA.Length = 0;
|
|
ParseStringIntoArray(class'Ext_TraitZED_Summon'.Default.ZedTypes[i],SA,",",true);
|
|
|
|
for( j=0; j<SA.Length; ++j )
|
|
{
|
|
C = class<KFPawn_Monster>(DynamicLoadObject(SA[j],Class'Class'));
|
|
if( C==None )
|
|
continue;
|
|
Default.ZedTypes[i].Zeds[Default.ZedTypes[i].Zeds.Length] = C;
|
|
}
|
|
if( Default.ZedTypes[i].Zeds.Length==0 )
|
|
Default.ZedTypes[i].Zeds[Default.ZedTypes[i].Zeds.Length] = Class'KFPawn_ZedClot_Alpha';
|
|
}
|
|
}
|
|
static final function class<KFPawn_Monster> PickRandomMonster( byte Level, bool bNotBoss )
|
|
{
|
|
local byte i;
|
|
local class<KFPawn_Monster> Res;
|
|
|
|
Level = Min(Default.ZedTypes.Length-1,Level);
|
|
for( i=0; i<5; ++i )
|
|
{
|
|
Res = Default.ZedTypes[Level].Zeds[Rand(Default.ZedTypes[Level].Zeds.Length)];
|
|
if( !bNotBoss || class<KFPawn_MonsterBoss>(Res)==None )
|
|
break;
|
|
}
|
|
if( bNotBoss && class<KFPawn_MonsterBoss>(Res)!=None )
|
|
Res = Class'KFPawn_ZedFleshpound';
|
|
return Res;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
RespawnHelperTime=1
|
|
HPScale=0.5
|
|
DamageScale=2
|
|
FriendlyScalar=0.65
|
|
} |