Prepare fixtures
This commit is contained in:
parent
797e5ea192
commit
9c94356263
6021 changed files with 722805 additions and 22 deletions
9
kf_sources/ScrnZedPack/Classes/BlockHitEmitter.uc
Normal file
9
kf_sources/ScrnZedPack/Classes/BlockHitEmitter.uc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
class BlockHitEmitter extends MetalHitEmitter;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ImpactSounds(0)=None
|
||||
ImpactSounds(1)=None
|
||||
ImpactSounds(2)=None
|
||||
RemoteRole=ROLE_SimulatedProxy
|
||||
}
|
||||
14
kf_sources/ScrnZedPack/Classes/BrainDeadFemaleFP.uc
Normal file
14
kf_sources/ScrnZedPack/Classes/BrainDeadFemaleFP.uc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// for debugging
|
||||
class BrainDeadFemaleFP extends FemaleFP;
|
||||
|
||||
event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
SetMovementPhysics();
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ControllerClass=None
|
||||
}
|
||||
52
kf_sources/ScrnZedPack/Classes/BruteAvoidArea.uc
Normal file
52
kf_sources/ScrnZedPack/Classes/BruteAvoidArea.uc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
class BruteAvoidArea extends AvoidMarker;
|
||||
|
||||
var KFMonster KFMonst; // Should be the same as base and owner
|
||||
|
||||
state BigMeanAndScary
|
||||
{
|
||||
Begin:
|
||||
StartleBots();
|
||||
Sleep(1.0);
|
||||
GoTo('Begin');
|
||||
}
|
||||
|
||||
function InitFor(KFMonster V)
|
||||
{
|
||||
if (V != None)
|
||||
{
|
||||
KFMonst = V;
|
||||
SetCollisionSize(KFMonst.CollisionRadius * 3, KFMonst.CollisionHeight + CollisionHeight);
|
||||
SetBase(KFMonst);
|
||||
GoToState('BigMeanAndScary');
|
||||
}
|
||||
}
|
||||
|
||||
function Touch( actor Other )
|
||||
{
|
||||
if ( (Pawn(Other) != None) && RelevantTo(Pawn(Other)) )
|
||||
KFMonsterController(Pawn(Other).Controller).AvoidThisMonster(KFMonst);
|
||||
}
|
||||
|
||||
function bool RelevantTo(Pawn P)
|
||||
{
|
||||
return ( KFMonst != none && VSizeSquared(KFMonst.Velocity) >= 75 && Super.RelevantTo(P)
|
||||
&& KFMonst.Velocity dot (P.Location - KFMonst.Location) > 0 );
|
||||
}
|
||||
|
||||
function StartleBots()
|
||||
{
|
||||
local KFMonster P;
|
||||
|
||||
if (KFMonst != None)
|
||||
ForEach CollidingActors(class'KFMonster', P, CollisionRadius)
|
||||
if (RelevantTo(P))
|
||||
KFMonsterController(P.Controller).AvoidThisMonster(KFMonst);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
CollisionRadius=1000.000000
|
||||
bBlockZeroExtentTraces=False
|
||||
bBlockNonZeroExtentTraces=False
|
||||
bBlockHitPointTraces=False
|
||||
}
|
||||
69
kf_sources/ScrnZedPack/Classes/BruteZombieController.uc
Normal file
69
kf_sources/ScrnZedPack/Classes/BruteZombieController.uc
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
class BruteZombieController extends KFMonsterController;
|
||||
|
||||
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
|
||||
|
||||
function TimedFireWeaponAtEnemy()
|
||||
{
|
||||
if ( (Enemy == None) || FireWeaponAt(Enemy) )
|
||||
SetCombatTimer();
|
||||
else
|
||||
SetTimer(0.01, True);
|
||||
}
|
||||
|
||||
state ZombieCharge
|
||||
{
|
||||
function Tick(float Delta)
|
||||
{
|
||||
local ZombieBrute ZFP;
|
||||
Global.Tick(Delta);
|
||||
|
||||
// Bored, get angry
|
||||
if (RageFrustrationTimer < RageFrustrationThreshhold)
|
||||
{
|
||||
RageFrustrationTimer += Delta;
|
||||
|
||||
if (RageFrustrationTimer >= RageFrustrationThreshhold)
|
||||
{
|
||||
ZFP = ZombieBrute(Pawn);
|
||||
|
||||
if( ZFP != none && !ZFP.bChargingPlayer )
|
||||
{
|
||||
ZFP.StartCharging();
|
||||
ZFP.bFrustrated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool StrafeFromDamage(float Damage, class<DamageType> DamageType, bool bFindDest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function bool TryStrafe(vector sideDir)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function Timer()
|
||||
{
|
||||
Disable('NotifyBump');
|
||||
Target = Enemy;
|
||||
TimedFireWeaponAtEnemy();
|
||||
}
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
super.BeginState();
|
||||
|
||||
RageFrustrationThreshhold = default.RageFrustrationThreshhold + (Frand() * 5);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RageFrustrationThreshhold=10.000000
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/DamTypeEMP.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/DamTypeEMP.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class DamTypeEMP extends DamTypeTesla;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DeathString="%o watched %k's Self-Destruct Sequence too close."
|
||||
}
|
||||
10
kf_sources/ScrnZedPack/Classes/DamTypeTesla.uc
Normal file
10
kf_sources/ScrnZedPack/Classes/DamTypeTesla.uc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
class DamTypeTesla extends DamTypeZombieAttack;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bCheckForHeadShots=False
|
||||
DeathString="%o accepts %k's shaft."
|
||||
FemaleSuicide="%o rode the lighting."
|
||||
MaleSuicide="%o rode the lighting."
|
||||
bLocationalHit=False
|
||||
}
|
||||
125
kf_sources/ScrnZedPack/Classes/FFPController.uc
Normal file
125
kf_sources/ScrnZedPack/Classes/FFPController.uc
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//-----------------------------------------------------------
|
||||
//Still behaves like a Fleshpound for the most part, although quicker to rage.
|
||||
//Thanks to Scary for the work on this one. - Whisky
|
||||
//-----------------------------------------------------------
|
||||
class FFPController extends FleshpoundZombieController;
|
||||
|
||||
var bool bFindNewEnemy, bSmashDoor, bStartled, bAttackedTarget, bMissTarget;
|
||||
var float prevRageTimer,prevRageThreshold;
|
||||
|
||||
//I fear nothing but you WILL fear me!!
|
||||
//FFP will not bother trying to avoid nades when raged, prevents players from using their nades to stop her in a door.
|
||||
//(I know because as a medic I was doing it all the time. - Whisky)
|
||||
function FearThisSpot(AvoidMarker aSpot)
|
||||
{
|
||||
local FemaleFP FFP;
|
||||
FFP = FemaleFP(Pawn);
|
||||
|
||||
if (!FFP.bChargingPlayer)
|
||||
{
|
||||
if ( Skill > 1 + 2.0 * FRand() )
|
||||
super(Controller).FearThisSpot(aSpot);
|
||||
}
|
||||
}
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
prevRageThreshold= default.RageFrustrationThreshhold + (Frand() * 5);
|
||||
}
|
||||
|
||||
function bool FindNewEnemy()
|
||||
{
|
||||
bFindNewEnemy= true;
|
||||
return super.FindNewEnemy();
|
||||
}
|
||||
|
||||
function BreakUpDoor(KFDoorMover Other, bool bTryDistanceAttack)
|
||||
{
|
||||
bSmashDoor= true;
|
||||
super.BreakUpDoor(Other,bTryDistanceAttack);
|
||||
}
|
||||
|
||||
function Startle(Actor Feared)
|
||||
{
|
||||
bStartled= True;
|
||||
super.Startle(Feared);
|
||||
}
|
||||
|
||||
state SpinAttack
|
||||
{
|
||||
ignores EnemyNotVisible, GetOutOfTheWayOfShot;
|
||||
|
||||
function DoSpinDamage()
|
||||
{
|
||||
local Actor A;
|
||||
|
||||
//log("FLESHPOUND DOSPINDAMAGE!");
|
||||
foreach CollidingActors(class'actor', A, (KFM.MeleeRange * 1.5)+pawn.CollisionRadius, pawn.Location)
|
||||
FemaleFP(pawn).SpinDamage(A);
|
||||
}
|
||||
|
||||
Begin:
|
||||
|
||||
WaitForAnim:
|
||||
While( KFM.bShotAnim )
|
||||
{
|
||||
Sleep(0.1);
|
||||
DoSpinDamage();
|
||||
}
|
||||
|
||||
WhatToDoNext(152);
|
||||
if ( bSoaking )
|
||||
SoakStop("STUCK IN SPINATTACK!!!");
|
||||
}
|
||||
|
||||
state ZombieCharge
|
||||
{
|
||||
function BeginState()
|
||||
{
|
||||
super.BeginState();
|
||||
|
||||
if (!bSmashDoor && ((bAttackedTarget && bMissTarget) || bFindNewEnemy || bStartled))
|
||||
{
|
||||
RageFrustrationTimer= prevRageTimer;
|
||||
RageFrustrationThreshhold= prevRageThreshold;
|
||||
}
|
||||
bFindNewEnemy= false;
|
||||
bSmashDoor= false;
|
||||
bStartled= false;
|
||||
bAttackedTarget= false;
|
||||
bMissTarget= false;
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
prevRageTimer= RageFrustrationTimer;
|
||||
prevRageThreshold= RageFrustrationThreshhold;
|
||||
}
|
||||
|
||||
function Tick( float Delta )
|
||||
{
|
||||
local FemaleFP FFP;
|
||||
|
||||
Global.Tick(Delta);
|
||||
|
||||
// Make the FP rage if we haven't reached our enemy after a certain amount of time
|
||||
if( RageFrustrationTimer < RageFrustrationThreshhold ) {
|
||||
RageFrustrationTimer += Delta;
|
||||
|
||||
if( RageFrustrationTimer >= RageFrustrationThreshhold ) {
|
||||
FFP = FemaleFP(Pawn);
|
||||
|
||||
if( FFP != none && !FFP.bChargingPlayer ) {
|
||||
FFP.StartCharging();
|
||||
FFP.bFrustrated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RageFrustrationThreshhold=30.000000
|
||||
}
|
||||
61
kf_sources/ScrnZedPack/Classes/FFPKarma.uc
Normal file
61
kf_sources/ScrnZedPack/Classes/FFPKarma.uc
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
This object is used to load bRagdolls config variable
|
||||
Clients, who have no config (and probabaly have no karma data),
|
||||
will have karma ragdoll death animations turned off.
|
||||
|
||||
@author PooSH
|
||||
@author Marco
|
||||
*/
|
||||
|
||||
Class FFPKarma extends Object
|
||||
Config(FemaleFPMut)
|
||||
PerObjectConfig;
|
||||
|
||||
var config bool bRagdolls;
|
||||
var config bool bAutoDetect;
|
||||
|
||||
var private bool bHasInit,bRagdoll;
|
||||
|
||||
static final function InitConfig(LevelInfo Level)
|
||||
{
|
||||
local FFPKarma D;
|
||||
|
||||
Default.bHasInit = true;
|
||||
|
||||
if ( Level.NetMode == NM_DedicatedServer ) {
|
||||
Default.bRagdoll = false;
|
||||
}
|
||||
else if ( Level.PlatformIsWindows() ) {
|
||||
// DIR command doesn't work on Linux. Not sure about MacOS
|
||||
Default.bRagdoll = Level.GetLocalPlayerController().ConsoleCommand("DIR ../KarmaData/FFPKarma.ka") ~= "FFPKarma.ka";
|
||||
}
|
||||
else {
|
||||
// read from config. create config file, if it doesn't exist
|
||||
D = New(None,"FemaleFPKarma") Class'FFPKarma';
|
||||
Default.bRagdoll = D.bRagdolls;
|
||||
if ( Level.PlatformIsWindows() ) {
|
||||
if ( Level.GetLocalPlayerController().ConsoleCommand("DIR ../KarmaData/FFPKarma.ka") ~= "FFPKarma.ka" ) {
|
||||
// karma file exists
|
||||
if ( default.bAutoDetect )
|
||||
Default.bRagdolls = true; // enable it in config for the next use, but don't enable it now. For cases, when karma file is obtained via MusicLoader
|
||||
}
|
||||
else {
|
||||
// karma file doesn't exist - disable ragdoll animations
|
||||
Default.bRagdolls = false;
|
||||
Default.bRagdoll = false;
|
||||
}
|
||||
}
|
||||
D.SaveConfig();
|
||||
}
|
||||
}
|
||||
static final function bool UseRagdoll(LevelInfo Level)
|
||||
{
|
||||
if( !Default.bHasInit )
|
||||
InitConfig(Level);
|
||||
return Default.bRagdoll;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bAutoDetect=True
|
||||
}
|
||||
88
kf_sources/ScrnZedPack/Classes/FFPVentEmitter.uc
Normal file
88
kf_sources/ScrnZedPack/Classes/FFPVentEmitter.uc
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
class FFPVentEmitter extends VehicleExhaustEffect;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MaxSpritePPSOne=20
|
||||
MaxSpritePPSTwo=22
|
||||
IdleSpritePPSOne=5
|
||||
IdleSpritePPSTwo=7
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter1
|
||||
FadeOut=True
|
||||
FadeIn=True
|
||||
SpinParticles=True
|
||||
UseSizeScale=True
|
||||
UseRegularSizeScale=False
|
||||
UniformSize=True
|
||||
BlendBetweenSubdivisions=True
|
||||
UseRandomSubdivision=True
|
||||
UseVelocityScale=True
|
||||
Acceleration=(X=70.000000,Z=20.000000)
|
||||
ColorScale(0)=(Color=(B=255,G=255,R=255,A=50))
|
||||
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255))
|
||||
FadeOutStartTime=0.100000
|
||||
MaxParticles=20
|
||||
UseRotationFrom=PTRS_Actor
|
||||
SpinsPerSecondRange=(X=(Min=-0.075000,Max=0.075000))
|
||||
SizeScale(0)=(RelativeSize=0.500000)
|
||||
SizeScale(1)=(RelativeTime=0.070000,RelativeSize=0.500000)
|
||||
SizeScale(2)=(RelativeTime=0.370000,RelativeSize=1.100000)
|
||||
SizeScale(3)=(RelativeTime=1.000000,RelativeSize=2.500000)
|
||||
StartSizeRange=(X=(Min=15.000000,Max=30.000000))
|
||||
InitialParticlesPerSecond=5.000000
|
||||
DrawStyle=PTDS_AlphaBlend
|
||||
Texture=Texture'Effects_Tex.Vehicles.Gasoline_Smoke'
|
||||
TextureUSubdivisions=2
|
||||
TextureVSubdivisions=2
|
||||
SecondsBeforeInactive=0.000000
|
||||
LifetimeRange=(Min=0.200000,Max=0.300000)
|
||||
StartVelocityRange=(X=(Min=45.000000,Max=300.000000),Y=(Min=-45.000000,Max=45.000000),Z=(Min=-45.000000,Max=45.000000))
|
||||
VelocityScale(0)=(RelativeVelocity=(X=1.000000,Y=1.000000,Z=1.000000))
|
||||
VelocityScale(1)=(RelativeTime=0.300000,RelativeVelocity=(X=0.200000,Y=1.000000,Z=1.000000))
|
||||
VelocityScale(2)=(RelativeTime=1.000000,RelativeVelocity=(Y=0.400000,Z=0.400000))
|
||||
End Object
|
||||
Emitters(0)=SpriteEmitter'ScrnZedPack.FFPVentEmitter.SpriteEmitter1'
|
||||
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter2
|
||||
FadeOut=True
|
||||
FadeIn=True
|
||||
AutoReset=True
|
||||
SpinParticles=True
|
||||
UseSizeScale=True
|
||||
UseRegularSizeScale=False
|
||||
UniformSize=True
|
||||
BlendBetweenSubdivisions=True
|
||||
UseRandomSubdivision=True
|
||||
UseVelocityScale=True
|
||||
Acceleration=(X=70.000000,Z=20.000000)
|
||||
ColorScale(0)=(Color=(B=128,G=128,R=128,A=50))
|
||||
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255))
|
||||
FadeOutStartTime=0.100000
|
||||
MaxParticles=20
|
||||
AutoResetTimeRange=(Min=5.000000,Max=10.000000)
|
||||
UseRotationFrom=PTRS_Actor
|
||||
SpinsPerSecondRange=(X=(Min=-0.075000,Max=0.075000))
|
||||
SizeScale(0)=(RelativeSize=0.500000)
|
||||
SizeScale(1)=(RelativeTime=0.070000,RelativeSize=0.500000)
|
||||
SizeScale(2)=(RelativeTime=0.370000,RelativeSize=1.100000)
|
||||
SizeScale(3)=(RelativeTime=1.000000,RelativeSize=2.500000)
|
||||
StartSizeRange=(X=(Min=11.000000,Max=21.000000))
|
||||
InitialParticlesPerSecond=5.000000
|
||||
DrawStyle=PTDS_AlphaBlend
|
||||
Texture=Texture'Effects_Tex.Vehicles.Deisel_Smoke'
|
||||
TextureUSubdivisions=2
|
||||
TextureVSubdivisions=2
|
||||
SecondsBeforeInactive=0.000000
|
||||
LifetimeRange=(Min=0.200000,Max=0.300000)
|
||||
StartVelocityRange=(X=(Min=45.000000,Max=300.000000),Y=(Min=-10.000000,Max=10.000000),Z=(Min=-10.000000,Max=10.000000))
|
||||
VelocityScale(0)=(RelativeVelocity=(X=1.000000,Y=1.000000,Z=1.000000))
|
||||
VelocityScale(1)=(RelativeTime=0.400000,RelativeVelocity=(X=0.150000,Y=1.000000,Z=1.000000))
|
||||
VelocityScale(2)=(RelativeTime=1.000000,RelativeVelocity=(Y=0.400000,Z=0.400000))
|
||||
End Object
|
||||
Emitters(1)=SpriteEmitter'ScrnZedPack.FFPVentEmitter.SpriteEmitter2'
|
||||
|
||||
AutoDestroy=True
|
||||
bNetTemporary=True
|
||||
LifeSpan=8.000000
|
||||
bHardAttach=False
|
||||
bDirectional=True
|
||||
}
|
||||
982
kf_sources/ScrnZedPack/Classes/FemaleFP.uc
Normal file
982
kf_sources/ScrnZedPack/Classes/FemaleFP.uc
Normal file
|
|
@ -0,0 +1,982 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// Female Flesh Pound
|
||||
// A more dainty and gentle fleshpound... pfft! NOT!
|
||||
// Written by Whisky & Poosh, (Although it's mostly TWI's code in the first place.)
|
||||
// Scary Ghost's code used with permission.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FemaleFP extends KFMonster;
|
||||
|
||||
#exec load obj file=ScrnZedPack_T.utx
|
||||
#exec load obj file=ScrnZedPack_S.uax
|
||||
#exec load obj file=ScrnZedPack_A.ukx
|
||||
|
||||
var transient bool bChargingPlayer,bClientCharge,bFrustrated,bNeedVent;
|
||||
var transient bool bRageFirstHit; //did she hit a player during current rage run
|
||||
var float RageEndTime;
|
||||
var FleshPoundAvoidArea AvoidArea;
|
||||
var name ChargingAnim;
|
||||
|
||||
var() class<VehicleExhaustEffect> VentEffectClass; // Effect class for the vent emitter
|
||||
var() VehicleExhaustEffect VentEffect,VentEffect2; //Dual venting baby!
|
||||
var() float BlockDamageReduction;
|
||||
var() vector RotMag;
|
||||
var() vector RotRate;
|
||||
var() float RotTime;
|
||||
var() vector OffsetMag;
|
||||
var() vector OffsetRate;
|
||||
var() float OffsetTime;
|
||||
var() int RageDamageThreshold;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if(Role==ROLE_Authority)
|
||||
bChargingPlayer,bFrustrated, bNeedVent;
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
|
||||
if( ROLE==ROLE_Authority ) {
|
||||
StunsRemaining = fmax(7 - Level.Game.GameDifficulty, 1);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PostNetBeginPlay()
|
||||
{
|
||||
if(AvoidArea==None)
|
||||
AvoidArea=Spawn(class'FleshPoundAvoidArea',self);
|
||||
if(AvoidArea!=None)
|
||||
AvoidArea.InitFor(Self);
|
||||
|
||||
EnableChannelNotify(1,1);
|
||||
AnimBlendParams(1,1.0,0.0,,SpineBone2);
|
||||
super.PostNetBeginPlay();
|
||||
}
|
||||
|
||||
|
||||
// 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('ChargeToMarker') )
|
||||
{
|
||||
GotoState('ChargeToMarker');
|
||||
}
|
||||
else
|
||||
{
|
||||
NumZCDHits = 1;
|
||||
if( IsInState('ChargeToMarker') )
|
||||
{
|
||||
GotoState('');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( IsInState('ChargeToMarker') )
|
||||
{
|
||||
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( bChargingPlayer && NumZCDHits > 1 )
|
||||
{
|
||||
GotoState('ChargeToMarker');
|
||||
}
|
||||
else
|
||||
{
|
||||
GotoState('');
|
||||
}
|
||||
}
|
||||
|
||||
function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamageType)
|
||||
{
|
||||
if( Level.TimeSeconds - LastPainAnim < MinTimeBetweenPainAnims )
|
||||
return;
|
||||
|
||||
if ( Controller.IsInState('WaitForAnim') )
|
||||
return; // Don't interrupt the controller if its waiting for an animation to end
|
||||
|
||||
if( StunsRemaining > 0 && Damage>=100 )
|
||||
PlayDirectionalHit(HitLocation);
|
||||
|
||||
LastPainAnim = Level.TimeSeconds;
|
||||
|
||||
if( Level.TimeSeconds - LastPainSound < MinTimeBetweenPainSounds )
|
||||
return;
|
||||
|
||||
LastPainSound = Level.TimeSeconds;
|
||||
PlaySound(HitSound[0], SLOT_Pain,1.25,,400);
|
||||
}
|
||||
|
||||
//Taken from ScaryGhost's SuperFP.
|
||||
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
|
||||
{
|
||||
local bool didIHit;
|
||||
|
||||
didIHit= super.MeleeDamageTarget(hitdamage, pushdir);
|
||||
FFPController(Controller).bMissTarget=
|
||||
FFPController(Controller).bMissTarget || !didIHit;
|
||||
return didIHit;
|
||||
}
|
||||
|
||||
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
local int OldHealth;
|
||||
local bool bIsHeadShot;
|
||||
local float HeadShotCheckScale;
|
||||
local class<KFWeaponDamageType> KFDamType;
|
||||
|
||||
// optimizes typecasting and make code comre compact -- PooSH
|
||||
KFDamType = class<KFWeaponDamageType>(damageType);
|
||||
oldHealth= Health;
|
||||
|
||||
if ( KFDamType != none )
|
||||
{
|
||||
HeadShotCheckScale = 1.0;
|
||||
// Do larger headshot checks if it is a melee attach
|
||||
if( class<DamTypeMelee>(damageType) != none )
|
||||
HeadShotCheckScale *= 1.25;
|
||||
bIsHeadShot = IsHeadShot(Hitlocation, normal(Momentum), 1.0);
|
||||
|
||||
// She takes less damage to small arms fire (non explosives)
|
||||
// Frags and LAW rockets will bring her down way faster than bullets and shells.
|
||||
if ( !KFDamType.default.bIsExplosive ) // all explosives: current, future and custom -- PooSH
|
||||
{
|
||||
// Don't reduce the damage so much if its a high headshot damage weapon
|
||||
if( bIsHeadShot && KFDamType.default.HeadShotDamageMult >= 1.5 )
|
||||
{
|
||||
Damage *= 0.75;
|
||||
}
|
||||
else if ( Level.Game.GameDifficulty >= 5.0 && bIsHeadshot
|
||||
&& (ClassIsChildOf(KFDamType, class'DamTypeCrossbow')
|
||||
|| ClassIsChildOf(KFDamType, class'DamTypeM99SniperRifle')) )
|
||||
{
|
||||
Damage *= 0.35; // 65% damage reduction from xbow/m99 headshots
|
||||
}
|
||||
else
|
||||
{
|
||||
Damage *= 0.5;
|
||||
}
|
||||
}
|
||||
// include subclasses = care about modders (c) PooSH
|
||||
// Can't check subclasses of DamTypeFrag, because LAW is one of them
|
||||
else if ( KFDamType == class'DamTypeFrag' || ClassIsChildOf(KFDamType, class'DamTypePipeBomb') )
|
||||
{
|
||||
Damage *= 1.25;
|
||||
}
|
||||
// M32 and SP are subclasses of DamTypeM79Grenade, so no need to additionally check those -- PooSH
|
||||
else if( ClassIsChildOf(KFDamType, class'DamTypeM79Grenade')
|
||||
|| ClassIsChildOf(KFDamType, class'DamTypeM203Grenade') )
|
||||
{
|
||||
Damage *= 1.25;
|
||||
}
|
||||
}
|
||||
|
||||
// Shut off his "Device" when dead
|
||||
if (Damage >= Health)
|
||||
PostNetReceive();
|
||||
|
||||
|
||||
if (damageType == class 'DamTypeVomit')
|
||||
Damage = 0; // nulled
|
||||
|
||||
// fixes none-reference erros when taking enviromental damage -- PooSH
|
||||
if (InstigatedBy == none || KFDamType == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, damageType); // skip NONE-reference error
|
||||
else
|
||||
super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, damageType);
|
||||
|
||||
|
||||
Damage = OldHealth - Health;
|
||||
|
||||
// Starts charging if single damage > 300 or health drops below 50% on hard difficulty or below,
|
||||
// or health <75% on Suicidal/HoE
|
||||
// -- PooSH
|
||||
if ( Health > 0 && !bDecapitated && !bChargingPlayer
|
||||
&& !bZapped && (!(bCrispified && bBurnified) || bFrustrated)
|
||||
&& (Damage > RageDamageThreshold || Health < HealthMax*0.5
|
||||
|| (Level.Game.GameDifficulty >= 5.0 && Health < HealthMax*0.75)) )
|
||||
StartCharging();
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if ( bShotAnim || Physics == PHYS_Swimming)
|
||||
return;
|
||||
else if ( CanAttack(A) )
|
||||
{
|
||||
bShotAnim = true;
|
||||
SetAnimAction('Claw');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Need to add sound!
|
||||
simulated function SpawnVentEmitter()
|
||||
{
|
||||
if ( VentEffectClass != none )
|
||||
{
|
||||
if ( VentEffect == none ) {
|
||||
VentEffect = Spawn(VentEffectClass, self);
|
||||
AttachToBone(VentEffect, 'BODY_Piston_top_Camisa_l');
|
||||
VentEffect.SetRelativeRotation(rot(0, 0, 0));
|
||||
}
|
||||
if ( VentEffect2 == none ) {
|
||||
VentEffect2 = Spawn(VentEffectClass, self);
|
||||
AttachToBone(VentEffect2, 'BODY_Piston_top_Camisa_r');
|
||||
}
|
||||
}
|
||||
else
|
||||
bNeedVent = false;
|
||||
}
|
||||
|
||||
|
||||
//Clean up of effects.
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
StopVenting();
|
||||
super.Died( Killer, damageType, HitLocation );
|
||||
}
|
||||
|
||||
simulated function VentMe()
|
||||
{
|
||||
//Level.GetLocalPlayerController().ClientMessage("VentMe");
|
||||
//Log("AAAAAARRRRRRROOOOOOOOOOOOOOGGGGGAAAAAAAAA!!");
|
||||
bNeedVent = true;
|
||||
SpawnVentEmitter();
|
||||
}
|
||||
|
||||
simulated function StopVenting()
|
||||
{
|
||||
bNeedVent = false;
|
||||
if ( VentEffect != none )
|
||||
{
|
||||
VentEffect.Destroy();
|
||||
VentEffect = none;
|
||||
}
|
||||
if ( VentEffect2 != none )
|
||||
{
|
||||
VentEffect2.Destroy();
|
||||
VentEffect2 = none;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the FFP in a berserk charge state until she either strikes her target, or hits timeout
|
||||
function StartCharging()
|
||||
{
|
||||
local float RageAnimDur;
|
||||
|
||||
if( Health <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetAnimAction('Rage_Start');
|
||||
Acceleration = vect(0,0,0);
|
||||
bShotAnim = true;
|
||||
Velocity.X = 0;
|
||||
Velocity.Y = 0;
|
||||
Controller.GoToState('WaitForAnim');
|
||||
KFMonsterController(Controller).bUseFreezeHack = True;
|
||||
RageAnimDur = GetAnimDuration('Rage_Start');
|
||||
FleshpoundZombieController(Controller).SetPoundRageTimout(RageAnimDur);
|
||||
GoToState('BeginRaging');
|
||||
}
|
||||
|
||||
state BeginRaging
|
||||
{
|
||||
Ignores StartCharging;
|
||||
|
||||
// Set the zed to the zapped behavior
|
||||
simulated function SetZappedBehavior()
|
||||
{
|
||||
Global.SetZappedBehavior();
|
||||
GoToState('');
|
||||
}
|
||||
|
||||
function bool CanGetOutOfWay()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool HitCanInterruptAction()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function Tick( float Delta )
|
||||
{
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
global.Tick(Delta);
|
||||
}
|
||||
|
||||
Begin:
|
||||
Sleep(GetAnimDuration('Rage_Start'));
|
||||
GotoState('RageCharging');
|
||||
}
|
||||
|
||||
|
||||
simulated function SetBurningBehavior()
|
||||
{
|
||||
if( bFrustrated || bChargingPlayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
super.SetBurningBehavior();
|
||||
}
|
||||
|
||||
//Next two States are Scary's Code.
|
||||
state RageCharging
|
||||
{
|
||||
Ignores StartCharging;
|
||||
// Set the zed to the zapped behavior
|
||||
simulated function SetZappedBehavior()
|
||||
{
|
||||
Global.SetZappedBehavior();
|
||||
GoToState('');
|
||||
}
|
||||
|
||||
function PlayDirectionalHit(Vector HitLoc)
|
||||
{
|
||||
if( !bShotAnim )
|
||||
{
|
||||
super.PlayDirectionalHit(HitLoc);
|
||||
}
|
||||
}
|
||||
|
||||
function bool CanGetOutOfWay()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't override speed in this state
|
||||
function bool CanSpeedAdjust()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
local float DifficultyModifier;
|
||||
|
||||
bRageFirstHit = false;
|
||||
|
||||
if( bZapped )
|
||||
{
|
||||
GoToState('');
|
||||
}
|
||||
else
|
||||
{
|
||||
bChargingPlayer = true;
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
ClientChargingAnims();
|
||||
|
||||
// Scale rage length by difficulty
|
||||
if( Level.Game.GameDifficulty < 2.0 )
|
||||
{
|
||||
DifficultyModifier = 0.85;
|
||||
}
|
||||
else if( Level.Game.GameDifficulty < 4.0 )
|
||||
{
|
||||
DifficultyModifier = 1.0;
|
||||
}
|
||||
else if( Level.Game.GameDifficulty < 5.0 )
|
||||
{
|
||||
DifficultyModifier = 1.25;
|
||||
}
|
||||
else // Hardest difficulty
|
||||
{
|
||||
DifficultyModifier = 3.0; // Doubled Fleshpound Rage time for Suicidal and HoE in Balance Round 1
|
||||
}
|
||||
|
||||
RageEndTime = Level.TimeSeconds + DifficultyModifier * (10.0 + 6.0*FRand());
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
bChargingPlayer = False;
|
||||
bFrustrated = false;
|
||||
|
||||
FleshPoundZombieController(Controller).RageFrustrationTimer = 0;
|
||||
StopVenting();
|
||||
|
||||
if( Health>0 && !bZapped )
|
||||
{
|
||||
SetGroundSpeed(GetOriginalGroundSpeed());
|
||||
}
|
||||
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
ClientChargingAnims();
|
||||
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
|
||||
function Tick( float Delta )
|
||||
{
|
||||
if( !bShotAnim )
|
||||
{
|
||||
SetGroundSpeed(OriginalGroundSpeed * 2.3);//2.0;
|
||||
if( !bFrustrated && !bZedUnderControl && Level.TimeSeconds>RageEndTime )
|
||||
{
|
||||
GoToState('');
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the flesh pound moving toward its target when attacking
|
||||
if( Role == ROLE_Authority && bShotAnim)
|
||||
{
|
||||
if( LookTarget!=None )
|
||||
{
|
||||
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
||||
}
|
||||
}
|
||||
|
||||
global.Tick(Delta);
|
||||
}
|
||||
|
||||
function Bump( Actor Other )
|
||||
{
|
||||
local float RageBumpDamage;
|
||||
local KFMonster KFMonst;
|
||||
|
||||
KFMonst = KFMonster(Other);
|
||||
|
||||
// Hurt/Kill enemies that we run into while raging
|
||||
if( !bShotAnim && KFMonst!=None && KFMonst.Health>0 && !SameSpeciesAs(self) )
|
||||
{
|
||||
// Random chance of doing obliteration damage
|
||||
if( FRand() < 0.4 )
|
||||
{
|
||||
RageBumpDamage = 501;
|
||||
}
|
||||
else
|
||||
{
|
||||
RageBumpDamage = 450;
|
||||
}
|
||||
|
||||
RageBumpDamage *= KFMonst.PoundRageBumpDamScale;
|
||||
|
||||
Other.TakeDamage(RageBumpDamage, self, Other.Location, Velocity * Other.Mass, class'DamTypePoundCrushed');
|
||||
}
|
||||
else Global.Bump(Other);
|
||||
}
|
||||
|
||||
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
|
||||
{
|
||||
local bool RetVal,bWasEnemy, bCalmDown;
|
||||
local float oldEnemyHealth;
|
||||
local bool bAttackingHuman;
|
||||
local KFPawn KFP;
|
||||
|
||||
|
||||
//Only rage again if he was attacking a human
|
||||
KFP = KFPawn(Controller.Target);
|
||||
bAttackingHuman = KFP != none;
|
||||
if (bAttackingHuman)
|
||||
oldEnemyHealth= KFP.Health;
|
||||
|
||||
bWasEnemy = (Controller.Target==Controller.Enemy);
|
||||
if ( !bRageFirstHit )
|
||||
hitdamage *= 1.5; // first rage hit doesn more damage, down from 1.75 to 1.5 in v091 -- PooSH
|
||||
RetVal = Super(KFMonster).MeleeDamageTarget(hitdamage, pushdir*3);
|
||||
|
||||
if ( bAttackingHuman || bWasEnemy )
|
||||
bRageFirstHit = true; //she had a chance to do a greater damage. If she missed - her fault
|
||||
|
||||
if(RetVal && bWasEnemy)
|
||||
{
|
||||
// On Hard and below she always calms down, no matter of was hit successful or not
|
||||
// On Suicidal she calms down after successfull hit
|
||||
// On HoE she calms down only if killed a player.
|
||||
if ( bAttackingHuman && Level.Game.GameDifficulty >= 5.0 ) {
|
||||
if ( Level.Game.GameDifficulty >= 7.0 )
|
||||
bCalmDown = KFP == none || KFP.Health <= 0;
|
||||
else
|
||||
bCalmDown = KFP == none || KFP.Health < oldEnemyHealth;
|
||||
}
|
||||
else {
|
||||
bCalmDown = true;
|
||||
}
|
||||
|
||||
if (bCalmDown)
|
||||
GoToState('');
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
state ChargeToMarker extends RageCharging
|
||||
{
|
||||
Ignores StartCharging;
|
||||
|
||||
function Tick( float Delta )
|
||||
{
|
||||
if( !bShotAnim )
|
||||
{
|
||||
SetGroundSpeed(OriginalGroundSpeed * 2.3);
|
||||
if( !bFrustrated && !bZedUnderControl && Level.TimeSeconds>RageEndTime )
|
||||
{
|
||||
GoToState('');
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the flesh pound moving toward its target when attacking
|
||||
if( Role == ROLE_Authority && bShotAnim)
|
||||
{
|
||||
if( LookTarget!=None )
|
||||
{
|
||||
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
||||
}
|
||||
}
|
||||
|
||||
global.Tick(Delta);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PostNetReceive()
|
||||
{
|
||||
super.PostNetReceive();
|
||||
|
||||
if( bClientCharge!=bChargingPlayer && !bZapped )
|
||||
{
|
||||
bClientCharge=bChargingPlayer;
|
||||
if( bChargingPlayer ) {
|
||||
MovementAnims[0]=ChargingAnim;
|
||||
MeleeAnims[0]='attack3';
|
||||
MeleeAnims[1]='attack3';
|
||||
MeleeAnims[2]='attack3';
|
||||
DeviceGoRed();
|
||||
}
|
||||
else {
|
||||
MovementAnims[0]=default.MovementAnims[0];
|
||||
MeleeAnims[0]=default.MeleeAnims[0];
|
||||
MeleeAnims[1]=default.MeleeAnims[1];
|
||||
MeleeAnims[2]=default.MeleeAnims[2];
|
||||
DeviceGoNormal();
|
||||
StopVenting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function ClientChargingAnims()
|
||||
{
|
||||
PostNetReceive();
|
||||
}
|
||||
|
||||
function ClawDamageTarget()
|
||||
{
|
||||
local vector PushDir;
|
||||
local KFHumanPawn HumanTarget;
|
||||
local KFPlayerController HumanTargetController;
|
||||
local float UsedMeleeDamage;
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
GetAnimParams( ExpectingChannel, Sequence, Frame, Rate );
|
||||
|
||||
if( MeleeDamage > 1 )
|
||||
{
|
||||
UsedMeleeDamage = (MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1));
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedMeleeDamage = MeleeDamage;
|
||||
}
|
||||
|
||||
// Reduce the melee damage for anims with repeated attacks, since it does repeated damage over time
|
||||
if( Sequence == 'Attack1' )
|
||||
{
|
||||
UsedMeleeDamage *= 0.5;
|
||||
}
|
||||
else if( Sequence == 'Attack2' )
|
||||
{
|
||||
UsedMeleeDamage *= 0.25;
|
||||
}
|
||||
|
||||
if(Controller!=none && Controller.Target!=none)
|
||||
{
|
||||
//calculate based on relative positions
|
||||
PushDir = (damageForce * Normal(Controller.Target.Location - Location));
|
||||
}
|
||||
else
|
||||
{
|
||||
//calculate based on way Monster is facing
|
||||
PushDir = damageForce * vector(Rotation);
|
||||
}
|
||||
if ( MeleeDamageTarget( UsedMeleeDamage, PushDir))
|
||||
{
|
||||
HumanTarget = KFHumanPawn(Controller.Target);
|
||||
if( HumanTarget!=None )
|
||||
HumanTargetController = KFPlayerController(HumanTarget.Controller);
|
||||
if( HumanTargetController!=None )
|
||||
HumanTargetController.ShakeView(RotMag, RotRate, RotTime, OffsetMag, OffsetRate, OffsetTime);
|
||||
PlaySound(MeleeAttackHitSound, SLOT_Interact, 1.25);
|
||||
}
|
||||
}
|
||||
|
||||
function SpinDamage(actor Target)
|
||||
{
|
||||
local vector HitLocation;
|
||||
local Float dummy;
|
||||
local float DamageAmount;
|
||||
local vector PushDir;
|
||||
local KFHumanPawn HumanTarget;
|
||||
|
||||
if(target==none)
|
||||
return;
|
||||
|
||||
PushDir = (damageForce * Normal(Target.Location - Location));
|
||||
damageamount = (SpinDamConst + rand(SpinDamRand) );
|
||||
|
||||
HumanTarget = KFHumanPawn(Target);
|
||||
if ( HumanTarget != none ) {
|
||||
// FLING DEM DEAD BODIEZ!
|
||||
if ( HumanTarget.Health <= DamageAmount ) {
|
||||
HumanTarget.RagDeathVel *= 3;
|
||||
HumanTarget.RagDeathUpKick *= 1.5;
|
||||
}
|
||||
|
||||
if (HumanTarget.Controller != none)
|
||||
HumanTarget.Controller.ShakeView(RotMag, RotRate, RotTime, OffsetMag, OffsetRate, OffsetTime);
|
||||
|
||||
//TODO - line below was KFPawn. Does this whole block need to be KFPawn, or is it OK as KFHumanPawn?
|
||||
HumanTarget.TakeDamage(DamageAmount, self ,HitLocation,pushdir, class 'KFmod.ZombieMeleeDamage');
|
||||
|
||||
if ( HumanTarget.Health <=0 ) {
|
||||
HumanTarget.SpawnGibs(rotator(pushdir), 1);
|
||||
HumanTarget.HideBone(HumanTarget.GetClosestBone(HitLocation,Velocity,dummy));
|
||||
}
|
||||
}
|
||||
else if ( Target.IsA('KFDoorMover') ) {
|
||||
Target.TakeDamage(DamageAmount , self ,HitLocation,pushdir, class 'KFmod.ZombieMeleeDamage');
|
||||
PlaySound(MeleeAttackHitSound, SLOT_Interact, 1.25);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function int DoAnimAction( name AnimName )
|
||||
{
|
||||
if( AnimName=='Attack1' || AnimName=='Attack2' || AnimName=='Attack3' )
|
||||
{
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 1);
|
||||
Return 1;
|
||||
}
|
||||
Return Super.DoAnimAction(AnimName);
|
||||
}
|
||||
|
||||
simulated event SetAnimAction(name NewAction)
|
||||
{
|
||||
local int meleeAnimIndex;
|
||||
|
||||
if( NewAction=='' )
|
||||
Return;
|
||||
if(NewAction == 'Claw')
|
||||
{
|
||||
meleeAnimIndex = Rand(3);
|
||||
NewAction = meleeAnims[meleeAnimIndex];
|
||||
CurrentDamtype = ZombieDamType[meleeAnimIndex];
|
||||
}
|
||||
else if( NewAction == 'DoorBash' )
|
||||
{
|
||||
CurrentDamtype = ZombieDamType[Rand(3)];
|
||||
}
|
||||
ExpectingChannel = DoAnimAction(NewAction);
|
||||
|
||||
if( AnimNeedsWait(NewAction) )
|
||||
{
|
||||
bWaitForAnim = true;
|
||||
}
|
||||
|
||||
if( Level.NetMode!=NM_Client )
|
||||
{
|
||||
AnimAction = NewAction;
|
||||
bResetAnimAct = True;
|
||||
ResetAnimActTime = Level.TimeSeconds+0.3;
|
||||
}
|
||||
|
||||
FFPController(Controller).bAttackedTarget=
|
||||
(NewAction == 'Claw') || (NewAction == 'DoorBash');
|
||||
}
|
||||
|
||||
// The animation is full body and should set the bWaitForAnim flag
|
||||
simulated function bool AnimNeedsWait(name TestAnim)
|
||||
{
|
||||
if( TestAnim == 'Rage_Start' || TestAnim == 'DoorBash' )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
// Keep the flesh pound moving toward its target when attacking
|
||||
if( Role == ROLE_Authority && bShotAnim)
|
||||
{
|
||||
if( LookTarget!=None )
|
||||
{
|
||||
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
||||
}
|
||||
}
|
||||
|
||||
if ( Level.NetMode != NM_DedicatedServer ) {
|
||||
if ( bNeedVent && Health > 0 )
|
||||
SpawnVentEmitter();
|
||||
|
||||
//DebugHead();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function DebugHead()
|
||||
{
|
||||
local coords C;
|
||||
local vector HeadLoc;
|
||||
local float Radius;
|
||||
|
||||
if ( Level.NetMode == NM_DedicatedServer || Health <= 0 )
|
||||
return;
|
||||
|
||||
Radius = HeadRadius * HeadScale;
|
||||
|
||||
// based on head bone
|
||||
C = GetBoneCoords(HeadBone);
|
||||
HeadLoc = C.Origin + (HeadHeight * HeadScale * C.XAxis);
|
||||
DrawDebugSphere(HeadLoc, Radius, 16, 0, 100, 255);
|
||||
|
||||
// based on OnlineHeadshotOffset
|
||||
HeadLoc = Location + (OnlineHeadshotOffset >> Rotation);
|
||||
Radius *= OnlineHeadshotScale;
|
||||
DrawDebugSphere(HeadLoc, Radius, 16, 255, 0, 0);
|
||||
}
|
||||
|
||||
function bool FlipOver()
|
||||
{
|
||||
Return False;
|
||||
}
|
||||
|
||||
function bool SameSpeciesAs(Pawn P)
|
||||
{
|
||||
return ZombieFleshPound(P) != none || FemaleFP(P) != none;
|
||||
}
|
||||
|
||||
simulated function Destroyed()
|
||||
{
|
||||
if( AvoidArea!=None )
|
||||
AvoidArea.Destroy();
|
||||
StopVenting();
|
||||
|
||||
Super.Destroyed();
|
||||
}
|
||||
|
||||
simulated function DeviceGoRed()
|
||||
{
|
||||
Skins[3]=Shader'ScrnZedPack_T.FFPLights_Red_shader';
|
||||
Skins[1]=Combiner'ScrnZedPack_T.FFP_Metal_R_cmb';
|
||||
}
|
||||
|
||||
simulated function DeviceGoNormal()
|
||||
{
|
||||
Skins[3]=Shader'ScrnZedPack_T.FFPLights_Yellow_shader';
|
||||
Skins[1]=Combiner'ScrnZedPack_T.FFP_Metal_cmb';
|
||||
}
|
||||
|
||||
//Metal does not burn like flesh!
|
||||
simulated function ZombieCrispUp()
|
||||
{
|
||||
bAshen = true;
|
||||
bCrispified = true;
|
||||
|
||||
SetBurningBehavior();
|
||||
|
||||
if ( Level.NetMode == NM_DedicatedServer || class'GameInfo'.static.UseLowGore() )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[4]=Combiner'PatchTex.Common.BurnSkinEmbers_cmb';
|
||||
|
||||
}
|
||||
|
||||
simulated function PlayDirectionalDeath(Vector HitLoc)
|
||||
{
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
SetCollision(false, false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// lame hack, but it is better than leaving her staying for those, who have no karma data
|
||||
// -- PooSH
|
||||
SetCollision(false, false, false);
|
||||
bHidden = true;
|
||||
}
|
||||
|
||||
// Player must have bRagdolls=True in FemaleFPMut.ini to see karma death animation.
|
||||
// If there is no FemaleFPMut.ini file on client side, then usually there is no FFPKarma.ka file too,
|
||||
// so non-ragdoll death fallback is used.
|
||||
// WARNING! Trying to use karma without karma file causes game crash!
|
||||
// -- PooSH
|
||||
simulated function PlayDyingAnimation(class<DamageType>DamageType,vector HitLoc)
|
||||
{
|
||||
if(Level.NetMode!=NM_DedicatedServer && Class'FFPKarma'.Static.UseRagdoll(Level) ) {
|
||||
// karma death
|
||||
super.PlayDyingAnimation(DamageType, HitLoc);
|
||||
}
|
||||
else {
|
||||
if(MyExtCollision!=None)
|
||||
MyExtCollision.Destroy();
|
||||
|
||||
// non-ragdoll death fallback
|
||||
Velocity+=GetTearOffMomemtum();
|
||||
BaseEyeHeight=Default.BaseEyeHeight;
|
||||
SetTwistLook(0,0);
|
||||
SetInvisibility(0.0);
|
||||
PlayDirectionalDeath(HitLoc);
|
||||
SetPhysics(PHYS_Falling);
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveHead()
|
||||
{
|
||||
Super.RemoveHead();
|
||||
// FFP has different bone names. Since most bones are hardcoded in KFMonster,
|
||||
// there is no easy way to implement decapitation
|
||||
KilledBy(LastDamagedBy);
|
||||
}
|
||||
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.FFP.BraTexture');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.FFP.FFP_Metal_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.FFP.FFP_Metal_R_cmb');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFPLights_Yellow_shader');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFPLights_Red_shader');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFP_Skin1_Sdr');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ChargingAnim="Rage_Run"
|
||||
VentEffectClass=Class'ScrnZedPack.FFPVentEmitter'
|
||||
RageDamageThreshold=300
|
||||
MeleeAnims(0)="Attack1"
|
||||
MeleeAnims(1)="Attack2"
|
||||
MeleeAnims(2)="Attack3"
|
||||
HitAnims(0)="Hit"
|
||||
HitAnims(1)="Hit"
|
||||
HitAnims(2)="Hit"
|
||||
MoanVoice=SoundGroup'ScrnZedPack_S.FFP.FFPG_Talk'
|
||||
KFHitFront="Hit"
|
||||
KFHitBack="Hit"
|
||||
KFHitLeft="Hit"
|
||||
KFHitRight="Hit"
|
||||
StunsRemaining=3
|
||||
BleedOutDuration=7.000000
|
||||
ZapThreshold=1.750000
|
||||
ZappedDamageMod=1.250000
|
||||
ZombieFlag=3
|
||||
MeleeDamage=30
|
||||
damageForce=15000
|
||||
bFatAss=True
|
||||
KFRagdollName="FFPKarma"
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_HitPlayer'
|
||||
JumpSound=SoundGroup'ScrnZedPack_S.FFP.FFPG_Jump'
|
||||
SpinDamConst=15.000000
|
||||
SpinDamRand=10.000000
|
||||
bMeleeStunImmune=True
|
||||
Intelligence=BRAINS_Mammal
|
||||
bUseExtendedCollision=True
|
||||
ColOffset=(Z=47.000000)
|
||||
ColRadius=40.000000
|
||||
ColHeight=40.000000
|
||||
ExtCollAttachBoneName="Collision_Attach"
|
||||
SeveredLegAttachScale=1.100000
|
||||
SeveredHeadAttachScale=1.200000
|
||||
DetachedArmClass=Class'ScrnZedPack.SeveredArmFFP'
|
||||
DetachedLegClass=Class'ScrnZedPack.SeveredLegFFP'
|
||||
PlayerCountHealthScale=0.300000
|
||||
OnlineHeadshotOffset=(X=25.000000,Z=61.000000)
|
||||
OnlineHeadshotScale=1.300000
|
||||
HeadHealth=600.000000
|
||||
PlayerNumHeadHealthScale=0.300000
|
||||
MotionDetectorThreat=5.000000
|
||||
HitSound(0)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Pain'
|
||||
DeathSound(0)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Death'
|
||||
ChallengeSound(0)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'ScrnZedPack_S.FFP.FFPG_Challenge'
|
||||
ScoringValue=200
|
||||
IdleHeavyAnim="Idle"
|
||||
IdleRifleAnim="Idle"
|
||||
FireRootBone="BODY_Spine2"
|
||||
GroundSpeed=140.000000
|
||||
HealthMax=1100.000000
|
||||
Health=1100
|
||||
HeadRadius=8.000000
|
||||
HeadHeight=2.500000
|
||||
HeadScale=1.300000
|
||||
MenuName="Female FleshPound"
|
||||
ControllerClass=Class'ScrnZedPack.FFPController'
|
||||
MovementAnims(0)="WalkF"
|
||||
MovementAnims(1)="WalkF"
|
||||
MovementAnims(2)="WalkL"
|
||||
MovementAnims(3)="WalkR"
|
||||
WalkAnims(2)="WalkL"
|
||||
WalkAnims(3)="WalkR"
|
||||
AirStillAnim="Jump"
|
||||
TakeoffStillAnim="Jump"
|
||||
IdleCrouchAnim="Idle"
|
||||
IdleWeaponAnim="Idle"
|
||||
IdleRestAnim="Idle"
|
||||
RootBone="Armature"
|
||||
HeadBone="BODY_Head"
|
||||
SpineBone1="BODY_Spine2"
|
||||
SpineBone2="BODY_Spine3"
|
||||
AmbientSound=SoundGroup'ScrnZedPack_S.FFP.FFPG_Idle'
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.FFPMesh'
|
||||
Skins(0)=Texture'ScrnZedPack_T.FFP.BraTexture'
|
||||
Skins(1)=Combiner'ScrnZedPack_T.FFP.FFP_Metal_cmb'
|
||||
Skins(2)=Combiner'ScrnZedPack_T.FFP.FFP_Metal_cmb'
|
||||
Skins(3)=Shader'ScrnZedPack_T.FFP.FFPLights_Yellow_shader'
|
||||
Skins(4)=Shader'ScrnZedPack_T.FFP.FFP_Skin1_Sdr'
|
||||
Mass=500.000000
|
||||
RotationRate=(Yaw=45000,Roll=0)
|
||||
}
|
||||
127
kf_sources/ScrnZedPack/Classes/FemaleFP_MKII.uc
Normal file
127
kf_sources/ScrnZedPack/Classes/FemaleFP_MKII.uc
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
class FemaleFP_MKII extends FemaleFP;
|
||||
|
||||
struct SDamageResistance
|
||||
{
|
||||
var class<KFWeaponDamageType> DamType;
|
||||
var byte ResistanceLevel;
|
||||
var float AdaptTime;
|
||||
};
|
||||
var array<SDamageResistance> DamageRes;
|
||||
var array<float> ResistanceLevels;
|
||||
var float AdaptInterval; // how long does it takes for FFP to adapt to received damage
|
||||
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
local int OldHealth;
|
||||
local class<KFWeaponDamageType> KFDamType;
|
||||
local int i;
|
||||
|
||||
// optimizes typecasting and make code comre compact -- PooSH
|
||||
KFDamType = class<KFWeaponDamageType>(damageType);
|
||||
oldHealth= Health;
|
||||
|
||||
if ( KFDamType != none ) {
|
||||
if ( KFDamType.default.bIsExplosive ) {
|
||||
if ( KFDamType == class'DamTypeFrag' )
|
||||
Damage *= 2.00;
|
||||
else if ( !ClassIsChildOf(KFDamType, class'DamTypeLAW'))
|
||||
Damage *= 1.25;
|
||||
}
|
||||
else if ( ClassIsChildOf(KFDamType, class'DamTypeCrossbow') )
|
||||
KFDamType = class'DamTypeCrossbowHeadShot'; // apply same resistance on similar damage types
|
||||
else if ( ClassIsChildOf(KFDamType, class'DamTypeM99SniperRifle') ) {
|
||||
KFDamType = class'DamTypeM99HeadShot';
|
||||
Damage *= 0.75; // additional damage resistance to M99
|
||||
}
|
||||
else if ( ClassIsChildOf(KFDamType, class'DamTypeCrossbuzzsaw') ) {
|
||||
KFDamType = class'DamTypeCrossbuzzsawHeadShot';
|
||||
Damage *= 0.75;
|
||||
}
|
||||
|
||||
for ( i=0; i<DamageRes.length; ++i ) {
|
||||
if ( DamageRes[i].DamType == KFDamType ) {
|
||||
if ( Level.TimeSeconds < DamageRes[i].AdaptTime ) {
|
||||
if ( DamageRes[i].ResistanceLevel > 0 )
|
||||
Damage *= ResistanceLevels[DamageRes[i].ResistanceLevel-1]; // skin is not adapted to this damage type yet
|
||||
}
|
||||
else {
|
||||
Damage *= ResistanceLevels[DamageRes[i].ResistanceLevel];
|
||||
if ( DamageRes[i].ResistanceLevel + 1 < ResistanceLevels.length ) {
|
||||
DamageRes[i].ResistanceLevel++;
|
||||
DamageRes[i].AdaptTime = Level.TimeSeconds + AdaptInterval;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == DamageRes.length ) {
|
||||
// new damage type
|
||||
DamageRes.insert(i, 1);
|
||||
DamageRes[i].DamType = KFDamType;
|
||||
DamageRes[i].AdaptTime = Level.TimeSeconds + AdaptInterval;
|
||||
}
|
||||
}
|
||||
|
||||
// Shut off her "Device" when dead
|
||||
if (Damage >= Health)
|
||||
PostNetReceive();
|
||||
|
||||
// fixes none-reference erros when taking enviromental damage -- PooSH
|
||||
if (InstigatedBy == none || KFDamType == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, damageType); // skip NONE-reference error
|
||||
else
|
||||
super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, damageType);
|
||||
|
||||
|
||||
Damage = OldHealth - Health;
|
||||
|
||||
// Starts charging if single damage > 300 or health drops below 50% on hard difficulty or below,
|
||||
// or health <75% on Suicidal/HoE
|
||||
// -- PooSH
|
||||
if ( Health > 0 && !bDecapitated && !bChargingPlayer
|
||||
&& !bZapped && (!(bCrispified && bBurnified) || bFrustrated)
|
||||
&& (Damage > RageDamageThreshold || Health < HealthMax*0.5
|
||||
|| (Level.Game.GameDifficulty >= 5.0 && Health < HealthMax*0.75)) )
|
||||
StartCharging();
|
||||
}
|
||||
|
||||
simulated function DeviceGoRed()
|
||||
{
|
||||
Skins[3]=Shader'ScrnZedPack_T.FFP.FFPLights_Blue_shader';
|
||||
Skins[1]=Combiner'ScrnZedPack_T.FFP.FFP_Metal_B_cmb';
|
||||
Skins[4]=Shader'ScrnZedPack_T.FFP.FFP_Skin1_B_Sdr';
|
||||
}
|
||||
|
||||
simulated function DeviceGoNormal()
|
||||
{
|
||||
Skins[3]=Shader'ScrnZedPack_T.FFP.FFPLights_Green_shader';
|
||||
Skins[1]=Combiner'ScrnZedPack_T.FFP.FFP_Metal_G_cmb';
|
||||
Skins[4]=Shader'ScrnZedPack_T.FFP.FFP_Skin1_Sdr';
|
||||
}
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.FFP.BraTexture');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.FFP.FFP_Metal_G_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.FFP.FFP_Metal_B_cmb');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFPLights_Green_shader');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFPLights_Blue_shader');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFP_Skin1_Sdr');
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.FFP.FFP_Skin1_B_Sdr');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DamageRes(0)=(damtype=Class'KFMod.DamTypeCrossbowHeadShot')
|
||||
DamageRes(1)=(damtype=Class'KFMod.DamTypeM99HeadShot')
|
||||
ResistanceLevels(0)=0.500000
|
||||
ResistanceLevels(1)=0.250000
|
||||
ResistanceLevels(2)=0.150000
|
||||
AdaptInterval=0.500000
|
||||
HeadHealth=800.000000
|
||||
PlayerNumHeadHealthScale=0.175000
|
||||
MenuName="Female FleshPound MKII"
|
||||
Skins(1)=Combiner'ScrnZedPack_T.FFP.FFP_Metal_G_cmb'
|
||||
Skins(2)=Combiner'ScrnZedPack_T.FFP.FFP_Metal_G_cmb'
|
||||
Skins(3)=Shader'ScrnZedPack_T.FFP.FFPLights_Green_shader'
|
||||
}
|
||||
612
kf_sources/ScrnZedPack/Classes/HardPat.uc
Normal file
612
kf_sources/ScrnZedPack/Classes/HardPat.uc
Normal file
|
|
@ -0,0 +1,612 @@
|
|||
Class HardPat extends ZombieBoss;
|
||||
|
||||
var transient float GiveUpTime;
|
||||
var byte MissilesLeft;
|
||||
var bool bEndGameBoss,bMovingChaingunAttack;
|
||||
var(Sounds) sound SaveMeSound;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if( ROLE==ROLE_AUTHORITY )
|
||||
bMovingChaingunAttack;
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
SyringeCount = 3; // no healing for mid-game bosses
|
||||
Health *= 0.75; // less hp for mid-game bosses
|
||||
}
|
||||
|
||||
function bool MakeGrandEntry()
|
||||
{
|
||||
Health = HealthMax; // restore original hp
|
||||
bEndGameBoss = true;
|
||||
SyringeCount = 0; // restore healing for end-game boss
|
||||
return Super.MakeGrandEntry();
|
||||
}
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
Super(KFMonster).Died(Killer,damageType,HitLocation);
|
||||
if ( bEndGameBoss )
|
||||
KFGameType(Level.Game).DoBossDeath();
|
||||
}
|
||||
|
||||
simulated function bool HitCanInterruptAction()
|
||||
{
|
||||
return (!bWaitForAnim && !bShotAnim);
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
local float D;
|
||||
local bool bOnlyE;
|
||||
local bool bDesireChainGun;
|
||||
|
||||
// Randomly make him want to chaingun more
|
||||
if( Controller.LineOfSightTo(A) && FRand() < 0.15 && LastChainGunTime<Level.TimeSeconds )
|
||||
{
|
||||
bDesireChainGun = true;
|
||||
}
|
||||
|
||||
if ( bShotAnim )
|
||||
{
|
||||
if( !IsAnimating(ExpectingChannel) )
|
||||
bShotAnim = false;
|
||||
return;
|
||||
}
|
||||
D = VSize(A.Location-Location);
|
||||
bOnlyE = (Pawn(A)!=None && OnlyEnemyAround(Pawn(A)));
|
||||
if ( IsCloseEnuf(A) )
|
||||
{
|
||||
bShotAnim = true;
|
||||
if( Health>1500 && Pawn(A)!=None && FRand() < 0.5 )
|
||||
{
|
||||
SetAnimAction('MeleeImpale');
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAnimAction('MeleeClaw');
|
||||
//PlaySound(sound'Claw2s', SLOT_None); KFTODO: Replace this
|
||||
}
|
||||
}
|
||||
else if( Level.TimeSeconds>LastSneakedTime )
|
||||
{
|
||||
if( FRand() < 0.3 )
|
||||
{
|
||||
// Wait another 20-40 to try this again
|
||||
LastSneakedTime = Level.TimeSeconds+20.f+FRand()*20;
|
||||
Return;
|
||||
}
|
||||
SetAnimAction('transition');
|
||||
GoToState('SneakAround');
|
||||
}
|
||||
else if( bChargingPlayer && (bOnlyE || D<200) )
|
||||
Return;
|
||||
else if( !bDesireChainGun && !bChargingPlayer && (D<300 || (D<700 && bOnlyE)) &&
|
||||
(Level.TimeSeconds - LastChargeTime > (5.0 + 5.0 * FRand())) ) // Don't charge again for a few seconds
|
||||
{
|
||||
SetAnimAction('transition');
|
||||
GoToState('Charging');
|
||||
}
|
||||
else if( LastMissileTime<Level.TimeSeconds && (D>500 || SyringeCount>=2) )
|
||||
{
|
||||
if( !Controller.LineOfSightTo(A) || FRand() > 0.75 )
|
||||
{
|
||||
LastMissileTime = Level.TimeSeconds+FRand() * 5;
|
||||
Return;
|
||||
}
|
||||
|
||||
LastMissileTime = Level.TimeSeconds + 10 + FRand() * 15;
|
||||
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('PreFireMissile');
|
||||
|
||||
HandleWaitForAnim('PreFireMissile');
|
||||
|
||||
GoToState('FireMissile');
|
||||
}
|
||||
else if ( !bWaitForAnim && !bShotAnim && LastChainGunTime<Level.TimeSeconds )
|
||||
{
|
||||
if ( !Controller.LineOfSightTo(A) || FRand()> 0.85 )
|
||||
{
|
||||
LastChainGunTime = Level.TimeSeconds+FRand()*4;
|
||||
Return;
|
||||
}
|
||||
|
||||
LastChainGunTime = Level.TimeSeconds + 5 + FRand() * 10;
|
||||
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('PreFireMG');
|
||||
|
||||
HandleWaitForAnim('PreFireMG');
|
||||
if ( bEndGameBoss )
|
||||
MGFireCounter = Rand(60) + 35*(SyringeCount+1);
|
||||
else
|
||||
MGFireCounter = Rand(60) + 60;
|
||||
|
||||
|
||||
GoToState('FireChaingun');
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool AnimNeedsWait(name TestAnim)
|
||||
{
|
||||
if( TestAnim == 'FireMG' )
|
||||
return !bMovingChaingunAttack;
|
||||
return Super.AnimNeedsWait(TestAnim);
|
||||
}
|
||||
simulated final function rotator GetBoneTransRot()
|
||||
{
|
||||
local rotator R;
|
||||
|
||||
R.Yaw = 24576+Rotation.Yaw;
|
||||
R.Pitch = 16384+Rotation.Pitch;
|
||||
return R;
|
||||
}
|
||||
simulated function int DoAnimAction( name AnimName )
|
||||
{
|
||||
if( AnimName=='FireMG' && bMovingChaingunAttack )
|
||||
{
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone, True);
|
||||
//SetBoneDirection(FireRootBone,GetBoneTransRot(),,1,1);
|
||||
PlayAnim('FireMG',, 0.f, 1);
|
||||
return 1;
|
||||
}
|
||||
else if( AnimName=='FireEndMG' )
|
||||
{
|
||||
//SetBoneDirection(FireRootBone,rot(0,0,0),,0,0);
|
||||
AnimBlendParams(1, 0);
|
||||
}
|
||||
return Super.DoAnimAction( AnimName );
|
||||
}
|
||||
simulated function AnimEnd(int Channel)
|
||||
{
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
if( Level.NetMode==NM_Client && bMinigunning )
|
||||
{
|
||||
GetAnimParams( Channel, Sequence, Frame, Rate );
|
||||
|
||||
if( Sequence != 'PreFireMG' && Sequence != 'FireMG' )
|
||||
{
|
||||
//SetBoneDirection(FireRootBone,rot(0,0,0),,0,0);
|
||||
Super(KFMonster).AnimEnd(Channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if( bMovingChaingunAttack )
|
||||
DoAnimAction('FireMG');
|
||||
else
|
||||
{
|
||||
PlayAnim('FireMG');
|
||||
bWaitForAnim = true;
|
||||
bShotAnim = true;
|
||||
IdleTime = Level.TimeSeconds;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//SetBoneDirection(FireRootBone,rot(0,0,0),,0,0);
|
||||
Super(KFMonster).AnimEnd(Channel);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix: Don't spawn needle before last stage.
|
||||
simulated function NotifySyringeA()
|
||||
{
|
||||
if( Level.NetMode!=NM_Client )
|
||||
{
|
||||
if( SyringeCount<3 )
|
||||
SyringeCount++;
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
PostNetReceive();
|
||||
}
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
DropNeedle();
|
||||
}
|
||||
simulated function NotifySyringeC()
|
||||
{
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
{
|
||||
CurrentNeedle = Spawn(Class'BossHPNeedle');
|
||||
CurrentNeedle.Velocity = vect(-45,300,-90) >> Rotation;
|
||||
DropNeedle();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function ZombieCrispUp() // Don't become crispy.
|
||||
{
|
||||
bAshen = true;
|
||||
bCrispified = true;
|
||||
SetBurningBehavior();
|
||||
}
|
||||
|
||||
state KnockDown
|
||||
{
|
||||
Ignores RangedAttack;
|
||||
|
||||
Begin:
|
||||
if ( Health > 0 )
|
||||
{
|
||||
Sleep(GetAnimDuration('KnockDown'));
|
||||
CloakBoss();
|
||||
PlaySound(SaveMeSound, SLOT_Misc, 2.0,,500.0);
|
||||
|
||||
if ( KFGameType(Level.Game).FinalSquadNum == SyringeCount )
|
||||
{
|
||||
KFGameType(Level.Game).AddBossBuddySquad();
|
||||
}
|
||||
|
||||
GotoState('Escaping');
|
||||
}
|
||||
else
|
||||
{
|
||||
GotoState('');
|
||||
}
|
||||
}
|
||||
state FireChaingun
|
||||
{
|
||||
function BeginState()
|
||||
{
|
||||
Super.BeginState();
|
||||
bMovingChaingunAttack = (SyringeCount>=2);
|
||||
bChargingPlayer = bEndGameBoss && SyringeCount>=3 && FRand()<0.4f;
|
||||
bCanStrafe = true;
|
||||
}
|
||||
function EndState()
|
||||
{
|
||||
bChargingPlayer = false;
|
||||
Super.EndState();
|
||||
bMovingChaingunAttack = false;
|
||||
bCanStrafe = false;
|
||||
}
|
||||
function Tick( float Delta )
|
||||
{
|
||||
Super(KFMonster).Tick(Delta);
|
||||
if( bChargingPlayer )
|
||||
GroundSpeed = OriginalGroundSpeed * 2.3;
|
||||
else GroundSpeed = OriginalGroundSpeed * 1.15;
|
||||
}
|
||||
function AnimEnd( int Channel )
|
||||
{
|
||||
if( MGFireCounter <= 0 )
|
||||
{
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('FireEndMG');
|
||||
HandleWaitForAnim('FireEndMG');
|
||||
GoToState('');
|
||||
}
|
||||
else if( bMovingChaingunAttack )
|
||||
{
|
||||
if( bFireAtWill && Channel!=1 )
|
||||
return;
|
||||
if( Controller.Target!=None )
|
||||
Controller.Focus = Controller.Target;
|
||||
bShotAnim = false;
|
||||
bFireAtWill = True;
|
||||
SetAnimAction('FireMG');
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( Controller.Enemy != none )
|
||||
{
|
||||
if ( Controller.LineOfSightTo(Controller.Enemy) && FastTrace(GetBoneCoords('tip').Origin,Controller.Enemy.Location))
|
||||
{
|
||||
MGLostSightTimeout = 0.0;
|
||||
Controller.Focus = Controller.Enemy;
|
||||
Controller.FocalPoint = Controller.Enemy.Location;
|
||||
}
|
||||
else
|
||||
{
|
||||
MGLostSightTimeout = Level.TimeSeconds + (0.25 + FRand() * 0.35);
|
||||
Controller.Focus = None;
|
||||
}
|
||||
Controller.Target = Controller.Enemy;
|
||||
}
|
||||
else
|
||||
{
|
||||
MGLostSightTimeout = Level.TimeSeconds + (0.25 + FRand() * 0.35);
|
||||
Controller.Focus = None;
|
||||
}
|
||||
|
||||
if( !bFireAtWill )
|
||||
{
|
||||
MGFireDuration = Level.TimeSeconds + (0.75 + FRand() * 0.5);
|
||||
}
|
||||
else if ( FRand() < 0.03 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none )
|
||||
{
|
||||
// Randomly send out a message about Patriarch shooting chain gun(3% chance)
|
||||
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 9, "");
|
||||
}
|
||||
|
||||
bFireAtWill = True;
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
SetAnimAction('FireMG');
|
||||
bWaitForAnim = true;
|
||||
}
|
||||
}
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
local float EnemyDistSq, DamagerDistSq;
|
||||
global.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType);
|
||||
if( bMovingChaingunAttack || Health<=0 )
|
||||
return;
|
||||
|
||||
// if someone close up is shooting us, just charge them
|
||||
if( InstigatedBy != none )
|
||||
{
|
||||
DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location);
|
||||
|
||||
if( (ChargeDamage > 200 && DamagerDistSq < (500 * 500)) || DamagerDistSq < (100 * 100) )
|
||||
{
|
||||
SetAnimAction('transition');
|
||||
GoToState('Charging');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( Controller.Enemy != none && InstigatedBy != none && InstigatedBy != Controller.Enemy )
|
||||
{
|
||||
EnemyDistSq = VSizeSquared(Location - Controller.Enemy.Location);
|
||||
DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location);
|
||||
}
|
||||
|
||||
if( InstigatedBy != none && (DamagerDistSq < EnemyDistSq || Controller.Enemy == none) )
|
||||
{
|
||||
MonsterController(Controller).ChangeEnemy(InstigatedBy,Controller.CanSee(InstigatedBy));
|
||||
Controller.Target = InstigatedBy;
|
||||
Controller.Focus = InstigatedBy;
|
||||
|
||||
if( DamagerDistSq < (500 * 500) )
|
||||
{
|
||||
SetAnimAction('transition');
|
||||
GoToState('Charging');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Begin:
|
||||
While( True )
|
||||
{
|
||||
if( !bMovingChaingunAttack )
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
if( MGLostSightTimeout > 0 && Level.TimeSeconds > MGLostSightTimeout )
|
||||
{
|
||||
Acceleration = vect(0,0,0);
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('FireEndMG');
|
||||
HandleWaitForAnim('FireEndMG');
|
||||
GoToState('');
|
||||
}
|
||||
|
||||
if( MGFireCounter <= 0 )
|
||||
{
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('FireEndMG');
|
||||
HandleWaitForAnim('FireEndMG');
|
||||
GoToState('');
|
||||
}
|
||||
|
||||
// Give some randomness to the patriarch's firing (constantly fire after first stage passed)
|
||||
if( Level.TimeSeconds > MGFireDuration && SyringeCount==0 )
|
||||
{
|
||||
if( AmbientSound != MiniGunSpinSound )
|
||||
{
|
||||
SoundVolume=185;
|
||||
SoundRadius=200;
|
||||
AmbientSound = MiniGunSpinSound;
|
||||
}
|
||||
Sleep(0.5 + FRand() * 0.75);
|
||||
MGFireDuration = Level.TimeSeconds + (0.75 + FRand() * 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( bFireAtWill )
|
||||
FireMGShot();
|
||||
Sleep(0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state FireMissile
|
||||
{
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if( SyringeCount>=2 )
|
||||
{
|
||||
Controller.Target = A;
|
||||
Controller.Focus = A;
|
||||
}
|
||||
}
|
||||
function BeginState()
|
||||
{
|
||||
if ( bEndGameBoss )
|
||||
MissilesLeft = SyringeCount+Rand(SyringeCount);
|
||||
else
|
||||
MissilesLeft = 1+Rand(3);
|
||||
Acceleration = vect(0,0,0);
|
||||
}
|
||||
|
||||
function AnimEnd( int Channel )
|
||||
{
|
||||
local vector Start;
|
||||
local Rotator R;
|
||||
|
||||
Start = GetBoneCoords('tip').Origin;
|
||||
if( Controller.Target==None )
|
||||
Controller.Target = Controller.Enemy;
|
||||
|
||||
if ( !SavedFireProperties.bInitialized )
|
||||
{
|
||||
SavedFireProperties.AmmoClass = MyAmmo.Class;
|
||||
SavedFireProperties.ProjectileClass = Class'BossLAWProj';
|
||||
SavedFireProperties.WarnTargetPct = 0.15;
|
||||
SavedFireProperties.MaxRange = 10000;
|
||||
SavedFireProperties.bTossed = False;
|
||||
SavedFireProperties.bLeadTarget = True;
|
||||
SavedFireProperties.bInitialized = true;
|
||||
}
|
||||
SavedFireProperties.bInstantHit = (SyringeCount<1);
|
||||
SavedFireProperties.bTrySplash = (SyringeCount>=2);
|
||||
|
||||
R = AdjustAim(SavedFireProperties,Start,100);
|
||||
PlaySound(RocketFireSound,SLOT_Interact,2.0,,TransientSoundRadius,,false);
|
||||
Spawn(Class'BossLAWProj',,,Start,R);
|
||||
|
||||
bShotAnim = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
SetAnimAction('FireEndMissile');
|
||||
HandleWaitForAnim('FireEndMissile');
|
||||
|
||||
// Randomly send out a message about Patriarch shooting a rocket(5% chance)
|
||||
if ( FRand() < 0.05 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none )
|
||||
{
|
||||
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 10, "");
|
||||
}
|
||||
|
||||
if( MissilesLeft==0 )
|
||||
GoToState('');
|
||||
else
|
||||
{
|
||||
--MissilesLeft;
|
||||
GoToState(,'SecondMissile');
|
||||
}
|
||||
}
|
||||
Begin:
|
||||
while ( true )
|
||||
{
|
||||
Acceleration = vect(0,0,0);
|
||||
Sleep(0.1);
|
||||
}
|
||||
SecondMissile:
|
||||
Acceleration = vect(0,0,0);
|
||||
Sleep(0.5f);
|
||||
AnimEnd(0);
|
||||
}
|
||||
|
||||
State Escaping // Added god-mode if bEndGameBoss
|
||||
{
|
||||
Ignores RangedAttack;
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
GiveUpTime = Level.TimeSeconds+20.f+FRand()*20.f;
|
||||
Super.BeginState();
|
||||
if ( bEndGameBoss ) {
|
||||
bBlockActors = false;
|
||||
// While escaping Pat doesn't blow up pipebombs -- PooSH
|
||||
MotionDetectorThreat=0;
|
||||
}
|
||||
}
|
||||
function EndState()
|
||||
{
|
||||
Super.EndState();
|
||||
if( Health>0 )
|
||||
bBlockActors = true;
|
||||
MotionDetectorThreat = default.MotionDetectorThreat;
|
||||
}
|
||||
function Tick( float Delta )
|
||||
{
|
||||
if( Level.TimeSeconds>GiveUpTime )
|
||||
{
|
||||
BeginHealing();
|
||||
return;
|
||||
}
|
||||
if( !bChargingPlayer )
|
||||
{
|
||||
bChargingPlayer = true;
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
PostNetReceive();
|
||||
}
|
||||
GroundSpeed = OriginalGroundSpeed * 2.5;
|
||||
Global.Tick(Delta);
|
||||
}
|
||||
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
if ( !bEndGameBoss )
|
||||
global.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType);
|
||||
}
|
||||
}
|
||||
|
||||
State SneakAround
|
||||
{
|
||||
function BeginState()
|
||||
{
|
||||
super.BeginState();
|
||||
SneakStartTime = Level.TimeSeconds+10.f+FRand()*15.f;
|
||||
}
|
||||
function EndState()
|
||||
{
|
||||
super.EndState();
|
||||
LastSneakedTime = Level.TimeSeconds+20.f+FRand()*30.f;
|
||||
if( Controller!=None && Controller.IsInState('PatFindWay') )
|
||||
Controller.GoToState('ZombieHunt');
|
||||
}
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
global.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType);
|
||||
if( Health<=0 )
|
||||
return;
|
||||
|
||||
// if someone close up is shooting us, just charge them
|
||||
if( InstigatedBy!=none && VSizeSquared(Location - InstigatedBy.Location)<62500 )
|
||||
GoToState('Charging');
|
||||
}
|
||||
|
||||
Begin:
|
||||
CloakBoss();
|
||||
if( SyringeCount>=2 && FRand()<0.6 )
|
||||
HardPatController(Controller).FindPathAround();
|
||||
While( true )
|
||||
{
|
||||
Sleep(0.5);
|
||||
|
||||
if( !bCloaked && !bShotAnim )
|
||||
CloakBoss();
|
||||
if( !Controller.IsInState('PatFindWay') )
|
||||
{
|
||||
if( Level.TimeSeconds>SneakStartTime )
|
||||
GoToState('');
|
||||
if( !Controller.IsInState('WaitForAnim') && !Controller.IsInState('ZombieHunt') )
|
||||
Controller.GoToState('ZombieHunt');
|
||||
}
|
||||
else SneakStartTime = Level.TimeSeconds+30.f;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
SaveMeSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_SaveMe'
|
||||
RocketFireSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_FireRocket'
|
||||
MiniGunFireSound=Sound'KF_BasePatriarch.Attack.Kev_MG_GunfireLoop'
|
||||
MiniGunSpinSound=Sound'KF_BasePatriarch.Attack.Kev_MG_TurbineFireLoop'
|
||||
MeleeImpaleHitSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_HitPlayer_Impale'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_HitPlayer_Fist'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPatriarch'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPatriarch'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPatriarch'
|
||||
DetachedSpecialArmClass=Class'KFChar.SeveredRocketArmPatriarch'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Death'
|
||||
ScoringValue=1000
|
||||
MenuName="Hard Pat"
|
||||
ControllerClass=Class'ScrnZedPack.HardPatController'
|
||||
AmbientSound=Sound'KF_BasePatriarch.Idle.Kev_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Patriarch_Freak'
|
||||
LODBias=4.000000
|
||||
Skins(0)=Combiner'KF_Specimens_Trip_T.gatling_cmb'
|
||||
Skins(1)=Combiner'KF_Specimens_Trip_T.patriarch_cmb'
|
||||
}
|
||||
160
kf_sources/ScrnZedPack/Classes/HardPatController.uc
Normal file
160
kf_sources/ScrnZedPack/Classes/HardPatController.uc
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class HardPatController extends BossZombieController;
|
||||
|
||||
var NavigationPoint MidGoals[2];
|
||||
var byte ReachOffset;
|
||||
var Actor OldPathsCheck[3];
|
||||
|
||||
function Debugf( string S )
|
||||
{
|
||||
Level.GetLocalPlayerController().ClientMessage(S);
|
||||
Log(S);
|
||||
}
|
||||
final function FindPathAround()
|
||||
{
|
||||
local Actor Res;
|
||||
local NavigationPoint N;
|
||||
local NavigationPoint OldPts[12];
|
||||
local byte i;
|
||||
local bool bResult;
|
||||
|
||||
if( Enemy==None || VSizeSquared(Enemy.Location-Pawn.Location)<360000 )
|
||||
return; // No can do this.
|
||||
|
||||
// Attempt to find an alternative path to enemy.
|
||||
/* This works by:
|
||||
- finding shortest path to enemy
|
||||
- block middle path point
|
||||
- if the path is still about same to enemy, try block the new path and repeat up to 6 times.
|
||||
*/
|
||||
for( i=0; i<ArrayCount(OldPts); ++i )
|
||||
{
|
||||
Res = FindPathToward(Enemy);
|
||||
if( Res==None )
|
||||
break;
|
||||
if( i>0 && CompareOldPaths() )
|
||||
{
|
||||
bResult = true;
|
||||
break;
|
||||
}
|
||||
N = GetMidPoint();
|
||||
if( N==None )
|
||||
break;
|
||||
N.bBlocked = true;
|
||||
OldPts[i] = N;
|
||||
if( i==0 )
|
||||
SetOldPaths();
|
||||
}
|
||||
|
||||
// Unblock temp blocked paths.
|
||||
for( i=0; i<ArrayCount(OldPts); ++i )
|
||||
if( OldPts[i]!=None )
|
||||
OldPts[i].bBlocked = false;
|
||||
if( !bResult )
|
||||
return;
|
||||
|
||||
// Fetch results and switch state.
|
||||
GetMidGoals();
|
||||
if( ReachOffset<2 )
|
||||
GoToState('PatFindWay');
|
||||
}
|
||||
final function NavigationPoint GetMidPoint()
|
||||
{
|
||||
local byte n;
|
||||
|
||||
for( n=0; n<ArrayCount(RouteCache); ++n )
|
||||
if( RouteCache[n]==None )
|
||||
break;
|
||||
if( n==0 )
|
||||
return None;
|
||||
return NavigationPoint(RouteCache[(n-1)*0.5]);
|
||||
}
|
||||
final function bool CompareOldPaths()
|
||||
{
|
||||
local byte n,i;
|
||||
|
||||
for( i=0; i<6; ++i )
|
||||
{
|
||||
if( RouteCache[i]==None )
|
||||
break;
|
||||
for( n=0; n<ArrayCount(OldPathsCheck); ++n )
|
||||
if( RouteCache[i]==OldPathsCheck[n] )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
final function SetOldPaths()
|
||||
{
|
||||
local byte n;
|
||||
|
||||
for( n=0; n<ArrayCount(OldPathsCheck); ++n )
|
||||
OldPathsCheck[n] = RouteCache[n+1];
|
||||
if( RouteCache[1]==None )
|
||||
OldPathsCheck[0] = RouteCache[0];
|
||||
}
|
||||
final function GetMidGoals()
|
||||
{
|
||||
local byte n;
|
||||
|
||||
for( n=0; n<ArrayCount(RouteCache); ++n )
|
||||
if( RouteCache[n]==None )
|
||||
break;
|
||||
if( n==0 )
|
||||
{
|
||||
ReachOffset = 2;
|
||||
return;
|
||||
}
|
||||
--n;
|
||||
MidGoals[0] = NavigationPoint(RouteCache[n*0.5]);
|
||||
MidGoals[1] = NavigationPoint(RouteCache[n]);
|
||||
if( MidGoals[0]==MidGoals[1] )
|
||||
ReachOffset = 1;
|
||||
else ReachOffset = 0;
|
||||
}
|
||||
|
||||
function bool CanKillMeYet()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
state PatFindWay
|
||||
{
|
||||
Ignores Timer,SeePlayer,HearNoise,DamageAttitudeTo,EnemyChanged,Startle,Tick;
|
||||
|
||||
final function PickDestination()
|
||||
{
|
||||
if( ReachOffset>=2 )
|
||||
{
|
||||
GotoState('ZombieHunt');
|
||||
return;
|
||||
}
|
||||
if( ActorReachable(MidGoals[ReachOffset]) )
|
||||
{
|
||||
MoveTarget = MidGoals[ReachOffset];
|
||||
++ReachOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveTarget = FindPathToward(MidGoals[ReachOffset]);
|
||||
if( MoveTarget==None )
|
||||
++ReachOffset;
|
||||
}
|
||||
}
|
||||
function BreakUpDoor( KFDoorMover Other, bool bTryDistanceAttack )
|
||||
{
|
||||
Global.BreakUpDoor(Other,bTryDistanceAttack);
|
||||
Pawn.GoToState('');
|
||||
}
|
||||
Begin:
|
||||
PickDestination();
|
||||
if( MoveTarget==None )
|
||||
Sleep(0.5f);
|
||||
else MoveToward(MoveTarget,MoveTarget,,False);
|
||||
GoTo'Begin';
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
157
kf_sources/ScrnZedPack/Classes/HardPat_CIRCUS.uc
Normal file
157
kf_sources/ScrnZedPack/Classes/HardPat_CIRCUS.uc
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class HardPat_CIRCUS extends HardPat;
|
||||
|
||||
#exec OBJ LOAD FILE=KF_EnemiesFinalSnd_CIRCUS.uax
|
||||
|
||||
simulated function CloakBoss()
|
||||
{
|
||||
local Controller C;
|
||||
local int Index;
|
||||
|
||||
if ( bSpotted )
|
||||
{
|
||||
Visibility = 120;
|
||||
|
||||
if ( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[0] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[1] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[2] = Finalblend'KFX.StalkerGlow';
|
||||
bUnlit = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Visibility = 1;
|
||||
bCloaked = true;
|
||||
|
||||
if ( Level.NetMode!=NM_Client )
|
||||
{
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if ( C.bIsPlayer && C.Enemy==Self )
|
||||
{
|
||||
C.Enemy = None; // Make bots lose sight with me.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[1] = Shader'KF_Specimens_Trip_T.patriarch_invisible_gun';
|
||||
Skins[0] = Shader'KF_Specimens_Trip_T.patriarch_invisible';
|
||||
|
||||
// Invisible - no shadow
|
||||
if(PlayerShadow != none)
|
||||
{
|
||||
PlayerShadow.bShadowActive = false;
|
||||
}
|
||||
|
||||
// Remove/disallow projectors on invisible people
|
||||
Projectors.Remove(0, Projectors.Length);
|
||||
bAcceptsProjectors = false;
|
||||
SetOverlayMaterial(FinalBlend'KF_Specimens_Trip_T.patriarch_fizzle_FB', 1.0, true);
|
||||
|
||||
// Randomly send out a message about Patriarch going invisible(10% chance)
|
||||
if ( FRand() < 0.10 )
|
||||
{
|
||||
// Pick a random Player to say the message
|
||||
Index = Rand(Level.Game.NumPlayers);
|
||||
|
||||
for ( C = Level.ControllerList; C != none; C = C.NextController )
|
||||
{
|
||||
if ( PlayerController(C) != none )
|
||||
{
|
||||
if ( Index == 0 )
|
||||
{
|
||||
PlayerController(C).Speech('AUTO', 8, "");
|
||||
break;
|
||||
}
|
||||
|
||||
Index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Speech notifies called from the anims
|
||||
function PatriarchKnockDown()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_KnockedDown', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchEntrance()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Entrance', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchVictory()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Victory', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchMGPreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_WarnGun', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
function PatriarchMisslePreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_WarnRocket', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
// Taunt to use when doing the melee exploit radial attack
|
||||
function PatriarchRadialTaunt()
|
||||
{
|
||||
if( NumNinjas > 0 && NumNinjas > NumLumberJacks )
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_TauntNinja', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
else if( NumLumberJacks > 0 && NumLumberJacks > NumNinjas )
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_TauntLumberJack', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_TauntRadial', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
}
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{//should be derived and used.
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_CIRCUS_T.Patriarch_Circus.Patriarch_Circus_CMB');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.gatling_cmb');
|
||||
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.gatling_D');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.PatGungoInvisible_cmb');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_invisible');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_invisible_gun');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_fizzle_FB');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
SaveMeSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_SaveMe'
|
||||
RocketFireSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_FireRocket'
|
||||
MeleeImpaleHitSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_HitPlayer_Impale'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_HitPlayer_Fist'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPatriarch_CIRCUS'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPatriarch_CIRCUS'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPatriarch_CIRCUS'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_Death'
|
||||
MenuName="Hard Ringmaster"
|
||||
AmbientSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Patriarch.Kev_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip_CIRCUS.Patriarch_Circus'
|
||||
Skins(0)=Combiner'KF_Specimens_Trip_CIRCUS_T.Patriarch_Circus.Patriarch_Circus_CMB'
|
||||
Skins(1)=Combiner'KF_Specimens_Trip_T.gatling_cmb'
|
||||
}
|
||||
8
kf_sources/ScrnZedPack/Classes/HardPat_GRITTIER.uc
Normal file
8
kf_sources/ScrnZedPack/Classes/HardPat_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
class HardPat_GRITTIER extends HardPat;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MenuName="Hard Grittier Pat"
|
||||
Skins(1)=Combiner'ScrnZedPack_T.patriarch_grittier.patriarch_grittier_cmb'
|
||||
}
|
||||
152
kf_sources/ScrnZedPack/Classes/HardPat_HALLOWEEN.uc
Normal file
152
kf_sources/ScrnZedPack/Classes/HardPat_HALLOWEEN.uc
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class HardPat_HALLOWEEN extends HardPat;
|
||||
|
||||
|
||||
#exec OBJ LOAD FILE=KF_EnemiesFinalSnd_HALLOWEEN.uax
|
||||
|
||||
simulated function CloakBoss()
|
||||
{
|
||||
local Controller C;
|
||||
local int Index;
|
||||
|
||||
// No cloaking if zapped
|
||||
if( bZapped )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bSpotted )
|
||||
{
|
||||
Visibility = 120;
|
||||
|
||||
if ( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[0] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[1] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[2] = Finalblend'KFX.StalkerGlow';
|
||||
bUnlit = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Visibility = 1;
|
||||
bCloaked = true;
|
||||
|
||||
if ( Level.NetMode!=NM_Client )
|
||||
{
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if ( C.bIsPlayer && C.Enemy==Self )
|
||||
{
|
||||
C.Enemy = None; // Make bots lose sight with me.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[1] = Shader'KF_Specimens_Trip_HALLOWEEN_T.Patriarch.Patriarch_Halloween_Invisible';
|
||||
Skins[0] = Shader'KF_Specimens_Trip_T.patriarch_invisible_gun';
|
||||
|
||||
// Invisible - no shadow
|
||||
if(PlayerShadow != none)
|
||||
{
|
||||
PlayerShadow.bShadowActive = false;
|
||||
}
|
||||
|
||||
// Remove/disallow projectors on invisible people
|
||||
Projectors.Remove(0, Projectors.Length);
|
||||
bAcceptsProjectors = false;
|
||||
SetOverlayMaterial(FinalBlend'KF_Specimens_Trip_T.patriarch_fizzle_FB', 1.0, true);
|
||||
|
||||
// Randomly send out a message about Patriarch going invisible(10% chance)
|
||||
if ( FRand() < 0.10 )
|
||||
{
|
||||
// Pick a random Player to say the message
|
||||
Index = Rand(Level.Game.NumPlayers);
|
||||
|
||||
for ( C = Level.ControllerList; C != none; C = C.NextController )
|
||||
{
|
||||
if ( PlayerController(C) != none )
|
||||
{
|
||||
if ( Index == 0 )
|
||||
{
|
||||
PlayerController(C).Speech('AUTO', 8, "");
|
||||
break;
|
||||
}
|
||||
|
||||
Index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Speech notifies called from the anims
|
||||
function PatriarchKnockDown()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_KnockedDown', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchEntrance()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Entrance', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchVictory()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Victory', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchMGPreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_WarnGun', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
function PatriarchMisslePreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_WarnRocket', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
// Taunt to use when doing the melee exploit radial attack
|
||||
function PatriarchRadialTaunt()
|
||||
{
|
||||
if( NumNinjas > 0 && NumNinjas > NumLumberJacks )
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_TauntNinja', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
else if( NumLumberJacks > 0 && NumLumberJacks > NumNinjas )
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_TauntLumberJack', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_TauntRadial', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
SaveMeSound=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_SaveMe'
|
||||
RocketFireSound=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_FireRocket'
|
||||
MeleeImpaleHitSound=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_HitPlayer_Impale'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_HitPlayer_Fist'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPatriarch_HALLOWEEN'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPatriarch_HALLOWEEN'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPatriarch_HALLOWEEN'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd_HALLOWEEN.Patriarch.Kev_Death'
|
||||
MenuName="Hard Sheriff"
|
||||
AmbientSound=Sound'KF_BasePatriarch_HALLOWEEN.Kev_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip_HALLOWEEN.Patriarch_Halloween'
|
||||
Skins(1)=Combiner'KF_Specimens_Trip_HALLOWEEN_T.Patriarch.Patriarch_RedneckZombie_CMB'
|
||||
}
|
||||
154
kf_sources/ScrnZedPack/Classes/HardPat_XMAS.uc
Normal file
154
kf_sources/ScrnZedPack/Classes/HardPat_XMAS.uc
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class HardPat_XMAS extends HardPat;
|
||||
|
||||
#exec OBJ LOAD FILE=KF_EnemiesFinalSnd_Xmas.uax
|
||||
#exec OBJ LOAD FILE=KF_Specimens_Trip_XMAS_T.utx
|
||||
|
||||
simulated function CloakBoss()
|
||||
{
|
||||
local Controller C;
|
||||
local int Index;
|
||||
|
||||
// No cloaking if zapped
|
||||
if( bZapped )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bSpotted )
|
||||
{
|
||||
Visibility = 120;
|
||||
|
||||
if ( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[0] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[1] = Finalblend'KFX.StalkerGlow';
|
||||
bUnlit = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Visibility = 1;
|
||||
bCloaked = true;
|
||||
|
||||
if ( Level.NetMode!=NM_Client )
|
||||
{
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if ( C.bIsPlayer && C.Enemy==Self )
|
||||
{
|
||||
C.Enemy = None; // Make bots lose sight with me.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
{
|
||||
Return;
|
||||
}
|
||||
|
||||
Skins[1] = Shader'KF_Specimens_Trip_T.patriarch_invisible_gun';
|
||||
Skins[0] = Shader'KF_Specimens_Trip_XMAS_T.patriarch_Santa.patriarch_santa_invisible_shdr';
|
||||
|
||||
// Invisible - no shadow
|
||||
if(PlayerShadow != none)
|
||||
{
|
||||
PlayerShadow.bShadowActive = false;
|
||||
}
|
||||
|
||||
// Remove/disallow projectors on invisible people
|
||||
Projectors.Remove(0, Projectors.Length);
|
||||
bAcceptsProjectors = false;
|
||||
SetOverlayMaterial(FinalBlend'KF_Specimens_Trip_T.patriarch_fizzle_FB', 1.0, true);
|
||||
|
||||
// Randomly send out a message about Patriarch going invisible(10% chance)
|
||||
if ( FRand() < 0.10 )
|
||||
{
|
||||
// Pick a random Player to say the message
|
||||
Index = Rand(Level.Game.NumPlayers);
|
||||
|
||||
for ( C = Level.ControllerList; C != none; C = C.NextController )
|
||||
{
|
||||
if ( PlayerController(C) != none )
|
||||
{
|
||||
if ( Index == 0 )
|
||||
{
|
||||
PlayerController(C).Speech('AUTO', 8, "");
|
||||
break;
|
||||
}
|
||||
|
||||
Index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Speech notifies called from the anims
|
||||
function PatriarchKnockDown()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_KnockedDown', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchEntrance()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Entrance', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchVictory()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Victory', SLOT_Misc, 2.0,true,500.0);
|
||||
}
|
||||
|
||||
function PatriarchMGPreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_WarnGun', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
function PatriarchMisslePreFire()
|
||||
{
|
||||
PlaySound(SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_WarnRocket', SLOT_Misc, 2.0,true,1000.0);
|
||||
}
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{//should be derived and used.
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_XMAS_T.gatling_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.gatling_env_cmb');
|
||||
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.gatling_D');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.PatGungoInvisible_cmb');
|
||||
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_XMAS_T.patriarch_Santa.patriarch_Santa_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_XMAS_T.patriarch_Santa_env_cmb');
|
||||
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_XMAS_T.patriarch_Santa_Diff');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_invisible');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_invisible_gun');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.patriarch_fizzle_FB');
|
||||
//myLevel.AddPrecacheMaterial(Texture'kf_fx_trip_t.Gore.Patriarch_Gore_Limbs_Diff');
|
||||
//myLevel.AddPrecacheMaterial(Texture'kf_fx_trip_t.Gore.Patriarch_Gore_Limbs_Spec');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
SaveMeSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_SaveMe'
|
||||
RocketFireSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_FireRocket'
|
||||
MiniGunFireSound=Sound'KF_BasePatriarch_xmas.Attack.Kev_MG_GunfireLoop'
|
||||
MiniGunSpinSound=Sound'KF_BasePatriarch_xmas.Attack.Kev_MG_TurbineFireLoop'
|
||||
MeleeImpaleHitSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_HitPlayer_Impale'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_HitPlayer_Fist'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPatriarch_XMas'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPatriarch_XMas'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPatriarch_XMas'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_Death'
|
||||
MenuName="Hard Santa"
|
||||
AmbientSound=SoundGroup'KF_EnemiesFinalSnd_Xmas.Patriarch.Kev_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip_Xmas.SantaClause_Patriarch'
|
||||
Skins(0)=Combiner'KF_Specimens_Trip_XMAS_T.patriarch_Santa.patriarch_Santa_cmb'
|
||||
Skins(1)=Combiner'KF_Specimens_Trip_XMAS_T.gatling_cmb'
|
||||
}
|
||||
72
kf_sources/ScrnZedPack/Classes/HuskFireProjectileSE.uc
Normal file
72
kf_sources/ScrnZedPack/Classes/HuskFireProjectileSE.uc
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
class HuskFireProjectileSE extends KFChar.HuskFireProjectile;
|
||||
|
||||
simulated singular function Touch(Actor Other)
|
||||
{
|
||||
local vector HitLocation, HitNormal;
|
||||
|
||||
//Don't touch bulletwhip attachment. Taken from HuskFireProjectile
|
||||
if ( Other == None || KFBulletWhipAttachment(Other) != none )
|
||||
return;
|
||||
if ( Other.bProjTarget || Other.bBlockActors ) {
|
||||
LastTouched = Other;
|
||||
if ( Velocity == vect(0,0,0) || Other.IsA('Mover') ) {
|
||||
ProcessTouch(Other,Location);
|
||||
LastTouched = None;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Other.TraceThisActor(HitLocation, HitNormal, Location, Location - 2*Velocity, GetCollisionExtent()) )
|
||||
HitLocation = Location;
|
||||
|
||||
ProcessTouch(Other, HitLocation);
|
||||
LastTouched = None;
|
||||
if ( (Role < ROLE_Authority) && (Other.Role == ROLE_Authority) && (Pawn(Other) != None) )
|
||||
ClientSideTouch(Other, HitLocation);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't hit Zed extra collision cylinders
|
||||
simulated function ProcessTouch(Actor Other, Vector HitLocation)
|
||||
{
|
||||
if ( ExtendedZCollision(Other) != none /* || Other.IsA('KFMonster') */ )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't let it hit this player, or blow up on another player
|
||||
if (Other == none || Other == Instigator || Other.Base == Instigator)
|
||||
return;
|
||||
// Don't collide with bullet whip attachments
|
||||
if (KFBulletWhipAttachment(Other) != none) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the instigator's location if it exists. This fixes issues with
|
||||
// the original location of the projectile being really far away from
|
||||
// the real Origloc due to it taking a couple of milliseconds to
|
||||
// replicate the location to the client and the first replicated location has
|
||||
// already moved quite a bit.
|
||||
if (Instigator != none) {
|
||||
OrigLoc = Instigator.Location;
|
||||
}
|
||||
if (!bDud && ((VSizeSquared(Location - OrigLoc) < ArmDistSquared) || OrigLoc == vect(0,0,0))) {
|
||||
if( Role == ROLE_Authority ) {
|
||||
AmbientSound=none;
|
||||
PlaySound(Sound'ProjectileSounds.PTRD_deflect04',,2.0);
|
||||
Other.TakeDamage( ImpactDamage, Instigator, HitLocation, Normal(Velocity), ImpactDamageType );
|
||||
}
|
||||
|
||||
bDud = true;
|
||||
Velocity = vect(0,0,0);
|
||||
LifeSpan=1.0;
|
||||
SetPhysics(PHYS_Falling);
|
||||
}
|
||||
|
||||
if (!bDud) {
|
||||
Explode(HitLocation,Normal(HitLocation-Other.Location));
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
215
kf_sources/ScrnZedPack/Classes/HuskZombieControllerSE.uc
Normal file
215
kf_sources/ScrnZedPack/Classes/HuskZombieControllerSE.uc
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
// Code originally was taken from Scary Ghost's Super Zombies mutator
|
||||
class HuskZombieControllerSE extends HuskZombieController;
|
||||
|
||||
var float aimAtFeetZDelta;
|
||||
|
||||
function bool DefendMelee(float Dist)
|
||||
{
|
||||
return (Dist < 1000);
|
||||
}
|
||||
|
||||
function rotator AdjustAim(FireProperties FiredAmmunition, vector projStart, int aimerror)
|
||||
{
|
||||
local rotator FireRotation, TargetLook;
|
||||
local float FireDist, TargetDist, ProjSpeed;
|
||||
local actor HitActor;
|
||||
local vector FireSpot, FireDir, TargetVel, HitLocation, HitNormal;
|
||||
local int realYaw;
|
||||
local bool bDefendCloseRange, bClean, bLeadTargetNow;
|
||||
local bool bWantsToAimAtFeet;
|
||||
|
||||
if ( FiredAmmunition.ProjectileClass != None )
|
||||
projspeed = FiredAmmunition.ProjectileClass.default.speed;
|
||||
|
||||
// make sure bot has a valid target
|
||||
if ( Target == None ) {
|
||||
Target = Enemy;
|
||||
if ( Target == None )
|
||||
return Rotation;
|
||||
}
|
||||
FireSpot = Target.Location;
|
||||
|
||||
TargetDist = VSize(Target.Location - Pawn.Location);
|
||||
|
||||
// perfect aim at stationary objects
|
||||
if ( Pawn(Target) == None ) {
|
||||
if ( !FiredAmmunition.bTossed )
|
||||
return rotator(Target.Location - projstart);
|
||||
else {
|
||||
FireDir = AdjustToss(projspeed,ProjStart,Target.Location,true);
|
||||
SetRotation(Rotator(FireDir));
|
||||
return Rotation;
|
||||
}
|
||||
}
|
||||
|
||||
bLeadTargetNow = FiredAmmunition.bLeadTarget && bLeadTarget;
|
||||
bDefendCloseRange = ( (Target == Enemy) && DefendMelee(TargetDist) );
|
||||
aimerror = AdjustAimError(aimerror,TargetDist,bDefendCloseRange,FiredAmmunition.bInstantHit, bLeadTargetNow);
|
||||
|
||||
// lead target with non instant hit projectiles
|
||||
if ( bLeadTargetNow ) {
|
||||
TargetVel = Target.Velocity;
|
||||
// hack guess at projecting falling velocity of target
|
||||
if ( Target.Physics == PHYS_Falling) {
|
||||
if ( Target.PhysicsVolume.Gravity.Z <= Target.PhysicsVolume.Default.Gravity.Z ) {
|
||||
TargetVel.Z = FMin(TargetVel.Z + FMax(-400, Target.PhysicsVolume.Gravity.Z * FMin(1,TargetDist/projSpeed)),0);
|
||||
} else {
|
||||
TargetVel.Z = FMin(0, TargetVel.Z);
|
||||
}
|
||||
}
|
||||
// more or less lead target (with some random variation)
|
||||
FireSpot += FMin(1, 0.7 + 0.6 * FRand()) * TargetVel * TargetDist/projSpeed;
|
||||
FireSpot.Z = FMin(Target.Location.Z, FireSpot.Z);
|
||||
/**
|
||||
* If the target is within 1000uu, offset the Z coordinate of the
|
||||
* FireSpot vector with aimAtFeetZDelta. Otherwise, the husk will
|
||||
* aim at behind the target, not at his feet.
|
||||
*/
|
||||
if (aimAtFeetZDelta != 0.0 && Target.Physics == PHYS_Falling && bDefendCloseRange) {
|
||||
FireSpot.Z= Pawn.Location.Z + aimAtFeetZDelta;
|
||||
}
|
||||
|
||||
if ( (Target.Physics != PHYS_Falling) && (FRand() < 0.55) && (VSize(FireSpot - ProjStart) > 1000) ) {
|
||||
// don't always lead far away targets, especially if they are moving sideways with respect to the bot
|
||||
TargetLook = Target.Rotation;
|
||||
if ( Target.Physics == PHYS_Walking )
|
||||
TargetLook.Pitch = 0;
|
||||
bClean = ( ((Vector(TargetLook) Dot Normal(Target.Velocity)) >= 0.71) && FastTrace(FireSpot, ProjStart) );
|
||||
}
|
||||
else // make sure that bot isn't leading into a wall
|
||||
bClean = FastTrace(FireSpot, ProjStart);
|
||||
if ( !bClean) {
|
||||
// reduce amount of leading
|
||||
if ( FRand() < 0.3 )
|
||||
FireSpot = Target.Location;
|
||||
else
|
||||
FireSpot = 0.5 * (FireSpot + Target.Location);
|
||||
}
|
||||
}
|
||||
|
||||
bClean = false; //so will fail first check unless shooting at feet
|
||||
// Randomly determine if we should try and splash damage with the fire projectile
|
||||
|
||||
if( FiredAmmunition.bTrySplash ) {
|
||||
if( Skill < 2.0 ) {
|
||||
if(FRand() > 0.85) {
|
||||
bWantsToAimAtFeet = true;
|
||||
}
|
||||
}
|
||||
else if( Skill < 3.0 ) {
|
||||
if(FRand() > 0.5) {
|
||||
bWantsToAimAtFeet = true;
|
||||
}
|
||||
}
|
||||
else if( Skill >= 3.0 ) {
|
||||
if(FRand() > 0.25) {
|
||||
bWantsToAimAtFeet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( FiredAmmunition.bTrySplash && (Pawn(Target) != None) && (((Target.Physics == PHYS_Falling)
|
||||
&& (Pawn.Location.Z + 80 >= Target.Location.Z)) || ((Pawn.Location.Z + 19 >= Target.Location.Z)
|
||||
&& (bDefendCloseRange || bWantsToAimAtFeet))) ) {
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot - vect(0,0,1) * (Target.CollisionHeight + 10), FireSpot, false);
|
||||
|
||||
bClean = (HitActor == None);
|
||||
//So if we're too close, and not jumping, bClean is false
|
||||
//same distance but jumping, bClean is true
|
||||
if ( !bClean ) {
|
||||
FireSpot = HitLocation + vect(0,0,3);
|
||||
bClean = FastTrace(FireSpot, ProjStart);
|
||||
}
|
||||
else
|
||||
bClean = ( (Target.Physics == PHYS_Falling) && FastTrace(FireSpot, ProjStart) );
|
||||
/**
|
||||
* Update the aimAtFeetZDelta variable with the appropriate offset
|
||||
* once the Husk decides to aim at the target's feet. Update the
|
||||
* default property so all Super Husks can access it
|
||||
*/
|
||||
if (bClean && TargetDist > 625.0) {
|
||||
aimAtFeetZDelta= FireSpot.Z - Pawn.Location.Z;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bClean ) {
|
||||
//try middle
|
||||
FireSpot.Z = Target.Location.Z;
|
||||
bClean = FastTrace(FireSpot, ProjStart);
|
||||
}
|
||||
if ( FiredAmmunition.bTossed && !bClean && bEnemyInfoValid ) {
|
||||
FireSpot = LastSeenPos;
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != None ) {
|
||||
bCanFire = false;
|
||||
FireSpot += 2 * Target.CollisionHeight * HitNormal;
|
||||
}
|
||||
bClean = true;
|
||||
}
|
||||
|
||||
if( !bClean ) {
|
||||
// try head
|
||||
FireSpot.Z = Target.Location.Z + 0.9 * Target.CollisionHeight;
|
||||
bClean = FastTrace(FireSpot, ProjStart);
|
||||
}
|
||||
if ( !bClean && (Target == Enemy) && bEnemyInfoValid ) {
|
||||
FireSpot = LastSeenPos;
|
||||
if ( Pawn.Location.Z >= LastSeenPos.Z )
|
||||
FireSpot.Z -= 0.4 * Enemy.CollisionHeight;
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != None ) {
|
||||
FireSpot = LastSeenPos + 2 * Enemy.CollisionHeight * HitNormal;
|
||||
if ( Monster(Pawn).SplashDamage() && (Skill >= 4) ) {
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != None )
|
||||
FireSpot += 2 * Enemy.CollisionHeight * HitNormal;
|
||||
}
|
||||
bCanFire = false;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust for toss distance
|
||||
if ( FiredAmmunition.bTossed ) {
|
||||
FireDir = AdjustToss(projspeed,ProjStart,FireSpot,true);
|
||||
}
|
||||
else {
|
||||
FireDir = FireSpot - ProjStart;
|
||||
}
|
||||
|
||||
FireRotation = Rotator(FireDir);
|
||||
realYaw = FireRotation.Yaw;
|
||||
InstantWarnTarget(Target,FiredAmmunition,vector(FireRotation));
|
||||
|
||||
FireRotation.Yaw = SetFireYaw(FireRotation.Yaw + aimerror);
|
||||
FireDir = vector(FireRotation);
|
||||
// avoid shooting into wall
|
||||
FireDist = FMin(VSize(FireSpot-ProjStart), 400);
|
||||
FireSpot = ProjStart + FireDist * FireDir;
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != None ) {
|
||||
if ( HitNormal.Z < 0.7 ) {
|
||||
FireRotation.Yaw = SetFireYaw(realYaw - aimerror);
|
||||
FireDir = vector(FireRotation);
|
||||
FireSpot = ProjStart + FireDist * FireDir;
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
}
|
||||
if ( HitActor != None ) {
|
||||
FireSpot += HitNormal * 2 * Target.CollisionHeight;
|
||||
if ( Skill >= 4 ) {
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != None )
|
||||
FireSpot += Target.CollisionHeight * HitNormal;
|
||||
}
|
||||
FireDir = Normal(FireSpot - ProjStart);
|
||||
FireRotation = rotator(FireDir);
|
||||
}
|
||||
}
|
||||
|
||||
//Make it so the Husk always shoots the ground it the target is close
|
||||
SetRotation(FireRotation);
|
||||
return FireRotation;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
69
kf_sources/ScrnZedPack/Classes/JasonZombieController.uc
Normal file
69
kf_sources/ScrnZedPack/Classes/JasonZombieController.uc
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
class JasonZombieController extends KFMonsterController;
|
||||
// Custom Zombie Thinkerating
|
||||
// By : Alex
|
||||
|
||||
var bool bDoneSpottedCheck;
|
||||
|
||||
state ZombieHunt
|
||||
{
|
||||
event SeePlayer(Pawn SeenPlayer)
|
||||
{
|
||||
if ( !bDoneSpottedCheck && PlayerController(SeenPlayer.Controller) != none )
|
||||
{
|
||||
// 25% chance of first player to see this Scrake saying something
|
||||
if ( !KFGameType(Level.Game).bDidSpottedScrakeMessage && FRand() < 0.25 )
|
||||
{
|
||||
PlayerController(SeenPlayer.Controller).Speech('AUTO', 13, "");
|
||||
KFGameType(Level.Game).bDidSpottedScrakeMessage = true;
|
||||
}
|
||||
|
||||
bDoneSpottedCheck = true;
|
||||
}
|
||||
|
||||
super.SeePlayer(SeenPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
function TimedFireWeaponAtEnemy()
|
||||
{
|
||||
if ( (Enemy == None) || FireWeaponAt(Enemy) )
|
||||
SetCombatTimer();
|
||||
else SetTimer(0.01, True);
|
||||
}
|
||||
|
||||
state ZombieCharge
|
||||
{
|
||||
// Don't do this in this state
|
||||
function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}
|
||||
|
||||
function bool StrafeFromDamage(float Damage, class<DamageType> DamageType, bool bFindDest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
function bool TryStrafe(vector sideDir)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
function Timer()
|
||||
{
|
||||
Disable('NotifyBump');
|
||||
Target = Enemy;
|
||||
TimedFireWeaponAtEnemy();
|
||||
}
|
||||
|
||||
WaitForAnim:
|
||||
|
||||
While( Monster(Pawn).bShotAnim )
|
||||
Sleep(0.25);
|
||||
if ( !FindBestPathToward(Enemy, false,true) )
|
||||
GotoState('ZombieRestFormation');
|
||||
Moving:
|
||||
MoveToward(Enemy);
|
||||
WhatToDoNext(17);
|
||||
if ( bSoaking )
|
||||
SoakStop("STUCK IN CHARGING!");
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredArmBrute.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredArmBrute.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredArmBrute extends SeveredArm;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Brute.Brute_Right_Arm'
|
||||
}
|
||||
7
kf_sources/ScrnZedPack/Classes/SeveredArmFFP.uc
Normal file
7
kf_sources/ScrnZedPack/Classes/SeveredArmFFP.uc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class SeveredArmFFP extends SeveredArm;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawType=DT_Mesh
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.ffp_arm'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredArmShiver.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredArmShiver.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredArmShiver extends SeveredArm;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Shiver.Shiver_Arm'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredArmTeslaHusk.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredArmTeslaHusk.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredArmTeslaHusk extends SeveredArm;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.TeslaHusk.TeslaHusk_arm_gore'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredGunTeslaHusk.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredGunTeslaHusk.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredGunTeslaHusk extends SeveredArm;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.TeslaHusk.TeslaHusk_gun_gore'
|
||||
}
|
||||
16
kf_sources/ScrnZedPack/Classes/SeveredHeadBrute.uc
Normal file
16
kf_sources/ScrnZedPack/Classes/SeveredHeadBrute.uc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//=============================================================================
|
||||
// SeveredHeadPound
|
||||
//=============================================================================
|
||||
// Detached head gib class for the FleshPound
|
||||
//=============================================================================
|
||||
// Killing Floor Source
|
||||
// Copyright (C) 2009 Tripwire Interactive LLC
|
||||
// - John "Ramm-Jaeger" Gibson
|
||||
//=============================================================================
|
||||
|
||||
class SeveredHeadBrute extends SeveredHead;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Brute.Brute_head'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredHeadShiver.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredHeadShiver.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredHeadShiver extends SeveredHead;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Shiver.Shiver_Head'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredHeadTeslaHusk.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredHeadTeslaHusk.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredHeadTeslaHusk extends SeveredHead;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.TeslaHusk.TeslaHusk_head_gore'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredLegBrute.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredLegBrute.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredLegBrute extends SeveredLeg;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Brute.Brute_Left_Leg'
|
||||
}
|
||||
7
kf_sources/ScrnZedPack/Classes/SeveredLegFFP.uc
Normal file
7
kf_sources/ScrnZedPack/Classes/SeveredLegFFP.uc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class SeveredLegFFP extends SeveredLeg;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawType=DT_Mesh
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.ffp_leg'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredLegShiver.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredLegShiver.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredLegShiver extends SeveredLeg;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.Shiver.Shiver_Leg'
|
||||
}
|
||||
6
kf_sources/ScrnZedPack/Classes/SeveredLegTeslaHusk.uc
Normal file
6
kf_sources/ScrnZedPack/Classes/SeveredLegTeslaHusk.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class SeveredLegTeslaHusk extends SeveredLeg;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
StaticMesh=StaticMesh'ScrnZedPack_SM.TeslaHusk.TeslaHusk_leg_gore'
|
||||
}
|
||||
235
kf_sources/ScrnZedPack/Classes/TeslaBeam.uc
Normal file
235
kf_sources/ScrnZedPack/Classes/TeslaBeam.uc
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
// most of the code c&p from ZEDBeamEffect
|
||||
|
||||
class TeslaBeam extends xEmitter;
|
||||
|
||||
var array<TeslaBeam> ChildBeams;
|
||||
|
||||
var Actor StartActor, EndActor; // actors to chain with beam
|
||||
var name StartBoneName, EndBoneName; // bone names of StartActor/EndActor to use for beam ending locations
|
||||
|
||||
var transient float EffectEndTime; // time when beam should be hidden. 0 - don't hide
|
||||
|
||||
var ZedBeamSparks Sparks;
|
||||
var Vector PrevLoc;
|
||||
var Rotator PrevRot;
|
||||
|
||||
|
||||
var Vector StartEffect, EndEffect;
|
||||
|
||||
var transient protected bool bInstigatorReplicated; // not sure if we need this
|
||||
var transient protected float DestroyTime;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if ( Role == ROLE_Authority && bNetDirty )
|
||||
StartActor, EndActor, StartBoneName, EndBoneName,
|
||||
EffectEndTime;
|
||||
}
|
||||
|
||||
simulated function PostNetReceive()
|
||||
{
|
||||
bInstigatorReplicated = bInstigatorReplicated || Instigator != none;
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
|
||||
if ( TeslaHusk(Owner) != none )
|
||||
Instigator = TeslaHusk(Owner);
|
||||
}
|
||||
|
||||
// returns item index of ChildBeams array, which has ChainedActor as an EndActor
|
||||
// returns -1, if ChainedActor isn't chained to EndActor
|
||||
function int ChildIndex(Actor ChainedActor)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if ( ChainedActor != none ) {
|
||||
for ( i=0; i<ChildBeams.Length; ++i ) {
|
||||
if ( ChildBeams[i] != none && ChildBeams[i].EndActor == ChainedActor)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function bool IsChainedTo(Actor Other, optional byte ChainLevel)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if ( Other == none || ChainLevel > 100 ) // prevents circular links
|
||||
return false;
|
||||
|
||||
for ( i=0; i<ChildBeams.Length; ++i ) {
|
||||
if ( ChildBeams[i] != none && (ChildBeams[i].EndActor == Other || ChildBeams[i].IsChainedTo(Other, ChainLevel+1)) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function DestroyChildBeams()
|
||||
{
|
||||
local int i;
|
||||
|
||||
for ( i=0; i<ChildBeams.Length; ++i ) {
|
||||
if ( ChildBeams[i] != none ) {
|
||||
ChildBeams[i].Instigator = none;
|
||||
}
|
||||
}
|
||||
ChildBeams.Length = 0;
|
||||
}
|
||||
|
||||
simulated function Destroyed()
|
||||
{
|
||||
if ( Sparks != None )
|
||||
{
|
||||
Sparks.SetTimer(0, false);
|
||||
Sparks.mRegen = false;
|
||||
Sparks.LightType = LT_None;
|
||||
}
|
||||
|
||||
if ( ChildBeams.Length > 0 )
|
||||
DestroyChildBeams();
|
||||
|
||||
Super.Destroyed();
|
||||
}
|
||||
|
||||
simulated function SetBeamLocation()
|
||||
{
|
||||
if ( StartBoneName == '' )
|
||||
StartEffect = StartActor.Location;
|
||||
else {
|
||||
StartEffect = StartActor.GetBoneCoords(StartBoneName).Origin;
|
||||
}
|
||||
|
||||
if ( EndBoneName == '' )
|
||||
EndEffect = EndActor.Location;
|
||||
else {
|
||||
EndEffect = EndActor.GetBoneCoords(EndBoneName).Origin;
|
||||
}
|
||||
|
||||
SetLocation(StartEffect);
|
||||
bHidden = false;
|
||||
}
|
||||
|
||||
simulated function Vector SetBeamRotation()
|
||||
{
|
||||
SetRotation(Rotator(EndEffect - StartEffect));
|
||||
|
||||
return Normal(EndEffect - StartEffect);
|
||||
}
|
||||
|
||||
simulated function bool CheckMaxEffectDistance(PlayerController P, vector SpawnLocation)
|
||||
{
|
||||
return !P.BeyondViewDistance(SpawnLocation,1000);
|
||||
}
|
||||
|
||||
|
||||
simulated function Tick(float dt)
|
||||
{
|
||||
local float LocDiff, RotDiff, WiggleMe;
|
||||
local Vector BeamDir;
|
||||
local PlayerController LocalPC;
|
||||
|
||||
if ( Instigator == none ) {
|
||||
if ( Role == ROLE_Authority ) {
|
||||
if ( Level.NetMode != NM_Standalone && DestroyTime == 0 )
|
||||
DestroyTime = Level.TimeSeconds + 1.0; // give some time to replicate
|
||||
else if ( DestroyTime < Level.TimeSeconds )
|
||||
Destroy();
|
||||
}
|
||||
else if ( bInstigatorReplicated )
|
||||
Destroy();
|
||||
|
||||
bHidden = true;
|
||||
}
|
||||
else {
|
||||
bHidden = StartActor == none || EndActor == none || (EffectEndTime != 0 && EffectEndTime < Level.TimeSeconds);
|
||||
}
|
||||
if ( Sparks != none )
|
||||
Sparks.bHidden = bHidden;
|
||||
if ( bHidden ) {
|
||||
if ( ChildBeams.Length > 0 )
|
||||
DestroyChildBeams(); // destroy them, because they are comming from the EndActor
|
||||
return;
|
||||
}
|
||||
|
||||
// set beam start location
|
||||
SetBeamLocation();
|
||||
BeamDir = SetBeamRotation();
|
||||
|
||||
if ( Level.NetMode != NM_DedicatedServer )
|
||||
{
|
||||
if ( Sparks == None && EffectIsRelevant(EndEffect, false) )
|
||||
{
|
||||
LocalPC = Level.GetLocalPlayerController();
|
||||
if ( LocalPC != none && CheckMaxEffectDistance(LocalPC, Location) )
|
||||
Sparks = Spawn(class'ZedBeamSparks', self);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if ( Level.bDropDetail || Level.DetailMode == DM_Low )
|
||||
{
|
||||
bDynamicLight = false;
|
||||
LightType = LT_None;
|
||||
}
|
||||
else if ( bDynamicLight )
|
||||
LightType = LT_Steady;
|
||||
*/
|
||||
|
||||
mSpawnVecA = EndEffect;
|
||||
|
||||
LocDiff = VSize((Location - PrevLoc) * Vect(1,1,5));
|
||||
RotDiff = VSize(Vector(Rotation) - Vector(PrevRot));
|
||||
WiggleMe = FMax(LocDiff*0.02, RotDiff*4.0);
|
||||
mWaveAmplitude = FMax(1.0, mWaveAmplitude - mWaveAmplitude*1.0*dt);
|
||||
mWaveAmplitude = FMin(16.0, mWaveAmplitude + WiggleMe);
|
||||
|
||||
PrevLoc = Location;
|
||||
PrevRot = Rotation;
|
||||
|
||||
|
||||
if ( Sparks != None )
|
||||
{
|
||||
Sparks.SetLocation( EndEffect - BeamDir*10.0 );
|
||||
Sparks.SetRotation( Rotation);
|
||||
Sparks.mRegenRange[0] = Sparks.DesiredRegen;
|
||||
Sparks.mRegenRange[1] = Sparks.DesiredRegen;
|
||||
Sparks.bDynamicLight = true;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
mParticleType=PT_Beam
|
||||
mMaxParticles=3
|
||||
mRegenDist=65.000000
|
||||
mSpinRange(0)=45000.000000
|
||||
mSizeRange(0)=6.000000
|
||||
mColorRange(0)=(B=240,G=240,R=240)
|
||||
mColorRange(1)=(B=240,G=240,R=240)
|
||||
mAttenuate=False
|
||||
mAttenKa=0.000000
|
||||
mWaveFrequency=0.060000
|
||||
mWaveAmplitude=8.000000
|
||||
mWaveShift=100000.000000
|
||||
mBendStrength=3.000000
|
||||
mWaveLockEnd=True
|
||||
LightHue=100
|
||||
LightSaturation=100
|
||||
LightBrightness=255.000000
|
||||
LightRadius=4.000000
|
||||
bNetTemporary=False
|
||||
bReplicateInstigator=True
|
||||
bReplicateMovement=False
|
||||
RemoteRole=ROLE_SimulatedProxy
|
||||
NetUpdateFrequency=5.000000
|
||||
LifeSpan=10.000000
|
||||
Skins(0)=FinalBlend'KFZED_FX_T.Energy.ZED_FX_Beam_FB'
|
||||
Style=STY_Additive
|
||||
bNetNotify=True
|
||||
}
|
||||
893
kf_sources/ScrnZedPack/Classes/TeslaHusk.uc
Normal file
893
kf_sources/ScrnZedPack/Classes/TeslaHusk.uc
Normal file
|
|
@ -0,0 +1,893 @@
|
|||
class TeslaHusk extends ZombieHusk;
|
||||
|
||||
#exec OBJ LOAD FILE=KF_EnemiesFinalSnd_CIRCUS.uax
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_A.ukx
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_SM.usx
|
||||
|
||||
|
||||
var class<TeslaBeam> BeamClass;
|
||||
var TeslaBeam PrimaryBeam;
|
||||
var float MaxPrimaryBeamRange; // how far Husk can shoot with his tesla gun?
|
||||
var float MaxChildBeamRange; // max distance from primary target for a chain reaction
|
||||
var float ChainedBeamRangeExtension; // if pawn is already chained, chain max range is multiplied by this value
|
||||
// used for optimization
|
||||
var private float MaxPrimaryBeamRangeSquared, MaxChildBeamRangeSquared;
|
||||
|
||||
var float Energy;
|
||||
var float EnergyMax;
|
||||
var float EnergyRestoreRate;
|
||||
|
||||
var() float DischargeDamage; // beam damage per second
|
||||
var() float ChainDamageMult; // how much damage drops on the next chain
|
||||
var() class<DamageType> MyDamageType;
|
||||
var() byte MaxChainLevel;
|
||||
var() int MaxChainActors;
|
||||
|
||||
var ZedBeamSparks DecapitationSparks;
|
||||
|
||||
var bool bChainThoughZED; // chain tesla beam though a zed, which is between target and the husk, to extend firing range
|
||||
var transient float NextChainZedSearchTime;
|
||||
var transient float ChainRebuildTimer; // how many seconds between rebuilding chained actors
|
||||
|
||||
var float DischargeRate; // time between damaging chained pawns. Do not set it too low due to rounding precission of DischargeDamage
|
||||
var transient float LastDischargeTime;
|
||||
|
||||
// Tesla Husks are able to heal each other.
|
||||
var() float HealRate; // Percent of HealthMax to heal per second
|
||||
var() float HealEnergyDrain; // amount of energy required to heal 1%
|
||||
var transient float NextHealAttemptTime, LastHealTime;
|
||||
|
||||
|
||||
struct SActorDamages
|
||||
{
|
||||
var Actor Victim;
|
||||
var int Damage;
|
||||
};
|
||||
var protected array<SActorDamages> DischargedActors;
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
// Difficulty Scaling
|
||||
if (Level.Game != none && !bDiffAdjusted)
|
||||
{
|
||||
if( Level.Game.GameDifficulty < 2.0 ) {
|
||||
// beginner
|
||||
DischargeDamage *= 0.50;
|
||||
EnergyMax *= 0.50;
|
||||
EnergyRestoreRate *= 0.50;
|
||||
}
|
||||
else if( Level.Game.GameDifficulty < 4.0 ) {
|
||||
// normal
|
||||
}
|
||||
else if( Level.Game.GameDifficulty < 5.0 ) {
|
||||
//hard
|
||||
DischargeDamage *= 1.35;
|
||||
EnergyMax *= 1.35;
|
||||
EnergyRestoreRate *= 1.35;
|
||||
MaxPrimaryBeamRange *= 1.35;
|
||||
MaxChildBeamRange *= 1.35;
|
||||
}
|
||||
else if( Level.Game.GameDifficulty < 7.0 ) {
|
||||
// suicidal
|
||||
DischargeDamage *= 1.55;
|
||||
EnergyMax *= 1.55;
|
||||
EnergyRestoreRate *= 1.55;
|
||||
MaxPrimaryBeamRange *= 1.55;
|
||||
MaxChildBeamRange *= 1.55;
|
||||
}
|
||||
else {
|
||||
// HoE
|
||||
DischargeDamage *= 1.75;
|
||||
EnergyMax *= 1.75;
|
||||
EnergyRestoreRate *= 1.75;
|
||||
MaxPrimaryBeamRange *= 1.75;
|
||||
MaxChildBeamRange *= 1.75;
|
||||
// disabled due to bugs
|
||||
//bChainThoughZED = true;
|
||||
}
|
||||
}
|
||||
Energy = EnergyMax;
|
||||
MaxPrimaryBeamRangeSquared = MaxPrimaryBeamRange * MaxPrimaryBeamRange;
|
||||
MaxChildBeamRangeSquared = MaxChildBeamRange * MaxChildBeamRange;
|
||||
NextHealAttemptTime = Level.TimeSeconds + 5.0;
|
||||
|
||||
super.PostBeginPlay();
|
||||
|
||||
BurnDamageScale = 1.0; // no fire damage resistance
|
||||
}
|
||||
|
||||
simulated function HideBone(name boneName)
|
||||
{
|
||||
local int BoneScaleSlot;
|
||||
local bool bValidBoneToHide;
|
||||
|
||||
if( boneName == LeftThighBone )
|
||||
{
|
||||
boneScaleSlot = 0;
|
||||
bValidBoneToHide = true;
|
||||
}
|
||||
else if ( boneName == RightThighBone )
|
||||
{
|
||||
boneScaleSlot = 1;
|
||||
bValidBoneToHide = true;
|
||||
}
|
||||
else if( boneName == RightFArmBone )
|
||||
{
|
||||
boneScaleSlot = 2;
|
||||
bValidBoneToHide = true;
|
||||
}
|
||||
else if ( boneName == LeftFArmBone )
|
||||
{
|
||||
boneScaleSlot = 3;
|
||||
bValidBoneToHide = true;
|
||||
}
|
||||
else if ( boneName == HeadBone )
|
||||
{
|
||||
// Only scale the bone down once
|
||||
if( SeveredHead == none )
|
||||
{
|
||||
bValidBoneToHide = true;
|
||||
boneScaleSlot = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( boneName == 'spine' )
|
||||
{
|
||||
bValidBoneToHide = true;
|
||||
boneScaleSlot = 5;
|
||||
}
|
||||
|
||||
// Only hide the bone if it is one of the arms, legs, or head, don't hide other misc bones
|
||||
if( bValidBoneToHide )
|
||||
{
|
||||
SetBoneScale(BoneScaleSlot, 0.0, BoneName);
|
||||
}
|
||||
}
|
||||
|
||||
function TeslaBeam SpawnTeslaBeam()
|
||||
{
|
||||
local TeslaBeam beam;
|
||||
|
||||
beam = spawn(BeamClass, self);
|
||||
if ( beam != none ) {
|
||||
beam.Instigator = self;
|
||||
}
|
||||
|
||||
return beam;
|
||||
}
|
||||
|
||||
|
||||
function TeslaBeam SpawnPrimaryBeam()
|
||||
{
|
||||
if ( PrimaryBeam == none ) {
|
||||
PrimaryBeam = SpawnTeslaBeam();
|
||||
PrimaryBeam.StartActor = self;
|
||||
PrimaryBeam.StartBoneName = 'Barrel';
|
||||
}
|
||||
return PrimaryBeam;
|
||||
}
|
||||
|
||||
function FreePrimaryBeam()
|
||||
{
|
||||
if ( PrimaryBeam != none ) {
|
||||
//PrimaryBeam.DestroyChildBeams();
|
||||
PrimaryBeam.EndActor = none;
|
||||
PrimaryBeam.EffectEndTime = Level.TimeSeconds - 1;
|
||||
PrimaryBeam.Instigator = none; // mark to delete
|
||||
PrimaryBeam = none;
|
||||
}
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
local float Dist;
|
||||
local KFMonster M;
|
||||
|
||||
if ( bShotAnim || bDecapitated )
|
||||
return;
|
||||
|
||||
Dist = VSize(A.Location - Location);
|
||||
|
||||
if ( Physics == PHYS_Swimming )
|
||||
{
|
||||
SetAnimAction('Claw');
|
||||
bShotAnim = true;
|
||||
}
|
||||
else if ( Energy < 25 && Dist < MeleeRange + CollisionRadius + A.CollisionRadius ) // do melee hits only when low on energy
|
||||
{
|
||||
bShotAnim = true;
|
||||
SetAnimAction('Claw');
|
||||
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
}
|
||||
else if ( Energy > 25 && Dist < MaxPrimaryBeamRange*(0.7 + 0.3*frand()) )
|
||||
{
|
||||
bShotAnim = true;
|
||||
|
||||
SetAnimAction('ShootBurns');
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0);
|
||||
}
|
||||
else if ( bChainThoughZED && Energy > 50 && Controller.Enemy == A && KFPawn(A) != none
|
||||
&& NextChainZedSearchTime < Level.TimeSeconds
|
||||
&& Dist < MaxPrimaryBeamRange + MaxChildBeamRange )
|
||||
{
|
||||
NextChainZedSearchTime = Level.TimeSeconds + 3.0;
|
||||
foreach VisibleCollidingActors(class'KFMonster', M, MaxPrimaryBeamRange*0.9) {
|
||||
if ( !M.bDeleteMe && M.Health > 0 && TeslaHusk(M) == none
|
||||
&& VSizeSquared(M.Location - A.Location) < MaxChildBeamRangeSquared*0.9
|
||||
&& M.FastTrace(A.Location, M.Location) )
|
||||
{
|
||||
Controller.Target = M;
|
||||
bShotAnim = true;
|
||||
|
||||
SetAnimAction('ShootBurns');
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function n_SpawnBeam()
|
||||
{
|
||||
SpawnPrimaryBeam();
|
||||
if ( PrimaryBeam == none ) {
|
||||
log("Unable to spawn Primary Beam!", 'TeslaHusk');
|
||||
return;
|
||||
}
|
||||
PrimaryBeam.EndActor = Controller.Target;
|
||||
PrimaryBeam.EffectEndTime = Level.TimeSeconds + 2.5;
|
||||
GotoState('Shooting');
|
||||
}
|
||||
|
||||
function SpawnTwoShots()
|
||||
{
|
||||
warn("TeslaHuks.SpawnTwoShots() must not be called");
|
||||
}
|
||||
|
||||
simulated function Tick( float Delta )
|
||||
{
|
||||
if ( Role < ROLE_Authority ) {
|
||||
if ( bDecapitated && Health > 0 && DecapitationSparks == none ) {
|
||||
SpawnDecapitationEffects();
|
||||
}
|
||||
}
|
||||
|
||||
Super(KFMonster).Tick(Delta);
|
||||
|
||||
if ( Role == ROLE_Authority ) {
|
||||
if ( Energy < EnergyMax )
|
||||
Energy += EnergyRestoreRate * Delta;
|
||||
|
||||
if ( Energy > 50 && NextHealAttemptTime < Level.TimeSeconds ) {
|
||||
NextHealAttemptTime = Level.TimeSeconds + 3.0;
|
||||
TryHealing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function TryHealing()
|
||||
{
|
||||
local Controller C;
|
||||
local KFMonsterController MyMC;
|
||||
local KFMonster BestPatient, Candidate;
|
||||
local bool bAnyPatients;
|
||||
|
||||
MyMC = KFMonsterController(Controller);
|
||||
if ( MyMC == none )
|
||||
return; // just in case
|
||||
|
||||
if ( MyMC.Enemy != none && VSizeSquared(MyMC.Enemy.Location - Location) < MaxPrimaryBeamRangeSquared )
|
||||
return; // no healing when need to fight
|
||||
|
||||
for ( C=Level.ControllerList; C!=none; C=C.NextController ) {
|
||||
Candidate = KFMonster(C.Pawn);
|
||||
if ( Candidate != none && Candidate != self && Candidate.Health > 0
|
||||
&& (Candidate.IsA('TeslaHusk') || Candidate.IsA('ZombieFleshpound') || Candidate.IsA('FemaleFP')) )
|
||||
{
|
||||
bAnyPatients = true;
|
||||
if ( (BestPatient == none || Candidate.Health/Candidate.HealthMax < BestPatient.Health/BestPatient.HealthMax )
|
||||
&& VSizeSquared(C.Pawn.Location - Location) < MaxPrimaryBeamRangeSquared )
|
||||
BestPatient = Candidate;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bAnyPatients )
|
||||
NextHealAttemptTime = Level.TimeSeconds + 10.0; // no other husks on the map - so no need to do searching so often
|
||||
else if ( BestPatient != none ) {
|
||||
if ( BestPatient.Health < BestPatient.HealthMax * 0.99 ) {
|
||||
MyMC.Target = BestPatient;
|
||||
MyMC.ChangeEnemy(BestPatient, MyMC.CanSee(BestPatient));
|
||||
MyMC.GotoState('RangedAttack');
|
||||
|
||||
LastHealTime = Level.TimeSeconds + 3.0; // do not heal until beam is spawned
|
||||
GotoState('Healing');
|
||||
}
|
||||
else
|
||||
NextHealAttemptTime = Level.TimeSeconds + 1.0; // if there are other Tesla Husks nearby, then check their health each second
|
||||
}
|
||||
else
|
||||
NextHealAttemptTime = Level.TimeSeconds + 3.0; // there are other Tesla Husks on the map, but not too close
|
||||
}
|
||||
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
if ( PrimaryBeam != none )
|
||||
PrimaryBeam.Instigator = none;
|
||||
if ( DecapitationSparks != none )
|
||||
DecapitationSparks.Destroy();
|
||||
|
||||
AmbientSound = none;
|
||||
|
||||
super.Died(Killer, damageType, HitLocation);
|
||||
}
|
||||
|
||||
simulated event PlayDying(class<DamageType> DamageType, vector HitLoc)
|
||||
{
|
||||
super.PlayDying(DamageType, HitLoc);
|
||||
|
||||
if ( DecapitationSparks != none )
|
||||
DecapitationSparks.Destroy();
|
||||
|
||||
AmbientSound = none;
|
||||
}
|
||||
|
||||
// instead of roaming around, activate self-destruct
|
||||
function RemoveHead()
|
||||
{
|
||||
Intelligence = BRAINS_Retarded; // Headless dumbasses!
|
||||
|
||||
bDecapitated = true;
|
||||
DECAP = true;
|
||||
DecapTime = Level.TimeSeconds;
|
||||
|
||||
bShotAnim = true;
|
||||
SetAnimAction('KnockDown');
|
||||
Acceleration = vect(0, 0, 0);
|
||||
Velocity.X = 0;
|
||||
Velocity.Y = 0;
|
||||
Controller.GoToState('WaitForAnim');
|
||||
KFMonsterController(Controller).bUseFreezeHack = True;
|
||||
SetGroundSpeed(0);
|
||||
AirSpeed = 0;
|
||||
WaterSpeed = 0;
|
||||
|
||||
// No more raspy breathin'...cuz he has no throat or mouth :S
|
||||
AmbientSound = MiscSound;
|
||||
|
||||
|
||||
// super.TakeDamage(LastDamageAmount) isn't called yet, so set self-destruct sequence only if
|
||||
// zed can survive the hit
|
||||
if( Health > LastDamageAmount && Energy > 25 ) {
|
||||
SpawnDecapitationEffects();
|
||||
BleedOutTime = Level.TimeSeconds + BleedOutDuration;
|
||||
GotoState('SelfDestruct');
|
||||
}
|
||||
|
||||
|
||||
PlaySound(DecapitationSound, SLOT_Misc,1.30,true,525);
|
||||
}
|
||||
|
||||
// Tesla Husk doesn't get stunned by weak sniper shots
|
||||
// function PlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum, optional int HitIdx )
|
||||
// {
|
||||
// super(KFMonster).PlayHit(Damage, InstigatedBy, HitLocation, damageType, Momentum, HitIdx );
|
||||
// }
|
||||
|
||||
simulated function Destroyed()
|
||||
{
|
||||
if ( PrimaryBeam != none )
|
||||
PrimaryBeam.Destroy();
|
||||
|
||||
if ( DecapitationSparks != none )
|
||||
DecapitationSparks.Destroy();
|
||||
|
||||
super.Destroyed();
|
||||
}
|
||||
|
||||
simulated function SpawnDecapitationEffects()
|
||||
{
|
||||
if (Level.NetMode == NM_DedicatedServer)
|
||||
return;
|
||||
|
||||
DecapitationSparks = spawn(class'ZedBeamSparks', self,, GetBoneCoords(HeadBone).Origin, Rotation);
|
||||
}
|
||||
|
||||
simulated function int DoAnimAction( name AnimName )
|
||||
{
|
||||
// faked animation with forces to play the end of shoot animation (where Huks is putting his gun down)
|
||||
if ( AnimName == 'ShootBurnsEnd' ) {
|
||||
PlayAnim('ShootBurns');
|
||||
SetAnimFrame(120, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
return super.DoAnimAction(AnimName);
|
||||
}
|
||||
|
||||
function float RangedAttackTime()
|
||||
{
|
||||
return 5.0;
|
||||
}
|
||||
|
||||
// Overridden so that anims don't get interrupted on the server if one is already playing
|
||||
function bool IsHeadShot(vector loc, vector ray, float AdditionalScale)
|
||||
{
|
||||
local coords C;
|
||||
local vector HeadLoc, B, M, diff;
|
||||
local float t, DotMM, Distance;
|
||||
local int look;
|
||||
local bool bUseAltHeadShotLocation;
|
||||
local bool bWasAnimating;
|
||||
|
||||
if (HeadBone == '')
|
||||
return False;
|
||||
|
||||
// If we are a dedicated server estimate what animation is most likely playing on the client
|
||||
if (Level.NetMode == NM_DedicatedServer)
|
||||
{
|
||||
if (Physics == PHYS_Falling)
|
||||
PlayAnim(AirAnims[0], 1.0, 0.0);
|
||||
else if (Physics == PHYS_Walking)
|
||||
{
|
||||
// Only play the idle anim if we're not already doing a different anim.
|
||||
// This prevents anims getting interrupted on the server and borking things up - Ramm
|
||||
|
||||
if( !IsAnimating(0) && !IsAnimating(1) )
|
||||
{
|
||||
if (bIsCrouched)
|
||||
{
|
||||
PlayAnim(IdleCrouchAnim, 1.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bUseAltHeadShotLocation=true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bWasAnimating = true;
|
||||
}
|
||||
|
||||
if ( bDoTorsoTwist )
|
||||
{
|
||||
SmoothViewYaw = Rotation.Yaw;
|
||||
SmoothViewPitch = ViewPitch;
|
||||
|
||||
look = (256 * ViewPitch) & 65535;
|
||||
if (look > 32768)
|
||||
look -= 65536;
|
||||
|
||||
SetTwistLook(0, look);
|
||||
}
|
||||
}
|
||||
else if (Physics == PHYS_Swimming)
|
||||
PlayAnim(SwimAnims[0], 1.0, 0.0);
|
||||
|
||||
if( !bWasAnimating )
|
||||
{
|
||||
SetAnimFrame(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
if( bUseAltHeadShotLocation )
|
||||
{
|
||||
HeadLoc = Location + (OnlineHeadshotOffset >> Rotation);
|
||||
AdditionalScale *= OnlineHeadshotScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
C = GetBoneCoords(HeadBone);
|
||||
|
||||
HeadLoc = C.Origin + (HeadHeight * HeadScale * AdditionalScale * C.XAxis) -5.0*C.XAxis - 2.0*C.YAxis;
|
||||
}
|
||||
//ServerHeadLocation = HeadLoc;
|
||||
|
||||
// Express snipe trace line in terms of B + tM
|
||||
B = loc;
|
||||
M = ray * (2.0 * CollisionHeight + 2.0 * CollisionRadius);
|
||||
|
||||
// Find Point-Line Squared Distance
|
||||
diff = HeadLoc - B;
|
||||
t = M Dot diff;
|
||||
if (t > 0)
|
||||
{
|
||||
DotMM = M dot M;
|
||||
if (t < DotMM)
|
||||
{
|
||||
t = t / DotMM;
|
||||
diff = diff - (t * M);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 1;
|
||||
diff -= M;
|
||||
}
|
||||
}
|
||||
else
|
||||
t = 0;
|
||||
|
||||
Distance = Sqrt(diff Dot diff);
|
||||
|
||||
return (Distance < (HeadRadius * HeadScale * AdditionalScale));
|
||||
}
|
||||
|
||||
state Healing
|
||||
{
|
||||
ignores TryHealing;
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
//log("Entering Healing State @ " $ Level.TimeSeconds, 'TeslaHusk');
|
||||
|
||||
LastHealTime = Level.TimeSeconds + 3.0; // do not heal until beam is spawned
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
local name SeqName;
|
||||
local float AnimFrame, AnimRate;
|
||||
|
||||
//log("Exiting Healing State @ " $ Level.TimeSeconds, 'TeslaHusk');
|
||||
|
||||
NextHealAttemptTime = Level.TimeSeconds + 5.0;
|
||||
FreePrimaryBeam();
|
||||
|
||||
// end shooting animation
|
||||
GetAnimParams(0, SeqName, AnimFrame, AnimRate);
|
||||
if ( SeqName == 'ShootBurns' && AnimFrame < 120 )
|
||||
SetAnimAction('ShootBurnsEnd'); // faked anim
|
||||
|
||||
Controller.Enemy = none;
|
||||
KFMonsterController(Controller).FindNewEnemy();
|
||||
}
|
||||
|
||||
function n_SpawnBeam()
|
||||
{
|
||||
SpawnPrimaryBeam();
|
||||
if ( Controller != none )
|
||||
PrimaryBeam.EndActor = Controller.Target;
|
||||
PrimaryBeam.EffectEndTime = Level.TimeSeconds + 2.5;
|
||||
LastHealTime = Level.TimeSeconds - 1.0; // start healing
|
||||
}
|
||||
|
||||
function bool FlipOver()
|
||||
{
|
||||
if ( global.FlipOver() ) {
|
||||
GotoState('');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Tick(float DeltaTime)
|
||||
{
|
||||
local KFMonster Patient;
|
||||
local int HealthToAdd, HeadHealthToAdd;
|
||||
local int HeadHealthMax;
|
||||
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
if ( Level.TimeSeconds >= LastHealTime+0.25 ) {
|
||||
if ( PrimaryBeam == none || Energy <= 0 || Level.TimeSeconds > PrimaryBeam.EffectEndTime ) {
|
||||
GotoState('');
|
||||
return;
|
||||
}
|
||||
|
||||
NextHealAttemptTime = Level.TimeSeconds + 3.0;
|
||||
Patient = KFMonster(PrimaryBeam.EndActor);
|
||||
if ( Patient == none || Patient.Health <= 0 || Patient.Health >= Patient.HealthMax )
|
||||
GotoState('');
|
||||
else {
|
||||
HealthToAdd = min(Patient.HealthMax*HealRate*(Level.TimeSeconds-LastHealTime), Patient.HealthMax - Patient.Health);
|
||||
if ( HealthToAdd*HealEnergyDrain > Energy )
|
||||
HealthToAdd = Energy / HealEnergyDrain;
|
||||
if ( !Patient.bDecapitated && Patient.HeadHealth > 0 ) {
|
||||
HeadHealthMax = Patient.default.HeadHealth * Patient.DifficultyHeadHealthModifer() * Patient.NumPlayersHeadHealthModifer();
|
||||
HeadHealthToAdd = min(HeadHealthMax*HealRate*2.0*(Level.TimeSeconds-LastHealTime), HeadHealthMax - Patient.HeadHealth);
|
||||
Patient.HeadHealth += HeadHealthToAdd;
|
||||
}
|
||||
Patient.Health += HealthToAdd;
|
||||
Energy -= HealthToAdd*HealEnergyDrain;
|
||||
LastHealTime = Level.TimeSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// todo: make custom controller, moving states there
|
||||
state Shooting
|
||||
{
|
||||
ignores TryHealing;
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
//log("Entering Shooting State @ " $ Level.TimeSeconds, 'TeslaHusk');
|
||||
|
||||
if ( PrimaryBeam == none ) {
|
||||
SpawnPrimaryBeam();
|
||||
PrimaryBeam.EndActor = Controller.Target;
|
||||
}
|
||||
|
||||
PrimaryBeam.EffectEndTime = Level.TimeSeconds + 2.5;
|
||||
BuildChain();
|
||||
LastDischargeTime = Level.TimeSeconds;
|
||||
Discharge(DischargeRate);
|
||||
}
|
||||
|
||||
|
||||
function EndState()
|
||||
{
|
||||
local name SeqName;
|
||||
local float AnimFrame, AnimRate;
|
||||
|
||||
//log("Exiting Shooting State @ " $ Level.TimeSeconds, 'TeslaHusk');
|
||||
|
||||
FreePrimaryBeam();
|
||||
|
||||
// end shooting animation
|
||||
GetAnimParams(0, SeqName, AnimFrame, AnimRate);
|
||||
if ( SeqName == 'ShootBurns' && AnimFrame < 120 )
|
||||
SetAnimAction('ShootBurnsEnd'); // faked anim
|
||||
}
|
||||
|
||||
function BuildChain()
|
||||
{
|
||||
local int ChainsRemaining;
|
||||
|
||||
ChainRebuildTimer = default.ChainRebuildTimer;
|
||||
ChainsRemaining = MaxChainActors;
|
||||
if ( PrimaryBeam != none && KFDoorMover(PrimaryBeam.EndActor) == none )
|
||||
SpawnChildBeams(PrimaryBeam, 1, ChainsRemaining);
|
||||
}
|
||||
|
||||
function SpawnChildBeams(TeslaBeam MasterBeam, byte level, out int ChainsRemaining)
|
||||
{
|
||||
local Pawn P;
|
||||
local TeslaBeam ChildBeam;
|
||||
local int i;
|
||||
|
||||
if ( MasterBeam == none || level > MaxChainLevel || ChainsRemaining <= 0 )
|
||||
return;
|
||||
|
||||
for ( i=0; i<MasterBeam.ChildBeams.length; ++i ) {
|
||||
if ( MasterBeam.ChildBeams[i] == none )
|
||||
MasterBeam.ChildBeams.remove(i--, 1);
|
||||
}
|
||||
|
||||
if ( MasterBeam.EndActor == none || MasterBeam.EndActor.bDeleteMe )
|
||||
return;
|
||||
|
||||
foreach MasterBeam.EndActor.VisibleCollidingActors(class'Pawn', P, MaxChildBeamRange, MasterBeam.EndActor.Location) {
|
||||
if ( !P.bDeleteMe && P.Health > 0 && P != MasterBeam.StartActor && P != MasterBeam.EndActor
|
||||
&& TeslaHusk(P) == none && !PrimaryBeam.IsChainedTo(P) )
|
||||
{
|
||||
i = MasterBeam.ChildIndex(P);
|
||||
if ( i != -1 ) {
|
||||
ChildBeam = MasterBeam.ChildBeams[i];
|
||||
ChildBeam.EffectEndTime = PrimaryBeam.EffectEndTime;
|
||||
}
|
||||
else {
|
||||
ChildBeam = SpawnTeslaBeam();
|
||||
if ( ChildBeam != none ) {
|
||||
ChildBeam.StartActor = MasterBeam.EndActor;
|
||||
ChildBeam.EndActor = P;
|
||||
ChildBeam.EffectEndTime = PrimaryBeam.EffectEndTime;
|
||||
MasterBeam.ChildBeams[MasterBeam.ChildBeams.length] = ChildBeam;
|
||||
}
|
||||
}
|
||||
if ( --ChainsRemaining <= 0 )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i=0; i<MasterBeam.ChildBeams.length && ChainsRemaining > 0; ++i ) {
|
||||
SpawnChildBeams(MasterBeam.ChildBeams[i], level+1, ChainsRemaining);
|
||||
}
|
||||
}
|
||||
|
||||
function ChainDamage(TeslaBeam Beam, float Damage, byte ChainLevel)
|
||||
{
|
||||
local int i;
|
||||
local float DmgMult;
|
||||
|
||||
if ( Beam == none || Beam.EndActor == none || Energy < 0)
|
||||
return;
|
||||
|
||||
Damage = clamp(Damage, 1, Energy);
|
||||
|
||||
// look if actor already received a damage during this discharge
|
||||
for ( i=0; i<DischargedActors.length; ++i ) {
|
||||
if ( DischargedActors[i].Victim == Beam.EndActor ) {
|
||||
if ( DischargedActors[i].Damage >= Damage )
|
||||
return; // Victim already received enough damage
|
||||
else {
|
||||
Damage -= DischargedActors[i].Damage;
|
||||
DischargedActors[i].Damage += Damage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( i == DischargedActors.length ) {
|
||||
// new victim
|
||||
DischargedActors.insert(i, 1);
|
||||
DischargedActors[i].Victim = Beam.EndActor;
|
||||
DischargedActors[i].Damage = Damage;
|
||||
}
|
||||
|
||||
// deal higher damage to monsters, but do not drain energy quicker
|
||||
DmgMult = 1.0;
|
||||
if ( KFMonster(Beam.EndActor) != none ) {
|
||||
DmgMult = 10.0;
|
||||
}
|
||||
// if pawn is already chained, then damage him until he gets out of the primary range
|
||||
Beam.SetBeamLocation(); // ensure that StartEffect and EndEffect are set
|
||||
if ( KFDoorMover(Beam.EndActor) != none ) {
|
||||
Beam.EndActor.TakeDamage(Damage*10.0,Self,Location,vect(0,0,0), class'DamTypeUnWeld');
|
||||
}
|
||||
else if ( VSizeSquared(Beam.EndEffect - Beam.StartEffect) <= MaxPrimaryBeamRangeSquared * ChainedBeamRangeExtension
|
||||
&& FastTrace(Beam.EndEffect, Beam.StartEffect) )
|
||||
{
|
||||
Beam.EndActor.TakeDamage(Damage*DmgMult, self, Beam.EndActor.Location, Beam.SetBeamRotation(), MyDamageType);
|
||||
Energy -= Damage;
|
||||
|
||||
Damage *= ChainDamageMult;
|
||||
ChainLevel++;
|
||||
if ( Damage > 0 && ChainLevel <= MaxChainLevel) {
|
||||
for ( i=0; i<Beam.ChildBeams.length && Energy > 0; ++i )
|
||||
ChainDamage(Beam.ChildBeams[i], Damage, ChainLevel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Beam.Instigator = none; // delete beam
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Discharge(float DeltaTime)
|
||||
{
|
||||
LastDischargeTime = Level.TimeSeconds;
|
||||
DischargedActors.length = 0;
|
||||
ChainDamage(PrimaryBeam, DischargeDamage*DeltaTime, 0);
|
||||
if (Energy <= 0)
|
||||
GotoState(''); // out of energy - stop shooting
|
||||
}
|
||||
|
||||
function bool FlipOver()
|
||||
{
|
||||
if ( global.FlipOver() ) {
|
||||
GotoState('');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
//log("Shooting.Tick @ " $ Level.TimeSeconds $ ":" @"Energy="$Energy @"PrimaryBeam="$PrimaryBeam, 'TeslaHusk');
|
||||
|
||||
ChainRebuildTimer -= DeltaTime;
|
||||
if ( Energy <= 0 || PrimaryBeam == none || PrimaryBeam.EndActor == none || Level.TimeSeconds > PrimaryBeam.EffectEndTime ) {
|
||||
GotoState('');
|
||||
}
|
||||
else if ( LastDischargeTime + DischargeRate <= Level.TimeSeconds ) {
|
||||
if ( ChainRebuildTimer <= 0 )
|
||||
BuildChain();
|
||||
|
||||
Discharge(Level.TimeSeconds - LastDischargeTime); // damage chained actors
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
state SelfDestruct
|
||||
{
|
||||
ignores PlayDirectionalHit, RangedAttack, MeleeDamageTarget;
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
local TeslaHuskEMPCharge MyNade;
|
||||
|
||||
MyNade = spawn(class'TeslaHuskEMPCharge', self,, Location);
|
||||
if ( MyNade != none ) {
|
||||
AttachToBone(MyNade, RootBone);
|
||||
MyNade.SetTimer(3.0, false);
|
||||
MyNade.bTimerSet = true;
|
||||
MyNade.Damage = max(30, Energy * 0.65);
|
||||
MyNade.Killer = LastDamagedBy;
|
||||
}
|
||||
else {
|
||||
// wtf?
|
||||
Died(LastDamagedBy.Controller,class'DamTypeBleedOut',Location);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function bool CanGetOutOfWay()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// takes only 25% of damage
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
global.TakeDamage(Damage*0.25,instigatedBy,hitlocation,momentum,damageType,HitIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{
|
||||
myLevel.AddPrecacheMaterial(Shader'ScrnZedPack_T.TeslaHusk.TeslaHusk_SHADER');
|
||||
myLevel.AddPrecacheMaterial(FinalBlend'KFZED_FX_T.Energy.ZED_FX_Beam_FB');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
BeamClass=Class'ScrnZedPack.TeslaBeam'
|
||||
MaxPrimaryBeamRange=300.000000
|
||||
MaxChildBeamRange=150.000000
|
||||
ChainedBeamRangeExtension=1.350000
|
||||
Energy=100.000000
|
||||
EnergyMax=100.000000
|
||||
EnergyRestoreRate=20.000000
|
||||
DischargeDamage=10.000000
|
||||
ChainDamageMult=0.850000
|
||||
MyDamageType=Class'ScrnZedPack.DamTypeTesla'
|
||||
MaxChainLevel=5
|
||||
MaxChainActors=20
|
||||
DischargeRate=0.250000
|
||||
HealRate=0.250000
|
||||
HealEnergyDrain=0.100000
|
||||
ProjectileFireInterval=5.000000
|
||||
BurnDamageScale=1.000000
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Talk'
|
||||
BleedOutDuration=5.000000
|
||||
MiscSound=Sound'KF_FY_ZEDV2SND.foley.WEP_ZEDV2_Projectile_Loop'
|
||||
DecapitationSound=Sound'KF_FY_ZEDV2SND.Fire.WEP_ZEDV2_Secondary_Explode'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Bloat.Bloat_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Jump'
|
||||
ColHeight=30.000000
|
||||
ProjectileBloodSplatClass=None
|
||||
DetachedArmClass=Class'ScrnZedPack.SeveredArmTeslaHusk'
|
||||
DetachedLegClass=Class'ScrnZedPack.SeveredLegTeslaHusk'
|
||||
DetachedHeadClass=Class'ScrnZedPack.SeveredHeadTeslaHusk'
|
||||
DetachedSpecialArmClass=Class'ScrnZedPack.SeveredGunTeslaHusk'
|
||||
BurningWalkFAnims(0)="WalkF"
|
||||
BurningWalkFAnims(1)="WalkF"
|
||||
BurningWalkFAnims(2)="WalkF"
|
||||
BurningWalkAnims(0)="WalkB"
|
||||
BurningWalkAnims(1)="WalkL"
|
||||
BurningWalkAnims(2)="WalkR"
|
||||
OnlineHeadshotOffset=(X=22.000000,Z=50.000000)
|
||||
HeadHealth=250.000000
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Challenge'
|
||||
ScoringValue=25
|
||||
GroundSpeed=140.000000
|
||||
WaterSpeed=120.000000
|
||||
HealthMax=800.000000
|
||||
Health=800
|
||||
MenuName="Tesla Husk"
|
||||
AmbientSound=Sound'KF_BaseHusk_CIRCUS.Husk_IdleLoop'
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.TeslaHuskMesh'
|
||||
Skins(0)=Shader'ScrnZedPack_T.TeslaHusk.TeslaHusk_SHADER'
|
||||
}
|
||||
170
kf_sources/ScrnZedPack/Classes/TeslaHuskEMPCharge.uc
Normal file
170
kf_sources/ScrnZedPack/Classes/TeslaHuskEMPCharge.uc
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
// used for Tesla Husk self-destruct explosion on decapitation
|
||||
class TeslaHuskEMPCharge extends Nade;
|
||||
|
||||
var() class<Emitter> ExplosionEffect;
|
||||
var Pawn Killer;
|
||||
|
||||
function Timer()
|
||||
{
|
||||
if ( bHidden )
|
||||
Destroy();
|
||||
else if ( Instigator != none && Instigator.Health > 0 )
|
||||
Explode(Location, vect(0,0,1));
|
||||
else
|
||||
Disintegrate(Location, vect(0,0,1));
|
||||
}
|
||||
|
||||
|
||||
// don't get destroyed by a Siren
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
}
|
||||
|
||||
simulated function Explode(vector HitLocation, vector HitNormal)
|
||||
{
|
||||
local PlayerController LocalPlayer;
|
||||
|
||||
bHasExploded = True;
|
||||
BlowUp(HitLocation);
|
||||
|
||||
PlaySound(ExplodeSounds[rand(ExplodeSounds.length)],,2.0);
|
||||
|
||||
if ( EffectIsRelevant(Location,false) )
|
||||
{
|
||||
Spawn(ExplosionEffect,,, HitLocation, rotator(vect(0,0,1)));
|
||||
Spawn(ExplosionDecal,self,,HitLocation, rotator(-HitNormal));
|
||||
}
|
||||
|
||||
// Shake nearby players screens
|
||||
LocalPlayer = Level.GetLocalPlayerController();
|
||||
if ( (LocalPlayer != None) && (VSize(Location - LocalPlayer.ViewTarget.Location) < (DamageRadius * 1.5)) )
|
||||
LocalPlayer.ShakeView(RotMag, RotRate, RotTime, OffsetMag, OffsetRate, OffsetTime);
|
||||
|
||||
if ( Instigator != none ) {
|
||||
// blow up the instigator
|
||||
Instigator.TakeDamage(1000000, Killer, Instigator.Location, vect(0,0,1), MyDamageType);
|
||||
}
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
simulated function HurtRadius( float DamageAmount, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HitLocation )
|
||||
{
|
||||
local actor Victims;
|
||||
local float damageScale, dist;
|
||||
local vector dir;
|
||||
local KFMonster KFMonsterVictim;
|
||||
local Pawn P;
|
||||
local KFPawn KFP;
|
||||
local array<Pawn> CheckedPawns;
|
||||
local int i;
|
||||
local bool bAlreadyChecked;
|
||||
|
||||
|
||||
if ( bHurtEntry )
|
||||
return;
|
||||
|
||||
bHurtEntry = true;
|
||||
|
||||
foreach CollidingActors (class 'Actor', Victims, DamageRadius, HitLocation)
|
||||
{
|
||||
// don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag
|
||||
if( (Victims != self) && (Hurtwall != Victims) && (Victims.Role == ROLE_Authority) && !Victims.IsA('FluidSurfaceInfo')
|
||||
&& ExtendedZCollision(Victims)==None )
|
||||
{
|
||||
if( (Instigator==None || Instigator.Health<=0) && KFPawn(Victims)!=None )
|
||||
Continue;
|
||||
dir = Victims.Location - HitLocation;
|
||||
dist = FMax(1,VSize(dir));
|
||||
dir = dir/dist;
|
||||
damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);
|
||||
|
||||
if ( Instigator == None || Instigator.Controller == None )
|
||||
{
|
||||
Victims.SetDelayedDamageInstigatorController( InstigatorController );
|
||||
}
|
||||
|
||||
P = Pawn(Victims);
|
||||
|
||||
if( P != none )
|
||||
{
|
||||
for (i = 0; i < CheckedPawns.Length; i++)
|
||||
{
|
||||
if (CheckedPawns[i] == P)
|
||||
{
|
||||
bAlreadyChecked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( bAlreadyChecked )
|
||||
{
|
||||
bAlreadyChecked = false;
|
||||
P = none;
|
||||
continue;
|
||||
}
|
||||
|
||||
KFMonsterVictim = KFMonster(Victims);
|
||||
|
||||
if( KFMonsterVictim != none && KFMonsterVictim.Health <= 0 )
|
||||
{
|
||||
KFMonsterVictim = none;
|
||||
}
|
||||
|
||||
KFP = KFPawn(Victims);
|
||||
|
||||
if( KFMonsterVictim != none )
|
||||
{
|
||||
// 20x more damage zeds
|
||||
damageScale *= 20.0 * KFMonsterVictim.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity));
|
||||
if ( ZombieFleshpound(KFMonsterVictim) != none )
|
||||
damageScale *= 2.0; // compensate 50% dmg.res.
|
||||
}
|
||||
else if( KFP != none )
|
||||
{
|
||||
damageScale *= KFP.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity));
|
||||
}
|
||||
|
||||
CheckedPawns[CheckedPawns.Length] = P;
|
||||
|
||||
if ( damageScale <= 0)
|
||||
{
|
||||
P = none;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Victims = P;
|
||||
P = none;
|
||||
}
|
||||
}
|
||||
|
||||
Victims.TakeDamage(damageScale * DamageAmount, Killer,Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius)
|
||||
* dir,(damageScale * Momentum * dir),DamageType);
|
||||
|
||||
if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0)
|
||||
{
|
||||
Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, InstigatorController, DamageType, Momentum, HitLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bHurtEntry = false;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ExplosionEffect=Class'KFMod.ZEDMKIISecondaryProjectileExplosion'
|
||||
ShrapnelClass=None
|
||||
ExplodeSounds(0)=Sound'KF_FY_ZEDV2SND.Fire.WEP_ZEDV2_Secondary_Fire_S'
|
||||
ExplodeSounds(1)=Sound'KF_FY_ZEDV2SND.Fire.WEP_ZEDV2_Secondary_Fire_S'
|
||||
ExplodeSounds(2)=Sound'KF_FY_ZEDV2SND.Fire.WEP_ZEDV2_Secondary_Fire_S'
|
||||
Speed=0.000000
|
||||
Damage=50.000000
|
||||
DamageRadius=400.000000
|
||||
MyDamageType=Class'ScrnZedPack.DamTypeEMP'
|
||||
DrawType=DT_None
|
||||
bCollideActors=False
|
||||
bBlockZeroExtentTraces=False
|
||||
bBlockNonZeroExtentTraces=False
|
||||
}
|
||||
108
kf_sources/ScrnZedPack/Classes/ZombieBloat_GRITTIER.uc
Normal file
108
kf_sources/ScrnZedPack/Classes/ZombieBloat_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Code originally was taken from Scary Ghost's Super Zombies mutator
|
||||
class ZombieBloat_GRITTIER extends ZombieBloat;
|
||||
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
var bool bAmIBarfing;
|
||||
var float NextExtraBileTime;
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
if (InstigatedBy == none || class<KFWeaponDamageType>(DamType) == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
if( bAmIBarfing && !bDecapitated && Level.TimeSeconds > NextExtraBileTime ) {
|
||||
SpawnTwoShots();
|
||||
NextExtraBileTime = Level.TimeSeconds + default.NextExtraBileTime;
|
||||
}
|
||||
}
|
||||
|
||||
function Touch(Actor Other)
|
||||
{
|
||||
super.Touch(Other);
|
||||
if (Other.IsA('ShotgunBullet')) {
|
||||
ShotgunBullet(Other).Damage= 0;
|
||||
}
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
local int LastFireTime;
|
||||
|
||||
if ( bShotAnim )
|
||||
return;
|
||||
|
||||
if ( Physics == PHYS_Swimming ) {
|
||||
SetAnimAction('Claw');
|
||||
bShotAnim = true;
|
||||
LastFireTime = Level.TimeSeconds;
|
||||
}
|
||||
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
|
||||
bShotAnim = true;
|
||||
LastFireTime = Level.TimeSeconds;
|
||||
SetAnimAction('Claw');
|
||||
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
}
|
||||
else if ( (KFDoorMover(A) != none || VSize(A.Location-Location) <= 250) && !bDecapitated ) {
|
||||
bShotAnim = true;
|
||||
SetAnimAction('ZombieBarfMoving');
|
||||
RunAttackTimeout = GetAnimDuration('ZombieBarf', 1.0);
|
||||
bMovingPukeAttack=true;
|
||||
|
||||
// Randomly send out a message about Bloat Vomit burning(3% chance)
|
||||
if ( FRand() < 0.03 && KFHumanPawn(A) != none && PlayerController(KFHumanPawn(A).Controller) != none ) {
|
||||
PlayerController(KFHumanPawn(A).Controller).Speech('AUTO', 7, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ZombieBarf animation triggers this
|
||||
function SpawnTwoShots() {
|
||||
super.SpawnTwoShots();
|
||||
bAmIBarfing= true;
|
||||
}
|
||||
|
||||
simulated function AnimEnd(int Channel) {
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
|
||||
GetAnimParams( ExpectingChannel, Sequence, Frame, Rate );
|
||||
|
||||
super.AnimEnd(Channel);
|
||||
|
||||
if(Sequence == 'ZombieBarf')
|
||||
bAmIBarfing= false;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
NextExtraBileTime=1.000000
|
||||
BileExplosion=Class'KFMod.BileExplosion'
|
||||
BileExplosionHeadless=Class'KFMod.BileExplosionHeadless'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmBloat'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegBloat'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadBloat'
|
||||
HeadHealth=50.000000
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_Challenge'
|
||||
MenuName="Bloat.se"
|
||||
AmbientSound=Sound'KF_BaseBloat.Bloat_Idle1Loop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Bloat_Freak'
|
||||
Skins(0)=Combiner'ScrnZedPack_T.bloat_grittier.bloat_grittier_cmb'
|
||||
}
|
||||
24
kf_sources/ScrnZedPack/Classes/ZombieBoss_GRITTIER.uc
Normal file
24
kf_sources/ScrnZedPack/Classes/ZombieBoss_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
class ZombieBoss_GRITTIER extends ZombieBoss;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RocketFireSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_FireRocket'
|
||||
MiniGunFireSound=Sound'KF_BasePatriarch.Attack.Kev_MG_GunfireLoop'
|
||||
MiniGunSpinSound=Sound'KF_BasePatriarch.Attack.Kev_MG_TurbineFireLoop'
|
||||
MeleeImpaleHitSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_HitPlayer_Impale'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_HitPlayer_Fist'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPatriarch'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPatriarch'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPatriarch'
|
||||
DetachedSpecialArmClass=Class'KFChar.SeveredRocketArmPatriarch'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Patriarch.Kev_Death'
|
||||
MenuName="Grittier Patriarch"
|
||||
AmbientSound=Sound'KF_BasePatriarch.Idle.Kev_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Patriarch_Freak'
|
||||
Skins(0)=Combiner'KF_Specimens_Trip_T.gatling_cmb'
|
||||
Skins(1)=Combiner'ScrnZedPack_T.patriarch_grittier.patriarch_grittier_cmb'
|
||||
}
|
||||
738
kf_sources/ScrnZedPack/Classes/ZombieBrute.uc
Normal file
738
kf_sources/ScrnZedPack/Classes/ZombieBrute.uc
Normal file
|
|
@ -0,0 +1,738 @@
|
|||
class ZombieBrute extends KFMonster;
|
||||
|
||||
#exec load obj file=ScrnZedPack_T.utx
|
||||
#exec load obj file=ScrnZedPack_S.uax
|
||||
#exec load obj file=ScrnZedPack_A.ukx
|
||||
#exec OBJ LOAD FILE=KFWeaponSound.uax
|
||||
|
||||
var bool bChargingPlayer;
|
||||
var bool bClientCharge;
|
||||
var bool bFrustrated;
|
||||
var int MaxRageCounter; // Maximum amount of players we can hit before calming down
|
||||
var int RageCounter; // Decreases each time we successfully hit a player
|
||||
var float RageSpeedTween;
|
||||
var int TwoSecondDamageTotal;
|
||||
var float LastDamagedTime;
|
||||
var int RageDamageThreshold;
|
||||
var int BlockHitsLanded; // Hits made while blocking or raging
|
||||
var float BlockMeleeDmgMul; //Multiplier for melee damage taken, when Brute is blocking (no matter where the hit was landed)
|
||||
var float HeadShotgunDmgMul; //Multiplier for shotgun damage taken into UNBLOCKED head
|
||||
var float HeadBulletDmgMul; //Multiplier for non-sniper bullet damage taken into UNBLOCKED head
|
||||
|
||||
|
||||
var name ChargingAnim;
|
||||
var Sound RageSound;
|
||||
|
||||
// View shaking for players
|
||||
var() vector ShakeViewRotMag;
|
||||
var() vector ShakeViewRotRate;
|
||||
var() float ShakeViewRotTime;
|
||||
var() vector ShakeViewOffsetMag;
|
||||
var() vector ShakeViewOffsetRate;
|
||||
var() float ShakeViewOffsetTime;
|
||||
|
||||
var float PushForce;
|
||||
var vector PushAdd; // Used to add additional height to push
|
||||
var float RageDamageMul; // Multiplier for hit damage when raging
|
||||
var float RageBumpDamage; // Damage done when we hit other specimens while raging
|
||||
var float BlockAddScale; // Additional head scale when blocking
|
||||
var bool bBlockedHS;
|
||||
var bool bBlocking;
|
||||
var bool bServerBlock;
|
||||
var bool bClientBlock;
|
||||
var float BlockDmgMul; // Multiplier for damage taken from blocked shots
|
||||
var float BlockFireDmgMul;
|
||||
var float BurnGroundSpeedMul; // Multiplier for ground speed when burning
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if(Role == ROLE_Authority)
|
||||
bChargingPlayer, bServerBlock;
|
||||
}
|
||||
|
||||
simulated function PostNetBeginPlay()
|
||||
{
|
||||
super.PostNetBeginPlay();
|
||||
EnableChannelNotify(1,1);
|
||||
EnableChannelNotify(2,1);
|
||||
AnimBlendParams(1, 1.0, 0.0,, SpineBone1);
|
||||
}
|
||||
|
||||
function ServerRaiseBlock()
|
||||
{
|
||||
bServerBlock = true;
|
||||
SetAnimAction('BlockLoop');
|
||||
}
|
||||
|
||||
function ServerLowerBlock()
|
||||
{
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
bServerBlock = false;
|
||||
GetAnimParams(1, Sequence, Frame, Rate);
|
||||
if (Sequence == 'BlockLoop')
|
||||
AnimStopLooping(1);
|
||||
}
|
||||
|
||||
simulated function PostNetReceive()
|
||||
{
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
if(bClientCharge != bChargingPlayer)
|
||||
{
|
||||
bClientCharge = bChargingPlayer;
|
||||
if (bChargingPlayer)
|
||||
{
|
||||
MovementAnims[0] = ChargingAnim;
|
||||
MeleeAnims[0] = 'BruteRageAttack';
|
||||
MeleeAnims[1] = 'BruteRageAttack';
|
||||
MeleeAnims[2] = 'BruteRageAttack';
|
||||
}
|
||||
else
|
||||
{
|
||||
MovementAnims[0] = default.MovementAnims[0];
|
||||
MeleeAnims[0] = default.MeleeAnims[0];
|
||||
MeleeAnims[1] = default.MeleeAnims[1];
|
||||
MeleeAnims[2] = default.MeleeAnims[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (bClientBlock != bServerBlock)
|
||||
{
|
||||
bClientBlock = bServerBlock;
|
||||
if (bClientBlock)
|
||||
SetAnimAction('BlockLoop');
|
||||
else
|
||||
{
|
||||
GetAnimParams(1, Sequence, Frame, Rate);
|
||||
if (Sequence == 'BlockLoop')
|
||||
AnimStopLooping(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
// Lock to target when attacking (except on beginner!)
|
||||
if (bShotAnim && Level.Game.GameDifficulty >= 2.0)
|
||||
if (LookTarget != none)
|
||||
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
||||
|
||||
// Block according to rules
|
||||
if (Role == ROLE_Authority && !bServerBlock && !bShotAnim)
|
||||
if (Controller != none && Controller.Target != none)
|
||||
ServerRaiseBlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Override to always move when attacking
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if (bShotAnim || Physics == PHYS_Swimming)
|
||||
return;
|
||||
else if (CanAttack(A))
|
||||
{
|
||||
if (bChargingPlayer)
|
||||
SetAnimAction('AoeClaw');
|
||||
else
|
||||
{
|
||||
if (Rand(BlockHitsLanded) < 1)
|
||||
SetAnimAction('BlockClaw');
|
||||
else
|
||||
SetAnimAction('Claw');
|
||||
}
|
||||
|
||||
bShotAnim = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function bool IsHeadShot(vector Loc, vector Ray, float AdditionalScale)
|
||||
{
|
||||
local float D;
|
||||
local float AddScale;
|
||||
local bool bIsBlocking;
|
||||
|
||||
bBlockedHS = false;
|
||||
|
||||
if (bServerBlock && !IsTweening(1))
|
||||
{
|
||||
bIsBlocking = true;
|
||||
AddScale = AdditionalScale + BlockAddScale;
|
||||
}
|
||||
else
|
||||
AddScale = AdditionalScale + 1.0;
|
||||
|
||||
if (Super.IsHeadShot(Loc, Ray, AddScale))
|
||||
{
|
||||
if (bIsBlocking)
|
||||
{
|
||||
D = vector(Rotation) dot Ray;
|
||||
if (-D > 0.20) {
|
||||
bBlockedHS = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Damage, which doen't make headshots, always does full damage to Brute
|
||||
// Melee weapon resistance is applied only while blocking
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector HitLocation, Vector Momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
local bool bIsHeadShot;
|
||||
local class<KFWeaponDamageType> KFDamType;
|
||||
|
||||
KFDamType = class<KFWeaponDamageType>(DamType);
|
||||
|
||||
// damage, which doen't make headshots, always does full damage to Brute -- PooSH
|
||||
if (KFDamType != none && KFDamType.default.bCheckForHeadShots) {
|
||||
|
||||
bIsHeadShot = IsHeadShot(HitLocation, normal(Momentum), 1.0);
|
||||
|
||||
if (!bIsHeadShot && bBlockedHS)
|
||||
{
|
||||
if (class<KFProjectileWeaponDamageType>(DamType) != none)
|
||||
PlaySound(class'MetalHitEmitter'.default.ImpactSounds[rand(3)],, 128);
|
||||
else if (class<DamTypeChainsaw>(DamType) != none)
|
||||
PlaySound(Sound'KF_ChainsawSnd.Chainsaw_Impact_Metal',, 128);
|
||||
else if (class<DamTypeMelee>(DamType) != none)
|
||||
PlaySound(Sound'KF_KnifeSnd.Knife_HitMetal',, 128);
|
||||
|
||||
if ( KFDamType.default.bDealBurningDamage && !KFDamType.default.bIsPowerWeapon )
|
||||
Damage *= BlockFireDmgMul; // Fire damage isn't reduced as much, excluding TrenchGun
|
||||
else
|
||||
Damage *= BlockDmgMul; // Greatly reduce damage as we only hit the metal plating
|
||||
}
|
||||
else if ( bServerBlock && class<DamTypeMelee>(DamType) != none )
|
||||
Damage *= BlockMeleeDmgMul; // Give Brute higher melee damage resistance, but apply it only if Brute is blocking
|
||||
else if ( bIsHeadShot ) {
|
||||
if ( KFDamType.default.bIsPowerWeapon )
|
||||
Damage *= HeadShotgunDmgMul; // Give Brute's head resistance to stotguns
|
||||
else if ( !KFDamType.default.bSniperWeapon && !KFDamType.default.bIsMeleeDamage )
|
||||
Damage *= HeadBulletDmgMul; // Give damage bonus to commando and gunslinger weapons
|
||||
}
|
||||
}
|
||||
|
||||
// Record damage over 2-second frames
|
||||
if (LastDamagedTime < Level.TimeSeconds)
|
||||
{
|
||||
TwoSecondDamageTotal = 0;
|
||||
LastDamagedTime = Level.TimeSeconds + 2;
|
||||
}
|
||||
TwoSecondDamageTotal += Damage;
|
||||
|
||||
// If criteria is met make him rage
|
||||
if (!bDecapitated && !bChargingPlayer && TwoSecondDamageTotal > RageDamageThreshold)
|
||||
{
|
||||
StartCharging();
|
||||
if (InstigatedBy != None)
|
||||
if (Controller.Target != InstigatedBy)
|
||||
MonsterController(Controller).ChangeEnemy(InstigatedBy, Controller.CanSee(InstigatedBy));
|
||||
}
|
||||
|
||||
if (InstigatedBy == none || KFDamType == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
|
||||
if (bDecapitated)
|
||||
Died(InstigatedBy.Controller, DamType, HitLocation);
|
||||
}
|
||||
|
||||
function TakeFireDamage(int Damage, Pawn Instigator)
|
||||
{
|
||||
Super.TakeFireDamage(Damage, Instigator);
|
||||
|
||||
// Adjust movement speed if not charging
|
||||
if (!bChargingPlayer)
|
||||
{
|
||||
if (bBurnified)
|
||||
GroundSpeed = GetOriginalGroundSpeed() * BurnGroundSpeedMul;
|
||||
else
|
||||
GroundSpeed = GetOriginalGroundSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
function ClawDamageTarget()
|
||||
{
|
||||
local KFHumanPawn HumanTarget;
|
||||
local float UsedMeleeDamage;
|
||||
local Actor OldTarget;
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
local bool bHitSomeone;
|
||||
|
||||
if (MeleeDamage > 1)
|
||||
UsedMeleeDamage = (MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1));
|
||||
else
|
||||
UsedMeleeDamage = MeleeDamage;
|
||||
|
||||
GetAnimParams(1, Sequence, Frame, Rate);
|
||||
|
||||
if (Controller != none && Controller.Target != none)
|
||||
{
|
||||
if (Sequence == 'BruteRageAttack')
|
||||
{
|
||||
OldTarget = Controller.Target;
|
||||
foreach VisibleCollidingActors(class'KFHumanPawn', HumanTarget, MeleeRange + class'KFHumanPawn'.default.CollisionRadius)
|
||||
{
|
||||
bHitSomeone = ClawDamageSingleTarget(UsedMeleeDamage, HumanTarget);
|
||||
}
|
||||
Controller.Target = OldTarget;
|
||||
if (bHitSomeone)
|
||||
BlockHitsLanded++;
|
||||
}
|
||||
else if (Sequence != 'BruteAttack1' && Sequence != 'BruteAttack2' && Sequence != 'DoorBash') // Block attack
|
||||
{
|
||||
bHitSomeone = ClawDamageSingleTarget(UsedMeleeDamage, Controller.Target);
|
||||
if (bHitSomeone)
|
||||
BlockHitsLanded++;
|
||||
}
|
||||
else
|
||||
bHitSomeone = ClawDamageSingleTarget(UsedMeleeDamage, Controller.Target);
|
||||
|
||||
if (bHitSomeone)
|
||||
PlaySound(MeleeAttackHitSound, SLOT_Interact, 1.25);
|
||||
}
|
||||
}
|
||||
|
||||
function bool ClawDamageSingleTarget(float UsedMeleeDamage, Actor ThisTarget)
|
||||
{
|
||||
local Pawn HumanTarget;
|
||||
local KFPlayerController HumanTargetController;
|
||||
local bool bHitSomeone;
|
||||
local float EnemyAngle;
|
||||
local vector PushForceVar;
|
||||
|
||||
EnemyAngle = Normal(ThisTarget.Location - Location) dot vector(Rotation);
|
||||
if (EnemyAngle > 0)
|
||||
{
|
||||
Controller.Target = ThisTarget;
|
||||
if (MeleeDamageTarget(UsedMeleeDamage, vect(0, 0, 0)))
|
||||
{
|
||||
HumanTarget = KFHumanPawn(ThisTarget);
|
||||
if (HumanTarget != None)
|
||||
{
|
||||
EnemyAngle = (EnemyAngle * 0.5) + 0.5; // Players at sides get knocked back half as much
|
||||
PushForceVar = (PushForce * Normal(HumanTarget.Location - Location) * EnemyAngle) + PushAdd;
|
||||
if (!bChargingPlayer)
|
||||
PushForceVar *= 0.85;
|
||||
|
||||
// (!) I'm sure the VeterancyName string is localized but I'm not sure of another way compatible with ServerPerks
|
||||
if (KFPlayerReplicationInfo(HumanTarget.Controller.PlayerReplicationInfo).ClientVeteranSkill != none)
|
||||
if (KFPlayerReplicationInfo(HumanTarget.Controller.PlayerReplicationInfo).ClientVeteranSkill
|
||||
.default.VeterancyName == "Berserker")
|
||||
PushForceVar *= 0.75;
|
||||
|
||||
if (!(HumanTarget.Physics == PHYS_WALKING || HumanTarget.Physics == PHYS_NONE))
|
||||
PushForceVar *= vect(1, 1, 0); // (!) Don't throw upwards if we are not on the ground - adjust for more flexibility
|
||||
|
||||
HumanTarget.AddVelocity(PushForceVar);
|
||||
|
||||
HumanTargetController = KFPlayerController(HumanTarget.Controller);
|
||||
if (HumanTargetController != None)
|
||||
HumanTargetController.ShakeView(ShakeViewRotMag, ShakeViewRotRate, ShakeViewRotTime,
|
||||
ShakeViewOffsetMag, ShakeViewOffsetRate, ShakeViewOffsetTime);
|
||||
|
||||
bHitSomeone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bHitSomeone;
|
||||
}
|
||||
|
||||
function StartCharging()
|
||||
{
|
||||
// How many times should we hit before we cool down?
|
||||
if (Level.Game.NumPlayers <= 3)
|
||||
MaxRageCounter = 2;
|
||||
else
|
||||
MaxRageCounter = 3;
|
||||
|
||||
RageCounter = MaxRageCounter;
|
||||
PlaySound(RageSound, SLOT_Talk, 255);
|
||||
GotoState('RageCharging');
|
||||
}
|
||||
|
||||
state RageCharging
|
||||
{
|
||||
Ignores StartCharging;
|
||||
|
||||
function PlayDirectionalHit(Vector HitLoc)
|
||||
{
|
||||
if (!bShotAnim)
|
||||
super.PlayDirectionalHit(HitLoc);
|
||||
}
|
||||
|
||||
function bool CanGetOutOfWay()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function bool CanSpeedAdjust()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function BeginState()
|
||||
{
|
||||
bFrustrated = false;
|
||||
bChargingPlayer = true;
|
||||
RageSpeedTween = 0.0;
|
||||
if (Level.NetMode != NM_DedicatedServer)
|
||||
ClientChargingAnims();
|
||||
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
bChargingPlayer = false;
|
||||
|
||||
BruteZombieController(Controller).RageFrustrationTimer = 0;
|
||||
|
||||
if (Health > 0)
|
||||
{
|
||||
GroundSpeed = GetOriginalGroundSpeed();
|
||||
if (bBurnified)
|
||||
GroundSpeed *= BurnGroundSpeedMul;
|
||||
}
|
||||
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
ClientChargingAnims();
|
||||
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
|
||||
function Tick(float Delta)
|
||||
{
|
||||
if (!bShotAnim)
|
||||
{
|
||||
RageSpeedTween = FClamp(RageSpeedTween + (Delta * 0.75), 0, 1.0);
|
||||
GroundSpeed = OriginalGroundSpeed + ((OriginalGroundSpeed * 0.75 / MaxRageCounter * (RageCounter + 1) * RageSpeedTween));
|
||||
if (bBurnified)
|
||||
GroundSpeed *= BurnGroundSpeedMul;
|
||||
}
|
||||
|
||||
Global.Tick(Delta);
|
||||
}
|
||||
|
||||
function Bump(Actor Other)
|
||||
{
|
||||
local KFMonster KFM;
|
||||
|
||||
KFM = KFMonster(Other);
|
||||
|
||||
// Hurt enemies that we run into while raging
|
||||
if (!bShotAnim && KFM != None && ZombieBrute(Other) == None && Pawn(Other).Health > 0)
|
||||
Other.TakeDamage(RageBumpDamage, self, Other.Location, Velocity * Other.Mass, class'DamTypePoundCrushed');
|
||||
else Global.Bump(Other);
|
||||
}
|
||||
|
||||
function bool MeleeDamageTarget(int HitDamage, vector PushDir)
|
||||
{
|
||||
local bool DamDone, bWasEnemy;
|
||||
|
||||
bWasEnemy = (Controller.Target == Controller.Enemy);
|
||||
|
||||
DamDone = Super.MeleeDamageTarget(HitDamage * RageDamageMul, vect(0, 0, 0));
|
||||
|
||||
if (bWasEnemy && DamDone)
|
||||
{
|
||||
ChangeTarget();
|
||||
CalmDown();
|
||||
}
|
||||
|
||||
return DamDone;
|
||||
}
|
||||
|
||||
function CalmDown()
|
||||
{
|
||||
RageCounter = FClamp(RageCounter - 1, 0, MaxRageCounter);
|
||||
if (RageCounter == 0)
|
||||
GotoState('');
|
||||
}
|
||||
|
||||
function ChangeTarget()
|
||||
{
|
||||
local Controller C;
|
||||
local Pawn BestPawn;
|
||||
local float Dist, BestDist;
|
||||
|
||||
for (C = Level.ControllerList; C != none; C = C.NextController)
|
||||
if (C.Pawn != none && KFHumanPawn(C.Pawn) != none)
|
||||
{
|
||||
Dist = VSize(C.Pawn.Location - Location);
|
||||
if (C.Pawn == Controller.Target)
|
||||
Dist += GroundSpeed * 4;
|
||||
|
||||
if (BestPawn == none)
|
||||
{
|
||||
BestPawn = C.Pawn;
|
||||
BestDist = Dist;
|
||||
}
|
||||
else if (Dist < BestDist)
|
||||
{
|
||||
BestPawn = C.Pawn;
|
||||
BestDist = Dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (BestPawn != none && BestPawn != Controller.Enemy)
|
||||
MonsterController(Controller).ChangeEnemy(BestPawn, Controller.CanSee(BestPawn));
|
||||
}
|
||||
}
|
||||
|
||||
// Override to prevent stunning
|
||||
function bool FlipOver()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shouldn't fight with our own
|
||||
function bool SameSpeciesAs(Pawn P)
|
||||
{
|
||||
return (ZombieBrute(P) != none);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Animation --------------------------------------------
|
||||
// ------------------------------------------------------
|
||||
|
||||
function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamageType)
|
||||
{
|
||||
if (Level.TimeSeconds - LastPainAnim < MinTimeBetweenPainAnims)
|
||||
return;
|
||||
|
||||
// Uncomment this if we want some damage to make him drop his block
|
||||
/*if( !Controller.IsInState('WaitForAnim') && Damage >= 10 )
|
||||
PlayDirectionalHit(HitLocation);*/
|
||||
|
||||
LastPainAnim = Level.TimeSeconds;
|
||||
|
||||
if (Level.TimeSeconds - LastPainSound < MinTimeBetweenPainSounds)
|
||||
return;
|
||||
|
||||
LastPainSound = Level.TimeSeconds;
|
||||
PlaySound(HitSound[0], SLOT_Pain,1.25,,400);
|
||||
}
|
||||
|
||||
// Overridden to handle playing upper body only attacks when moving
|
||||
simulated event SetAnimAction(name NewAction)
|
||||
{
|
||||
if (NewAction=='')
|
||||
return;
|
||||
|
||||
if (NewAction == 'Claw')
|
||||
{
|
||||
NewAction = MeleeAnims[rand(2)];
|
||||
CurrentDamType = ZombieDamType[0];
|
||||
}
|
||||
else if (NewAction == 'BlockClaw')
|
||||
{
|
||||
NewAction = 'BruteBlockSlam';
|
||||
CurrentDamType = ZombieDamType[0];
|
||||
}
|
||||
else if (NewAction == 'AoeClaw')
|
||||
{
|
||||
NewAction = 'BruteRageAttack';
|
||||
CurrentDamType = ZombieDamType[0];
|
||||
}
|
||||
else if (NewAction == 'DoorBash')
|
||||
CurrentDamType = ZombieDamType[Rand(3)];
|
||||
|
||||
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=='BruteAttack1' || AnimName=='BruteAttack2' || AnimName=='ZombieFireGun' || AnimName == 'DoorBash')
|
||||
{
|
||||
if (Role == ROLE_Authority)
|
||||
ServerLowerBlock();
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 1);
|
||||
return 1;
|
||||
}
|
||||
else if (AnimName == 'BruteRageAttack')
|
||||
{
|
||||
if (Role == ROLE_Authority)
|
||||
ServerLowerBlock();
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 1);
|
||||
return 1;
|
||||
}
|
||||
else if (AnimName == 'BlockLoop')
|
||||
{
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
||||
LoopAnim(AnimName,, 0.25, 1);
|
||||
return 1;
|
||||
}
|
||||
else if (AnimName == 'BruteBlockSlam')
|
||||
{
|
||||
AnimBlendParams(2, 1.0, 0.0,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 2);
|
||||
return 2;
|
||||
}
|
||||
return Super.DoAnimAction(AnimName);
|
||||
}
|
||||
|
||||
// The animation is full body and should set the bWaitForAnim flag
|
||||
simulated function bool AnimNeedsWait(name TestAnim)
|
||||
{
|
||||
if (TestAnim == 'DoorBash')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function AnimEnd(int Channel)
|
||||
{
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
GetAnimParams(Channel, Sequence, Frame, Rate);
|
||||
|
||||
// Don't allow notification for a looping animation
|
||||
if (Sequence == 'BlockLoop')
|
||||
return;
|
||||
|
||||
// Disable channel 2 when we're done with it
|
||||
if (Channel == 2 && Sequence == 'BruteBlockSlam')
|
||||
{
|
||||
AnimBlendParams(2, 0);
|
||||
bShotAnim = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Super.AnimEnd(Channel);
|
||||
}
|
||||
|
||||
simulated function ClientChargingAnims()
|
||||
{
|
||||
PostNetReceive();
|
||||
}
|
||||
|
||||
function PlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum, optional int HitIdx)
|
||||
{
|
||||
local Actor A;
|
||||
if (bBlockedHS)
|
||||
A = Spawn(class'BlockHitEmitter', InstigatedBy,, HitLocation, rotator(Normal(HitLocation - Location)));
|
||||
else
|
||||
Super.PlayHit(Damage, InstigatedBy, HitLocation, damageType, Momentum, HitIdx);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RageDamageThreshold=50
|
||||
BlockMeleeDmgMul=0.500000
|
||||
HeadShotgunDmgMul=0.500000
|
||||
HeadBulletDmgMul=1.250000
|
||||
ChargingAnim="BruteRun"
|
||||
RageSound=SoundGroup'ScrnZedPack_S.Brute.BruteRage'
|
||||
ShakeViewRotMag=(X=500.000000,Y=500.000000,Z=600.000000)
|
||||
ShakeViewRotRate=(X=12500.000000,Y=12500.000000,Z=12500.000000)
|
||||
ShakeViewRotTime=6.000000
|
||||
ShakeViewOffsetMag=(X=5.000000,Y=10.000000,Z=5.000000)
|
||||
ShakeViewOffsetRate=(X=300.000000,Y=300.000000,Z=300.000000)
|
||||
ShakeViewOffsetTime=3.500000
|
||||
PushForce=860.000000
|
||||
PushAdd=(Z=150.000000)
|
||||
RageDamageMul=1.100000
|
||||
RageBumpDamage=4.000000
|
||||
BlockAddScale=2.500000
|
||||
BlockDmgMul=0.100000
|
||||
BlockFireDmgMul=1.000000
|
||||
BurnGroundSpeedMul=0.600000
|
||||
MeleeAnims(0)="BruteAttack1"
|
||||
MeleeAnims(1)="BruteAttack2"
|
||||
MeleeAnims(2)="BruteBlockSlam"
|
||||
MoanVoice=SoundGroup'ScrnZedPack_S.Brute.BruteTalk'
|
||||
BleedOutDuration=7.000000
|
||||
ZombieFlag=3
|
||||
MeleeDamage=20
|
||||
damageForce=25000
|
||||
bFatAss=True
|
||||
KFRagdollName="FleshPound_Trip"
|
||||
MeleeAttackHitSound=SoundGroup'ScrnZedPack_S.Brute.BruteHitPlayer'
|
||||
JumpSound=SoundGroup'ScrnZedPack_S.Brute.BruteJump'
|
||||
SpinDamConst=20.000000
|
||||
SpinDamRand=20.000000
|
||||
bMeleeStunImmune=True
|
||||
bUseExtendedCollision=True
|
||||
ColOffset=(Z=52.000000)
|
||||
ColRadius=35.000000
|
||||
ColHeight=25.000000
|
||||
SeveredArmAttachScale=1.300000
|
||||
SeveredLegAttachScale=1.200000
|
||||
SeveredHeadAttachScale=1.500000
|
||||
DetachedArmClass=Class'ScrnZedPack.SeveredArmBrute'
|
||||
DetachedLegClass=Class'ScrnZedPack.SeveredLegBrute'
|
||||
DetachedHeadClass=Class'ScrnZedPack.SeveredHeadBrute'
|
||||
PlayerCountHealthScale=0.250000
|
||||
OnlineHeadshotOffset=(X=22.000000,Z=68.000000)
|
||||
OnlineHeadshotScale=1.300000
|
||||
HeadHealth=210.000000
|
||||
PlayerNumHeadHealthScale=0.150000
|
||||
MotionDetectorThreat=5.000000
|
||||
HitSound(0)=SoundGroup'ScrnZedPack_S.Brute.BrutePain'
|
||||
DeathSound(0)=SoundGroup'ScrnZedPack_S.Brute.BruteDeath'
|
||||
ChallengeSound(0)=SoundGroup'ScrnZedPack_S.Brute.BruteChallenge'
|
||||
ChallengeSound(1)=SoundGroup'ScrnZedPack_S.Brute.BruteChallenge'
|
||||
ChallengeSound(2)=SoundGroup'ScrnZedPack_S.Brute.BruteChallenge'
|
||||
ChallengeSound(3)=SoundGroup'ScrnZedPack_S.Brute.BruteChallenge'
|
||||
ScoringValue=60
|
||||
IdleHeavyAnim="BruteIdle"
|
||||
IdleRifleAnim="BruteIdle"
|
||||
RagDeathUpKick=100.000000
|
||||
MeleeRange=85.000000
|
||||
GroundSpeed=140.000000
|
||||
WaterSpeed=120.000000
|
||||
HealthMax=1000.000000
|
||||
Health=1000
|
||||
HeadHeight=2.500000
|
||||
HeadScale=1.300000
|
||||
MenuName="Brute.se"
|
||||
ControllerClass=Class'ScrnZedPack.BruteZombieController'
|
||||
MovementAnims(0)="BruteWalkC"
|
||||
MovementAnims(1)="BruteWalkC"
|
||||
WalkAnims(0)="BruteWalkC"
|
||||
WalkAnims(1)="BruteWalkC"
|
||||
WalkAnims(2)="RunL"
|
||||
WalkAnims(3)="RunR"
|
||||
IdleCrouchAnim="BruteIdle"
|
||||
IdleWeaponAnim="BruteIdle"
|
||||
IdleRestAnim="BruteIdle"
|
||||
AmbientSound=SoundGroup'ScrnZedPack_S.Brute.BruteIdle1Shot'
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.BruteMesh'
|
||||
PrePivot=(Z=0.000000)
|
||||
Skins(0)=Combiner'ScrnZedPack_T.Brute.Brute_Final'
|
||||
Mass=600.000000
|
||||
RotationRate=(Yaw=45000,Roll=0)
|
||||
}
|
||||
22
kf_sources/ScrnZedPack/Classes/ZombieClot_GRITTIER.uc
Normal file
22
kf_sources/ScrnZedPack/Classes/ZombieClot_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class ZombieClot_GRITTIER extends ZombieClot;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmClot'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegClot'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadClot'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
|
||||
MenuName="Grittier Clot"
|
||||
AmbientSound=Sound'KF_BaseClot.Clot_Idle1Loop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.CLOT_Freak'
|
||||
Skins(0)=Combiner'ScrnZedPack_T.clot_grittier.clot_grittier_cmb'
|
||||
}
|
||||
41
kf_sources/ScrnZedPack/Classes/ZombieCrawler_GRITTIER.uc
Normal file
41
kf_sources/ScrnZedPack/Classes/ZombieCrawler_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Code originally was taken from Scary Ghost's Super Zombies mutator
|
||||
class ZombieCrawler_GRITTIER extends ZombieCrawler;
|
||||
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
PounceSpeed= Rand(221)+330;
|
||||
MeleeRange= Rand(41)+50;
|
||||
}
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
if (InstigatedBy == none || class<KFWeaponDamageType>(DamType) == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmCrawler'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegCrawler'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadCrawler'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Acquire'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Acquire'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Acquire'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Crawler.Crawler_Acquire'
|
||||
GroundSpeed=190.000000
|
||||
WaterSpeed=175.000000
|
||||
MenuName="Crawler.se"
|
||||
AmbientSound=Sound'KF_BaseCrawler.Crawler_Idle'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Crawler_Freak'
|
||||
Skins(0)=Combiner'ScrnZedPack_T.crawler_grittier.crawler_grittier_cmb'
|
||||
}
|
||||
22
kf_sources/ScrnZedPack/Classes/ZombieFleshpound_GRITTIER.uc
Normal file
22
kf_sources/ScrnZedPack/Classes/ZombieFleshpound_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class ZombieFleshpound_GRITTIER extends ZombieFleshpound;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmPound'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegPound'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadPound'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Fleshpound.FP_Challenge'
|
||||
MenuName="Grittier Fleshpound"
|
||||
AmbientSound=Sound'KF_BaseFleshpound.FP_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.FleshPound_Freak'
|
||||
Skins(0)=Combiner'ScrnZedPack_T.fleshpound_grittier.fleshpound_grittier_cmb'
|
||||
}
|
||||
295
kf_sources/ScrnZedPack/Classes/ZombieGhost.uc
Normal file
295
kf_sources/ScrnZedPack/Classes/ZombieGhost.uc
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
// Completely invisible Stalker
|
||||
// (c) PooSH, 2014
|
||||
// used 'ClawAndMove' code from Scary Ghost's SuperStaler
|
||||
|
||||
class ZombieGhost extends ZombieStalker;
|
||||
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
// max distance squared for player to see cloacked Stalkers.
|
||||
// Beyond that distance Stalkers will appear completely invisible.
|
||||
var float CloakDistanceSqr;
|
||||
// Unclock distance squared for Commandos
|
||||
var float UncloakDistanceSqr;
|
||||
|
||||
var const Material CloakMat;
|
||||
var const Material InvisibleMat;
|
||||
var const Material UncloakMat, UncloakFBMat;
|
||||
var const Material GlowFX;
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{
|
||||
myLevel.AddPrecacheMaterial(default.CloakMat);
|
||||
myLevel.AddPrecacheMaterial(default.InvisibleMat);
|
||||
myLevel.AddPrecacheMaterial(default.UncloakMat);
|
||||
myLevel.AddPrecacheMaterial(default.UncloakFBMat);
|
||||
myLevel.AddPrecacheMaterial(default.GlowFX);
|
||||
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.stalker_env_cmb');
|
||||
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_diff');
|
||||
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_spec');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.StalkerCloakOpacity_cmb');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.StalkerCloakEnv_rot');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.stalker_opacity_osc');
|
||||
myLevel.AddPrecacheMaterial(Material'KFCharacters.StalkerSkin');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
simulated function PostNetBeginPlay()
|
||||
{
|
||||
super.PostNetBeginPlay();
|
||||
|
||||
if ( LocalKFHumanPawn != none ) {
|
||||
CloakDistanceSqr = fmax(CloakDistanceSqr, 3.0 * UncloakDistanceSqr * LocalKFHumanPawn.GetStalkerViewDistanceMulti());
|
||||
UncloakDistanceSqr *= LocalKFHumanPawn.GetStalkerViewDistanceMulti();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function RenderOverlays(Canvas Canvas)
|
||||
{
|
||||
Canvas.SetDrawColor(0, 92, 255, 255);
|
||||
super.RenderOverlays(Canvas);
|
||||
}
|
||||
|
||||
// makes Stalker invisible or glowing (for commando)
|
||||
simulated function CloakStalker()
|
||||
{
|
||||
// No cloaking if zapped
|
||||
if( bZapped )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bSpotted ) {
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
return;
|
||||
|
||||
Skins[0] = GlowFX;
|
||||
Skins[1] = GlowFX;
|
||||
bUnlit = true;
|
||||
}
|
||||
else if ( !bDecapitated && !bCrispified ) // No head, no cloak, honey. updated : Being charred means no cloak either :D
|
||||
{
|
||||
Visibility = 1;
|
||||
bCloaked = true;
|
||||
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
Return;
|
||||
|
||||
Skins[0] = InvisibleMat;
|
||||
Skins[1] = InvisibleMat;
|
||||
bUnlit = false;
|
||||
|
||||
// Invisible - no shadow
|
||||
if(PlayerShadow != none)
|
||||
PlayerShadow.bShadowActive = false;
|
||||
if(RealTimeShadow != none)
|
||||
RealTimeShadow.Destroy();
|
||||
|
||||
// Remove/disallow projectors on invisible people
|
||||
Projectors.Remove(0, Projectors.Length);
|
||||
bAcceptsProjectors = false;
|
||||
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function UnCloakStalker()
|
||||
{
|
||||
if( bZapped )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( !bCrispified )
|
||||
{
|
||||
LastUncloakTime = Level.TimeSeconds;
|
||||
|
||||
Visibility = default.Visibility;
|
||||
bCloaked = false;
|
||||
bUnlit = false;
|
||||
|
||||
// 25% chance of our Enemy saying something about us being invisible
|
||||
if( Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller.Enemy!=none &&
|
||||
PlayerController(Controller.Enemy.Controller)!=none )
|
||||
{
|
||||
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 17, "");
|
||||
KFGameType(Level.Game).bDidStalkerInvisibleMessage = true;
|
||||
}
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
Return;
|
||||
|
||||
if ( Skins[0] != UncloakMat )
|
||||
{
|
||||
Skins[1] = FinalBlend'KF_Specimens_Trip_T.stalker_fb';
|
||||
Skins[0] = UncloakMat;
|
||||
|
||||
if (PlayerShadow != none)
|
||||
PlayerShadow.bShadowActive = true;
|
||||
|
||||
bAcceptsProjectors = true;
|
||||
|
||||
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveHead()
|
||||
{
|
||||
Super(KFMonster).RemoveHead();
|
||||
|
||||
if (!bCrispified)
|
||||
{
|
||||
Skins[1] = UncloakFBMat;
|
||||
Skins[0] = UncloakMat;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
|
||||
{
|
||||
Super(KFMonster).PlayDying(DamageType,HitLoc);
|
||||
|
||||
if(bUnlit)
|
||||
bUnlit=!bUnlit;
|
||||
|
||||
LocalKFHumanPawn = none;
|
||||
|
||||
if (!bCrispified)
|
||||
{
|
||||
Skins[1] = UncloakFBMat;
|
||||
Skins[0] = UncloakMat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
local float DistanceSqr;
|
||||
|
||||
Super(KFMonster).Tick(DeltaTime);
|
||||
|
||||
// Keep the stalker moving toward its target when attacking
|
||||
if( Role == ROLE_Authority && bShotAnim && !bWaitForAnim && !bZapped ) {
|
||||
if( LookTarget!=None ) {
|
||||
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
|
||||
}
|
||||
}
|
||||
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
Return; // Servers aren't intrested in this info.
|
||||
|
||||
if( bZapped ) {
|
||||
// Make sure we check if we need to be cloaked as soon as the zap wears off
|
||||
NextCheckTime = Level.TimeSeconds;
|
||||
}
|
||||
else if( Level.TimeSeconds > NextCheckTime && Health > 0 )
|
||||
{
|
||||
NextCheckTime = Level.TimeSeconds + 0.5;
|
||||
|
||||
bSpotted = false;
|
||||
if ( LocalKFHumanPawn != none ) {
|
||||
DistanceSqr = VSizeSquared(Location - LocalKFHumanPawn.Location);
|
||||
if( LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers()
|
||||
&& DistanceSqr < UncloakDistanceSqr )
|
||||
{
|
||||
bSpotted = True;
|
||||
if ( Skins[0] != GlowFX ) {
|
||||
Skins[0] = GlowFX;
|
||||
Skins[1] = GlowFX;
|
||||
bUnlit = true;
|
||||
}
|
||||
}
|
||||
else if ( DistanceSqr < CloakDistanceSqr ) {
|
||||
if ( bCloaked && Skins[0] != CloakMat ) {
|
||||
Skins[0] = CloakMat;
|
||||
Skins[1] = CloakMat;
|
||||
bUnlit = false;
|
||||
}
|
||||
}
|
||||
else if ( Skins[0] != InvisibleMat ) {
|
||||
CloakStalker();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if ( !bShotAnim && Physics != PHYS_Swimming && CanAttack(A) ) {
|
||||
bShotAnim = true;
|
||||
SetAnimAction('ClawAndMove');
|
||||
}
|
||||
}
|
||||
|
||||
// copied from ZombieSuperStalker (c) Scary Ghost
|
||||
simulated event SetAnimAction(name NewAction)
|
||||
{
|
||||
if( NewAction=='' )
|
||||
Return;
|
||||
|
||||
ExpectingChannel = AttackAndMoveDoAnimAction(NewAction);
|
||||
|
||||
bWaitForAnim= false;
|
||||
|
||||
if( Level.NetMode!=NM_Client ) {
|
||||
AnimAction = NewAction;
|
||||
bResetAnimAct = True;
|
||||
ResetAnimActTime = Level.TimeSeconds+0.3;
|
||||
}
|
||||
}
|
||||
|
||||
// copied from ZombieSuperStalker (c) Scary Ghost
|
||||
simulated function int AttackAndMoveDoAnimAction( name AnimName )
|
||||
{
|
||||
local int meleeAnimIndex;
|
||||
local float duration;
|
||||
|
||||
if( AnimName == 'ClawAndMove' ) {
|
||||
meleeAnimIndex = Rand(3);
|
||||
AnimName = meleeAnims[meleeAnimIndex];
|
||||
CurrentDamtype = ZombieDamType[meleeAnimIndex];
|
||||
|
||||
duration= GetAnimDuration(AnimName, 1.0);
|
||||
}
|
||||
|
||||
if( AnimName=='StalkerSpinAttack' || AnimName=='StalkerAttack1' || AnimName=='JumpAttack') {
|
||||
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return super.DoAnimAction( AnimName );
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
CloakDistanceSqr=62500.000000
|
||||
UncloakDistanceSqr=360000.000000
|
||||
CloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
|
||||
InvisibleMat=Shader'KF_Specimens_Trip_T.patriarch_invisible'
|
||||
UncloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
|
||||
UncloakFBMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
|
||||
GlowFX=FinalBlend'ScrnZedPack_T.Ghost.GhostGlow'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmStalker'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegStalker'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadStalker'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
MenuName="Ghost"
|
||||
AmbientSound=Sound'KF_BaseStalker.Stalker_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Stalker_Freak'
|
||||
Skins(0)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
|
||||
Skins(1)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
|
||||
}
|
||||
91
kf_sources/ScrnZedPack/Classes/ZombieGorefast_GRITTIER.uc
Normal file
91
kf_sources/ScrnZedPack/Classes/ZombieGorefast_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
// Code originally was taken from Scary Ghost's Super Zombies mutator
|
||||
class ZombieGorefast_GRITTIER extends ZombieGorefast;
|
||||
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
var float minRageDist;
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
if (InstigatedBy == none || class<KFWeaponDamageType>(DamType) == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
}
|
||||
function RangedAttack(Actor A) {
|
||||
Super(KFMonster).RangedAttack(A);
|
||||
if( !bShotAnim && !bDecapitated && VSize(A.Location-Location)<=minRageDist )
|
||||
GoToState('RunningState');
|
||||
}
|
||||
|
||||
state RunningState {
|
||||
// Don't override speed in this state
|
||||
function bool CanSpeedAdjust() {
|
||||
return super.CanSpeedAdjust();
|
||||
}
|
||||
|
||||
function BeginState() {
|
||||
super.BeginState();
|
||||
}
|
||||
|
||||
function EndState() {
|
||||
super.EndState();
|
||||
}
|
||||
|
||||
function RemoveHead() {
|
||||
super.RemoveHead();
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A) {
|
||||
|
||||
if ( bShotAnim || Physics == PHYS_Swimming)
|
||||
return;
|
||||
else if ( CanAttack(A) ) {
|
||||
bShotAnim = true;
|
||||
|
||||
//Always do the charging melee attack
|
||||
SetAnimAction('ClawAndMove');
|
||||
RunAttackTimeout = GetAnimDuration('GoreAttack1', 1.0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime) {
|
||||
super.Tick(DeltaTime);
|
||||
}
|
||||
|
||||
|
||||
Begin:
|
||||
GoTo('CheckCharge');
|
||||
CheckCharge:
|
||||
if( Controller!=None && Controller.Target!=None && VSize(Controller.Target.Location-Location)<minRageDist ) {
|
||||
Sleep(0.5+ FRand() * 0.5);
|
||||
//log("Still charging");
|
||||
GoTo('CheckCharge');
|
||||
}
|
||||
else {
|
||||
//log("Done charging");
|
||||
GoToState('');
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
minRageDist=1400.000000
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmGorefast'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegGorefast'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadGorefast'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_Challenge'
|
||||
MenuName="Gorefast.se"
|
||||
AmbientSound=Sound'KF_BaseGorefast.Gorefast_Idle'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.GoreFast_Freak'
|
||||
Skins(0)=Combiner'ScrnZedPack_T.gorefast_grittier.gorefast_grittier_cmb'
|
||||
}
|
||||
144
kf_sources/ScrnZedPack/Classes/ZombieHusk_GRITTIER.uc
Normal file
144
kf_sources/ScrnZedPack/Classes/ZombieHusk_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// Code originally was taken from Scary Ghost's Super Zombies mutator
|
||||
class ZombieHusk_GRITTIER extends ZombieHusk;
|
||||
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
var int ShotsRemaining;
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{//should be derived and used.
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.husk_grittier.husk_grittier_diff');
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.husk_grittier.husk_grittier_emissive_mask');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.husk_grittier.husk_grittier_energy_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.husk_grittier.husk_grittier_env_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.husk_grittier.husk_grittier_fire_cmb');
|
||||
myLevel.AddPrecacheMaterial(Material'ScrnZedPack_T.husk_grittier.husk_grittier_shdr');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.husk_grittier.husk_grittier_cmb');
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
ShotsRemaining = Rand(default.ShotsRemaining) + 1;
|
||||
}
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
if (InstigatedBy == none || class<KFWeaponDamageType>(DamType) == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A) {
|
||||
local int LastFireTime;
|
||||
|
||||
if ( bShotAnim )
|
||||
return;
|
||||
|
||||
if ( Physics == PHYS_Swimming ) {
|
||||
SetAnimAction('Claw');
|
||||
bShotAnim = true;
|
||||
LastFireTime = Level.TimeSeconds;
|
||||
}
|
||||
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
|
||||
bShotAnim = true;
|
||||
LastFireTime = Level.TimeSeconds;
|
||||
SetAnimAction('Claw');
|
||||
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
}
|
||||
else if ( (KFDoorMover(A) != none ||
|
||||
(!Region.Zone.bDistanceFog && VSize(A.Location-Location) <= 65535) ||
|
||||
(Region.Zone.bDistanceFog && VSizeSquared(A.Location-Location) < (Square(Region.Zone.DistanceFogEnd) * 0.8))) // Make him come out of the fog a bit
|
||||
&& !bDecapitated )
|
||||
{
|
||||
bShotAnim = true;
|
||||
|
||||
SetAnimAction('ShootBurns');
|
||||
Controller.bPreparingMove = true;
|
||||
Acceleration = vect(0,0,0);
|
||||
|
||||
if(--ShotsRemaining > 0) {
|
||||
NextFireProjectileTime= Level.TimeSeconds;
|
||||
}
|
||||
else {
|
||||
NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0);
|
||||
ShotsRemaining = Rand(default.ShotsRemaining) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SpawnTwoShots() {
|
||||
local vector X,Y,Z, FireStart;
|
||||
local rotator FireRotation;
|
||||
local KFMonsterController KFMonstControl;
|
||||
|
||||
if( Controller!=None && KFDoorMover(Controller.Target)!=None ) {
|
||||
Controller.Target.TakeDamage(22,Self,Location,vect(0,0,0),Class'DamTypeVomit');
|
||||
return;
|
||||
}
|
||||
|
||||
GetAxes(Rotation,X,Y,Z);
|
||||
FireStart = GetBoneCoords('Barrel').Origin;
|
||||
if ( !SavedFireProperties.bInitialized ) {
|
||||
SavedFireProperties.AmmoClass = Class'SkaarjAmmo';
|
||||
SavedFireProperties.ProjectileClass = Class'HuskFireProjectileSE';
|
||||
SavedFireProperties.WarnTargetPct = 1;
|
||||
SavedFireProperties.MaxRange = 65535;
|
||||
SavedFireProperties.bTossed = False;
|
||||
SavedFireProperties.bTrySplash = true;
|
||||
SavedFireProperties.bLeadTarget = True;
|
||||
SavedFireProperties.bInstantHit = False;
|
||||
SavedFireProperties.bInitialized = True;
|
||||
}
|
||||
|
||||
// Turn off extra collision before spawning vomit, otherwise spawn fails
|
||||
ToggleAuxCollision(false);
|
||||
|
||||
FireRotation = Controller.AdjustAim(SavedFireProperties,FireStart,600);
|
||||
|
||||
foreach DynamicActors(class'KFMonsterController', KFMonstControl) {
|
||||
if( KFMonstControl != Controller ) {
|
||||
if( PointDistToLine(KFMonstControl.Pawn.Location, vector(FireRotation), FireStart) < 75 ) {
|
||||
KFMonstControl.GetOutOfTheWayOfShot(vector(FireRotation),FireStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spawn(Class'HuskFireProjectileSE',Self,,FireStart,FireRotation);
|
||||
|
||||
// Turn extra collision back on
|
||||
ToggleAuxCollision(true);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ShotsRemaining=4
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Bloat.Bloat_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmHusk'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegHusk'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadHusk'
|
||||
DetachedSpecialArmClass=Class'KFChar.SeveredArmHuskGun'
|
||||
BurningWalkFAnims(0)="WalkF"
|
||||
BurningWalkFAnims(1)="WalkF"
|
||||
BurningWalkFAnims(2)="WalkF"
|
||||
BurningWalkAnims(0)="WalkB"
|
||||
BurningWalkAnims(1)="WalkL"
|
||||
BurningWalkAnims(2)="WalkR"
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Husk.Husk_Challenge'
|
||||
MenuName="Husk.se"
|
||||
ControllerClass=Class'ScrnZedPack.HuskZombieControllerSE'
|
||||
AmbientSound=Sound'KF_BaseHusk.Husk_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks2_Trip.Burns_Freak'
|
||||
Skins(0)=Texture'ScrnZedPack_T.husk_grittier.husk_grittier_tatters'
|
||||
Skins(1)=Shader'ScrnZedPack_T.husk_grittier.husk_grittier_shdr'
|
||||
}
|
||||
210
kf_sources/ScrnZedPack/Classes/ZombieJason.uc
Normal file
210
kf_sources/ScrnZedPack/Classes/ZombieJason.uc
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
class ZombieJason extends ZombieScrake;
|
||||
|
||||
#exec load obj file=ScrnZedPack_T.utx
|
||||
#exec load obj file=ScrnZedPack_S.uax
|
||||
#exec load obj file=ScrnZedPack_A.ukx
|
||||
|
||||
var int OriginalMeleeDamage; // default melee damage, adjusted by game's difficulty
|
||||
var transient bool bFlippedOver;
|
||||
var transient float LastFlipOverTime;
|
||||
var float FlipOverDuration;
|
||||
var bool bWasRaged; // set to true, if Jason is raged or was raged before
|
||||
var float RageHealthPct;
|
||||
|
||||
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
OriginalMeleeDamage = MeleeDamage;
|
||||
FlipOverDuration = GetAnimDuration('KnockDown');
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
if ( bFlippedOver && Level.TimeSeconds > LastFlipOverTime + FlipOverDuration )
|
||||
bFlippedOver = false;
|
||||
}
|
||||
|
||||
// Machete has no Exhaust ;)
|
||||
simulated function SpawnExhaustEmitter() {}
|
||||
simulated function UpdateExhaustEmitter() {}
|
||||
|
||||
function bool FlipOver()
|
||||
{
|
||||
bFlippedOver= super.FlipOver();
|
||||
if ( bFlippedOver ) {
|
||||
LastFlipOverTime = Level.TimeSeconds;
|
||||
// do not rotate while stunned
|
||||
Controller.Focus = none;
|
||||
Controller.FocalPoint = Location + 512*vector(Rotation);
|
||||
}
|
||||
return bFlippedOver;
|
||||
}
|
||||
|
||||
function bool CanGetOutOfWay()
|
||||
{
|
||||
return !bFlippedOver; // can't dodge husk fireballs while stunned
|
||||
}
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector HitLocation, Vector Momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
local bool bIsHeadShot;
|
||||
local float headShotCheckScale;
|
||||
local class<KFWeaponDamageType> KFDamType;
|
||||
local int OldHealth, DamageDone;
|
||||
|
||||
KFDamType = class<KFWeaponDamageType>(DamType);
|
||||
|
||||
if ( InstigatedBy != none && KFDamType != none ) {
|
||||
if ( KFDamType.default.bCheckForHeadShots ) {
|
||||
headShotCheckScale= 1.0;
|
||||
if (class<DamTypeMelee>(DamType) != none) {
|
||||
headShotCheckScale*= 1.25;
|
||||
}
|
||||
bIsHeadShot = IsHeadShot(Hitlocation, normal(Momentum), 1.0);
|
||||
}
|
||||
|
||||
if ( ClassIsChildOf(DamType, class'DamTypePipeBomb') )
|
||||
Damage *= 1.5;
|
||||
else if ( bIsHeadShot && Level.Game.GameDifficulty >= 5.0 && class<DamTypeCrossbow>(DamType) != none )
|
||||
Damage *= 0.5;
|
||||
|
||||
OldHealth = Health;
|
||||
super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
DamageDone = OldHealth - Health;
|
||||
|
||||
if ( !bDecapitated ) {
|
||||
if( bFlippedOver ) {
|
||||
if ( Level.Game.GameDifficulty >= 7.0 && Health>0 && !bIsHeadShot && DamageDone<800
|
||||
&& Level.TimeSeconds - LastFlipOverTime > 0.1
|
||||
&& (DamageDone > 300 || (Damage > 50 && KFDamType.default.bSniperWeapon)) )
|
||||
{
|
||||
// [HoE only] Break stun if Jason is hit with sniper weapon to the body
|
||||
bFlippedOver = false;
|
||||
bWaitForAnim = false;
|
||||
bShotAnim = false;
|
||||
if ( Controller != none )
|
||||
Controller.GoToState('ZombieHunt');
|
||||
GoToState('RunningState');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( Level.Game.GameDifficulty >= 5.0 && !IsInState('SawingLoop') && !IsInState('RunningState') && float(Health) / HealthMax < RageHealthPct )
|
||||
RangedAttack(InstigatedBy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if ( bShotAnim || Physics == PHYS_Swimming)
|
||||
return;
|
||||
else if ( CanAttack(A) )
|
||||
{
|
||||
bShotAnim = true;
|
||||
SetAnimAction(MeleeAnims[Rand(2)]);
|
||||
CurrentDamType = ZombieDamType[0];
|
||||
//PlaySound(sound'Claw2s', SLOT_None); KFTODO: Replace this
|
||||
GoToState('SawingLoop');
|
||||
}
|
||||
|
||||
if( !bShotAnim && !bDecapitated ) {
|
||||
if ( bWasRaged || float(Health)/HealthMax < 0.5
|
||||
|| (Level.Game.GameDifficulty >= 5.0 && float(Health)/HealthMax < RageHealthPct) )
|
||||
GoToState('RunningState');
|
||||
}
|
||||
}
|
||||
|
||||
State SawingLoop
|
||||
{
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if ( bShotAnim )
|
||||
return;
|
||||
else if ( CanAttack(A) )
|
||||
{
|
||||
Acceleration = vect(0,0,0);
|
||||
bShotAnim = true;
|
||||
MeleeDamage = OriginalMeleeDamage*0.6; // fixed difficulty multiplier -- PooSH
|
||||
SetAnimAction('SawImpaleLoop');
|
||||
CurrentDamType = ZombieDamType[0];
|
||||
if( AmbientSound != SawAttackLoopSound )
|
||||
{
|
||||
AmbientSound=SawAttackLoopSound;
|
||||
}
|
||||
}
|
||||
else GoToState('');
|
||||
}
|
||||
}
|
||||
|
||||
simulated function float GetOriginalGroundSpeed()
|
||||
{
|
||||
local float result;
|
||||
|
||||
result = OriginalGroundSpeed;
|
||||
if ( bWasRaged || bCharging )
|
||||
result *= 3.5;
|
||||
else if( bZedUnderControl )
|
||||
result *= 1.25;
|
||||
|
||||
if ( bBurnified )
|
||||
result *= 0.8;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
state RunningState
|
||||
{
|
||||
function BeginState()
|
||||
{
|
||||
bWasRaged = true;
|
||||
|
||||
if( bZapped )
|
||||
GoToState('');
|
||||
else {
|
||||
bCharging = true;
|
||||
SetGroundSpeed(GetOriginalGroundSpeed());
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
PostNetReceive();
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
bCharging = False;
|
||||
if( !bZapped )
|
||||
SetGroundSpeed(GetOriginalGroundSpeed());
|
||||
if( Level.NetMode!=NM_DedicatedServer )
|
||||
PostNetReceive();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RageHealthPct=0.750000
|
||||
SawAttackLoopSound=Sound'KF_BaseGorefast.Attack.Gorefast_AttackSwish3'
|
||||
StunsRemaining=5
|
||||
BleedOutDuration=7.000000
|
||||
MeleeDamage=25
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.GoreFast.Gorefast_HitPlayer'
|
||||
HeadHealth=800.000000
|
||||
ScoringValue=300
|
||||
HealthMax=1500.000000
|
||||
Health=1500
|
||||
MenuName="Jason.se"
|
||||
AmbientSound=Sound'ScrnZedPack_S.Jason.Jason_Sound'
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.JasonMesh'
|
||||
Skins(0)=Shader'ScrnZedPack_T.Jason.Jason__FB'
|
||||
Skins(1)=Texture'ScrnZedPack_T.Jason.JVMaskB'
|
||||
Skins(2)=Combiner'ScrnZedPack_T.Jason.Machete_cmb'
|
||||
}
|
||||
26
kf_sources/ScrnZedPack/Classes/ZombieScrake_GRITTIER.uc
Normal file
26
kf_sources/ScrnZedPack/Classes/ZombieScrake_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
class ZombieScrake_GRITTIER extends ZombieScrake;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
SawAttackLoopSound=Sound'KF_BaseScrake.Chainsaw.Scrake_Chainsaw_Impale'
|
||||
ChainSawOffSound=SoundGroup'KF_ChainsawSnd.Chainsaw_Deselect'
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Chainsaw_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmScrake'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegScrake'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadScrake'
|
||||
DetachedSpecialArmClass=Class'KFChar.SeveredArmScrakeSaw'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Scrake.Scrake_Challenge'
|
||||
MenuName="Grittier Scrake"
|
||||
AmbientSound=Sound'KF_BaseScrake.Chainsaw.Scrake_Chainsaw_Idle'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Scrake_Freak'
|
||||
Skins(0)=Shader'ScrnZedPack_T.scrake_grittier.scrake_grittier_FB'
|
||||
Skins(1)=TexPanner'KF_Specimens_Trip_T.scrake_saw_panner'
|
||||
}
|
||||
626
kf_sources/ScrnZedPack/Classes/ZombieShiver.uc
Normal file
626
kf_sources/ScrnZedPack/Classes/ZombieShiver.uc
Normal file
|
|
@ -0,0 +1,626 @@
|
|||
class ZombieShiver extends KFMonster;
|
||||
|
||||
#exec load obj file=ScrnZedPack_T.utx
|
||||
#exec load obj file=ScrnZedPack_S.uax
|
||||
#exec load obj file=ScrnZedPack_A.ukx
|
||||
|
||||
var name WalkAnim, RunAnim;
|
||||
|
||||
// Head twitch
|
||||
var rotator CurHeadRot, NextHeadRot, HeadRot;
|
||||
var float NextHeadTime;
|
||||
var float MaxHeadTime;
|
||||
var float MaxTilt, MaxTurn;
|
||||
|
||||
// Targetting, charging
|
||||
var float TeleportBlockTime;
|
||||
var float HeadOffsetY;
|
||||
|
||||
var transient bool bRunning, bClientRunning;
|
||||
var bool bDelayedReaction;
|
||||
var bool bCanSeeTarget;
|
||||
var float SeeTargetTime;
|
||||
var float RunUntilTime;
|
||||
var float RunCooldownEnd;
|
||||
var float PeriodSeeTarget;
|
||||
var float PeriodRunBase;
|
||||
var float PeriodRunRan;
|
||||
var float PeriodRunCoolBase;
|
||||
var float PeriodRunCoolRan;
|
||||
|
||||
// Teleporting
|
||||
var byte FadeStage;
|
||||
var byte OldFadeStage;
|
||||
var float AlphaFader;
|
||||
var bool bFlashTeleporting;
|
||||
var float LastFlashTime;
|
||||
var float MinTeleportDist, MaxTeleportDist;
|
||||
var float MinLandDist, MaxLandDist; // How close we can teleport to the target (collision cylinders are taken into account)
|
||||
var int MaxTeleportAttempts; // Attempts per angle
|
||||
var int MaxTeleportAngles;
|
||||
var ColorModifier MatAlphaSkin;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if (Role == ROLE_Authority)
|
||||
FadeStage, bRunning;
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
if (Level.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
MatAlphaSkin = ColorModifier(Level.ObjectPool.AllocateObject(class'ColorModifier'));
|
||||
if (MatAlphaSkin != none)
|
||||
{
|
||||
MatAlphaSkin.Color = class'Canvas'.static.MakeColor(255, 255, 255, 255);
|
||||
MatAlphaSkin.RenderTwoSided = false;
|
||||
MatAlphaSkin.AlphaBlend = true;
|
||||
MatAlphaSkin.Material = Skins[0];
|
||||
Skins[0] = MatAlphaSkin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PostNetReceive()
|
||||
{
|
||||
super.PostNetReceive();
|
||||
|
||||
if( bClientRunning != bRunning )
|
||||
{
|
||||
bClientRunning = bRunning;
|
||||
if( bRunning ) {
|
||||
MovementAnims[0] = RunAnim;
|
||||
}
|
||||
else {
|
||||
MovementAnims[0] = WalkAnim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Destroyed()
|
||||
{
|
||||
if (Level.NetMode != NM_DedicatedServer && MatAlphaSkin != none)
|
||||
{
|
||||
Skins[0] = default.Skins[0];
|
||||
Level.ObjectPool.FreeObject(MatAlphaSkin);
|
||||
}
|
||||
|
||||
Super.Destroyed();
|
||||
}
|
||||
|
||||
simulated function StopBurnFX()
|
||||
{
|
||||
if (bBurnApplied)
|
||||
{
|
||||
MatAlphaSkin.Material = Texture'PatchTex.Common.ZedBurnSkin';
|
||||
Skins[0] = MatAlphaSkin;
|
||||
}
|
||||
|
||||
Super.StopBurnFX();
|
||||
}
|
||||
|
||||
function RangedAttack(Actor A)
|
||||
{
|
||||
if (bShotAnim || Physics == PHYS_Swimming)
|
||||
return;
|
||||
else if (CanAttack(A))
|
||||
{
|
||||
bShotAnim = true;
|
||||
SetAnimAction('Claw');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
state Running
|
||||
{
|
||||
function BeginState()
|
||||
{
|
||||
bRunning = true;
|
||||
RunUntilTime = Level.TimeSeconds + PeriodRunBase + FRand() * PeriodRunRan;
|
||||
MovementAnims[0] = RunAnim;
|
||||
}
|
||||
|
||||
function EndState()
|
||||
{
|
||||
bRunning = false;
|
||||
GroundSpeed = global.GetOriginalGroundSpeed();
|
||||
RunCooldownEnd = Level.TimeSeconds + PeriodRunCoolBase + FRand() * PeriodRunCoolRan;
|
||||
MovementAnims[0] = WalkAnim;
|
||||
}
|
||||
|
||||
function float GetOriginalGroundSpeed()
|
||||
{
|
||||
return global.GetOriginalGroundSpeed() * 2.5;
|
||||
}
|
||||
|
||||
function Tick(float Delta)
|
||||
{
|
||||
Global.Tick(Delta);
|
||||
if (RunUntilTime < Level.TimeSeconds)
|
||||
GotoState('');
|
||||
GroundSpeed = GetOriginalGroundSpeed(); }
|
||||
|
||||
function bool CanSpeedAdjust()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector momentum, class<DamageType> DamType, optional int HitIndex)
|
||||
{
|
||||
if (InstigatedBy == none || class<KFWeaponDamageType>(DamType) == none)
|
||||
Super(Monster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType); // skip NONE-reference error
|
||||
else
|
||||
Super(KFMonster).TakeDamage(Damage, instigatedBy, hitLocation, momentum, DamType);
|
||||
}
|
||||
|
||||
// returns true also for KnockDown (stun) animation -- PooSH
|
||||
simulated function bool AnimNeedsWait(name TestAnim)
|
||||
{
|
||||
if( TestAnim == 'DoorBash' || TestAnim == 'KnockDown' )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ExpectingChannel == 0;
|
||||
}
|
||||
|
||||
simulated function float GetOriginalGroundSpeed()
|
||||
{
|
||||
local float result;
|
||||
|
||||
result = OriginalGroundSpeed;
|
||||
|
||||
if( bZedUnderControl )
|
||||
result *= 1.25;
|
||||
|
||||
if ( bBurnified )
|
||||
result *= 0.8;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
simulated function Tick(float Delta)
|
||||
{
|
||||
Super.Tick(Delta);
|
||||
|
||||
if (Health > 0 && !bBurnApplied)
|
||||
{
|
||||
// Handle targetting
|
||||
if (Level.NetMode != NM_Client && !bDecapitated)
|
||||
{
|
||||
if (Controller == none || Controller.Target == none || !Controller.LineOfSightTo(Controller.Target))
|
||||
{
|
||||
if (bCanSeeTarget)
|
||||
bCanSeeTarget = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bCanSeeTarget)
|
||||
{
|
||||
bCanSeeTarget = true;
|
||||
SeeTargetTime = Level.TimeSeconds;
|
||||
}
|
||||
else if (Level.TimeSeconds > SeeTargetTime + PeriodSeeTarget)
|
||||
{
|
||||
if (VSize(Controller.Target.Location - Location) < MaxTeleportDist)
|
||||
{
|
||||
if (VSize(Controller.Target.Location - Location) > MinTeleportDist || !Controller.ActorReachable(Controller.Target))
|
||||
{
|
||||
if (CanTeleport())
|
||||
StartTelePort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CanRun())
|
||||
GotoState('Running');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle client-side teleport variables
|
||||
if (!bBurnApplied)
|
||||
{
|
||||
if (Level.NetMode != NM_DedicatedServer && OldFadeStage != FadeStage)
|
||||
{
|
||||
OldFadeStage = FadeStage;
|
||||
|
||||
if (FadeStage == 2)
|
||||
AlphaFader = 0;
|
||||
else
|
||||
AlphaFader = 255;
|
||||
}
|
||||
|
||||
// Handle teleporting
|
||||
if (FadeStage == 1) // Fade out (pre-teleport)
|
||||
{
|
||||
AlphaFader = FMax(AlphaFader - Delta * 512, 0);
|
||||
|
||||
if (Level.NetMode != NM_Client && AlphaFader == 0)
|
||||
{
|
||||
SetCollision(true, true);
|
||||
FlashTeleport();
|
||||
SetCollision(false, false);
|
||||
FadeStage = 2;
|
||||
}
|
||||
}
|
||||
else if (FadeStage == 2) // Fade in (post-teleport)
|
||||
{
|
||||
AlphaFader = FMin(AlphaFader + Delta * 512, 255);
|
||||
|
||||
if (Level.NetMode != NM_Client && AlphaFader == 255)
|
||||
{
|
||||
FadeStage = 0;
|
||||
SetCollision(true, true);
|
||||
GotoState('Running');
|
||||
}
|
||||
}
|
||||
|
||||
if (Level.NetMode != NM_DedicatedServer && ColorModifier(Skins[0]) != none)
|
||||
ColorModifier(Skins[0]).Color.A = AlphaFader;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
simulated function DebugHead()
|
||||
{
|
||||
local coords C;
|
||||
local vector HeadLoc;
|
||||
local float Radius;
|
||||
|
||||
Radius = HeadRadius * HeadScale;
|
||||
|
||||
ClearStayingDebugLines();
|
||||
// based on head bone
|
||||
C = GetBoneCoords(HeadBone);
|
||||
HeadLoc = C.Origin + (HeadHeight * HeadScale * C.XAxis) + HeadOffsetY * C.YAxis;
|
||||
DrawDebugSphere(HeadLoc, Radius, 16, 0, 100, 255);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(1,0,0), HeadLoc + Radius*vect(1,0,0), 0, 100, 255);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(0,1,0), HeadLoc + Radius*vect(0,1,0), 0, 100, 255);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(0,0,1), HeadLoc + Radius*vect(0,0,1), 0, 100, 255);
|
||||
|
||||
// based on OnlineHeadshotOffset
|
||||
HeadLoc = Location + (OnlineHeadshotOffset >> Rotation);
|
||||
Radius *= OnlineHeadshotScale;
|
||||
DrawDebugSphere(HeadLoc, Radius, 16, 255, 0, 0);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(1,0,0), HeadLoc + Radius*vect(1,0,0), 255, 0, 0);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(0,1,0), HeadLoc + Radius*vect(0,1,0), 255, 0, 0);
|
||||
DrawStayingDebugLine(HeadLoc - Radius*vect(0,0,1), HeadLoc + Radius*vect(0,0,1), 255, 0, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
function bool CanTeleport()
|
||||
{
|
||||
return !bFlashTeleporting && !bBurnified && Physics == PHYS_Walking && Level.TimeSeconds > TeleportBlockTime
|
||||
&& LastFlashTime + 7.5 < Level.TimeSeconds;
|
||||
}
|
||||
|
||||
function bool CanRun()
|
||||
{
|
||||
return (!bFlashTeleporting && !IsInState('Running') && RunCooldownEnd < Level.TimeSeconds);
|
||||
}
|
||||
|
||||
function bool IsHeadShot(vector loc, vector ray, float AdditionalScale)
|
||||
{
|
||||
local coords C;
|
||||
local vector HeadLoc, B, M, diff;
|
||||
local float t, DotMM, Distance;
|
||||
local int look;
|
||||
local bool bUseAltHeadShotLocation;
|
||||
local bool bWasAnimating;
|
||||
|
||||
if (HeadBone == '')
|
||||
return False;
|
||||
|
||||
// If we are a dedicated server estimate what animation is most likely playing on the client
|
||||
if (Level.NetMode == NM_DedicatedServer)
|
||||
{
|
||||
if (Physics == PHYS_Falling)
|
||||
PlayAnim(AirAnims[0], 1.0, 0.0);
|
||||
else if (Physics == PHYS_Walking)
|
||||
{
|
||||
// Only play the idle anim if we're not already doing a different anim.
|
||||
// This prevents anims getting interrupted on the server and borking things up - Ramm
|
||||
|
||||
if( !IsAnimating(0) && !IsAnimating(1) )
|
||||
{
|
||||
if (bIsCrouched)
|
||||
{
|
||||
PlayAnim(IdleCrouchAnim, 1.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bUseAltHeadShotLocation=true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bWasAnimating = true;
|
||||
}
|
||||
|
||||
if ( bDoTorsoTwist )
|
||||
{
|
||||
SmoothViewYaw = Rotation.Yaw;
|
||||
SmoothViewPitch = ViewPitch;
|
||||
|
||||
look = (256 * ViewPitch) & 65535;
|
||||
if (look > 32768)
|
||||
look -= 65536;
|
||||
|
||||
SetTwistLook(0, look);
|
||||
}
|
||||
}
|
||||
else if (Physics == PHYS_Swimming)
|
||||
PlayAnim(SwimAnims[0], 1.0, 0.0);
|
||||
|
||||
if( !bWasAnimating )
|
||||
{
|
||||
SetAnimFrame(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
if( bUseAltHeadShotLocation )
|
||||
{
|
||||
HeadLoc = Location + (OnlineHeadshotOffset >> Rotation);
|
||||
AdditionalScale *= OnlineHeadshotScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
C = GetBoneCoords(HeadBone);
|
||||
|
||||
HeadLoc = C.Origin + (HeadHeight * HeadScale * AdditionalScale * C.XAxis)
|
||||
+ HeadOffsetY * C.YAxis;
|
||||
}
|
||||
//ServerHeadLocation = HeadLoc;
|
||||
|
||||
// Express snipe trace line in terms of B + tM
|
||||
B = loc;
|
||||
M = ray * (2.0 * CollisionHeight + 2.0 * CollisionRadius);
|
||||
|
||||
// Find Point-Line Squared Distance
|
||||
diff = HeadLoc - B;
|
||||
t = M Dot diff;
|
||||
if (t > 0)
|
||||
{
|
||||
DotMM = M dot M;
|
||||
if (t < DotMM)
|
||||
{
|
||||
t = t / DotMM;
|
||||
diff = diff - (t * M);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 1;
|
||||
diff -= M;
|
||||
}
|
||||
}
|
||||
else
|
||||
t = 0;
|
||||
|
||||
Distance = Sqrt(diff Dot diff);
|
||||
|
||||
return (Distance < (HeadRadius * HeadScale * AdditionalScale));
|
||||
}
|
||||
|
||||
function StartTeleport()
|
||||
{
|
||||
FadeStage = 1;
|
||||
AlphaFader = 255;
|
||||
SetCollision(false, false);
|
||||
bFlashTeleporting = true;
|
||||
}
|
||||
|
||||
function FlashTeleport()
|
||||
{
|
||||
local Actor Target;
|
||||
local vector OldLoc;
|
||||
local vector NewLoc;
|
||||
local vector HitLoc;
|
||||
local vector HitNorm;
|
||||
local rotator RotOld;
|
||||
local rotator RotNew;
|
||||
local float LandTargetDist;
|
||||
local int iEndAngle;
|
||||
local int iAttempts;
|
||||
|
||||
if (Controller == none || Controller.Target == none)
|
||||
return;
|
||||
|
||||
Target = Controller.Target;
|
||||
RotOld = rotator(Target.Location - Location);
|
||||
RotNew = RotOld;
|
||||
OldLoc = Location;
|
||||
|
||||
for (iEndAngle = 0; iEndAngle < MaxTeleportAngles; iEndAngle++)
|
||||
{
|
||||
RotNew = RotOld;
|
||||
RotNew.Yaw += iEndAngle * (65536 / MaxTelePortAngles);
|
||||
|
||||
for (iAttempts = 0; iAttempts < MaxTeleportAttempts; iAttempts++)
|
||||
{
|
||||
LandTargetDist = Target.CollisionRadius + CollisionRadius +
|
||||
MinLandDist + (MaxLandDist - MinLandDist) * (iAttempts / (MaxTeleportAttempts - 1.0));
|
||||
|
||||
NewLoc = Target.Location - vector(RotNew) * LandTargetDist; // Target.Location - Location
|
||||
NewLoc.Z = Target.Location.Z;
|
||||
|
||||
if (Trace(HitLoc, HitNorm, NewLoc + vect(0, 0, -500), NewLoc) != none)
|
||||
NewLoc.Z = HitLoc.Z + CollisionHeight;
|
||||
|
||||
// Try a new location
|
||||
if (SetLocation(NewLoc))
|
||||
{
|
||||
SetPhysics(PHYS_Walking);
|
||||
|
||||
if (Controller.PointReachable(Target.Location))
|
||||
{
|
||||
Velocity = vect(0, 0, 0);
|
||||
Acceleration = vect(0, 0, 0);
|
||||
SetRotation(rotator(Target.Location - Location));
|
||||
|
||||
PlaySound(Sound'ScrnZedPack_S.Shiver.ShiverWarpGroup', SLOT_Interact, 4.0);
|
||||
Controller.GotoState('');
|
||||
MonsterController(Controller).WhatToDoNext(0);
|
||||
goto Teleported;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset location
|
||||
SetLocation(OldLoc);
|
||||
}
|
||||
}
|
||||
|
||||
Teleported:
|
||||
|
||||
bFlashTeleporting = false;
|
||||
LastFlashTime = Level.TimeSeconds;
|
||||
}
|
||||
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
// (!)
|
||||
Super.Died(Killer, damageType, HitLocation);
|
||||
}
|
||||
|
||||
function RemoveHead()
|
||||
{
|
||||
local class<KFWeaponDamageType> KFDamType;
|
||||
|
||||
KFDamType = class<KFWeaponDamageType>(LastDamagedByType);
|
||||
if ( KFDamType != none && !KFDamType.default.bIsPowerWeapon
|
||||
&& !KFDamType.default.bSniperWeapon && !KFDamType.default.bIsMeleeDamage
|
||||
&& !KFDamType.default.bIsExplosive && !KFDamType.default.bDealBurningDamage
|
||||
&& !ClassIsChildOf(KFDamType, class'DamTypeDualies')
|
||||
&& !ClassIsChildOf(KFDamType, class'DamTypeMK23Pistol')
|
||||
&& !ClassIsChildOf(KFDamType, class'DamTypeMagnum44Pistol') )
|
||||
{
|
||||
LastDamageAmount *= 3.5; //significantly raise decapitation bonus for Assault Rifles
|
||||
|
||||
//award shiver kill on decap for Commandos
|
||||
if ( KFPawn(LastDamagedBy)!=None && KFPlayerController(LastDamagedBy.Controller) != none
|
||||
&& KFSteamStatsAndAchievements(KFPlayerController(LastDamagedBy.Controller).SteamStatsAndAchievements) != none )
|
||||
{
|
||||
KFDamType.Static.AwardKill(
|
||||
KFSteamStatsAndAchievements(KFPlayerController(LastDamagedBy.Controller).SteamStatsAndAchievements),
|
||||
KFPlayerController(LastDamagedBy.Controller), self);
|
||||
}
|
||||
}
|
||||
if (IsInState('Running'))
|
||||
GotoState('');
|
||||
Super.RemoveHead();
|
||||
}
|
||||
|
||||
function bool FlipOver()
|
||||
{
|
||||
if ( super.FlipOver() ) {
|
||||
TeleportBlockTime = Level.TimeSeconds + 4.0; // can't teleport during stun
|
||||
// do not rotate while stunned
|
||||
Controller.Focus = none;
|
||||
Controller.FocalPoint = Location + 512*vector(Rotation);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamType)
|
||||
{
|
||||
if (Level.TimeSeconds - LastPainSound > MinTimeBetweenPainSounds)
|
||||
{
|
||||
LastPainSound = Level.TimeSeconds;
|
||||
PlaySound(HitSound[0], SLOT_Pain, 1.25,,400);
|
||||
}
|
||||
|
||||
if (!IsInState('Running') && Level.TimeSeconds - LastPainAnim > MinTimeBetweenPainAnims)
|
||||
{
|
||||
PlayDirectionalHit(HitLocation);
|
||||
LastPainAnim = Level.TimeSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function int DoAnimAction( name AnimName )
|
||||
{
|
||||
if (AnimName=='Claw' || AnimName=='Claw2' || AnimName=='Claw3')
|
||||
{
|
||||
AnimBlendParams(1, 1.0, 0.1,, FireRootBone);
|
||||
PlayAnim(AnimName,, 0.1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Super.DoAnimAction(AnimName);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
WalkAnim="ClotWalk"
|
||||
RunAnim="Run"
|
||||
MaxHeadTime=0.100000
|
||||
MaxTilt=10000.000000
|
||||
MaxTurn=20000.000000
|
||||
HeadOffsetY=-3.000000
|
||||
bDelayedReaction=True
|
||||
PeriodSeeTarget=2.000000
|
||||
PeriodRunBase=4.000000
|
||||
PeriodRunRan=4.000000
|
||||
PeriodRunCoolBase=4.000000
|
||||
PeriodRunCoolRan=3.000000
|
||||
AlphaFader=255.000000
|
||||
MinTeleportDist=550.000000
|
||||
MaxTeleportDist=2000.000000
|
||||
MinLandDist=150.000000
|
||||
MaxLandDist=500.000000
|
||||
MaxTeleportAttempts=3
|
||||
MaxTeleportAngles=3
|
||||
MoanVoice=SoundGroup'ScrnZedPack_S.Shiver.ShiverTalkGroup'
|
||||
bCannibal=True
|
||||
MeleeDamage=8
|
||||
damageForce=5000
|
||||
KFRagdollName="Clot_Trip"
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Jump'
|
||||
CrispUpThreshhold=9
|
||||
PuntAnim="ClotPunt"
|
||||
Intelligence=BRAINS_Mammal
|
||||
bUseExtendedCollision=True
|
||||
ColOffset=(Z=48.000000)
|
||||
ColRadius=25.000000
|
||||
ColHeight=5.000000
|
||||
ExtCollAttachBoneName="Collision_Attach"
|
||||
SeveredArmAttachScale=0.800000
|
||||
SeveredLegAttachScale=0.800000
|
||||
SeveredHeadAttachScale=0.800000
|
||||
DetachedArmClass=Class'ScrnZedPack.SeveredArmShiver'
|
||||
DetachedLegClass=Class'ScrnZedPack.SeveredLegShiver'
|
||||
DetachedHeadClass=Class'ScrnZedPack.SeveredHeadShiver'
|
||||
PlayerCountHealthScale=0.200000
|
||||
OnlineHeadshotOffset=(X=19.000000,Z=39.000000)
|
||||
OnlineHeadshotScale=1.400000
|
||||
MotionDetectorThreat=0.340000
|
||||
HitSound(0)=SoundGroup'ScrnZedPack_S.Shiver.ShiverPainGroup'
|
||||
DeathSound(0)=SoundGroup'ScrnZedPack_S.Shiver.ShiverDeathGroup'
|
||||
ChallengeSound(0)=SoundGroup'ScrnZedPack_S.Shiver.ShiverTalkGroup'
|
||||
ChallengeSound(1)=SoundGroup'ScrnZedPack_S.Shiver.ShiverTalkGroup'
|
||||
ChallengeSound(2)=SoundGroup'ScrnZedPack_S.Shiver.ShiverTalkGroup'
|
||||
ChallengeSound(3)=SoundGroup'ScrnZedPack_S.Shiver.ShiverTalkGroup'
|
||||
ScoringValue=15
|
||||
GroundSpeed=100.000000
|
||||
WaterSpeed=100.000000
|
||||
AccelRate=1024.000000
|
||||
JumpZ=340.000000
|
||||
HealthMax=300.000000
|
||||
Health=300
|
||||
HeadRadius=8.000000
|
||||
HeadHeight=3.000000
|
||||
HeadScale=1.300000
|
||||
MenuName="Shiver.se"
|
||||
MovementAnims(0)="ClotWalk"
|
||||
AmbientSound=SoundGroup'ScrnZedPack_S.Shiver.ShiverIdleGroup'
|
||||
Mesh=SkeletalMesh'ScrnZedPack_A.ShiverMesh'
|
||||
DrawScale=1.100000
|
||||
PrePivot=(Z=5.000000)
|
||||
Skins(0)=Combiner'ScrnZedPack_T.Shiver.CmbRemoveAlpha'
|
||||
RotationRate=(Yaw=45000,Roll=0)
|
||||
}
|
||||
17
kf_sources/ScrnZedPack/Classes/ZombieSiren_GRITTIER.uc
Normal file
17
kf_sources/ScrnZedPack/Classes/ZombieSiren_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class ZombieSiren_GRITTIER extends ZombieSiren;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.siren.Siren_Talk'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.siren.Siren_Jump'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegSiren'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadSiren'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.siren.Siren_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.siren.Siren_Death'
|
||||
MenuName="Grittier Siren"
|
||||
AmbientSound=Sound'KF_BaseSiren.Siren_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Siren_Freak'
|
||||
Skins(0)=FinalBlend'KF_Specimens_Trip_T.siren_hair_fb'
|
||||
Skins(1)=Combiner'ScrnZedPack_T.siren_grittier.siren_grittier_cmb'
|
||||
}
|
||||
176
kf_sources/ScrnZedPack/Classes/ZombieStalker_GRITTIER.uc
Normal file
176
kf_sources/ScrnZedPack/Classes/ZombieStalker_GRITTIER.uc
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
class ZombieStalker_GRITTIER extends ZombieStalker;
|
||||
#exec OBJ LOAD FILE=ScrnZedPack_T.utx
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
Super.Tick(DeltaTime);
|
||||
if( Level.NetMode==NM_DedicatedServer )
|
||||
Return; // Servers aren't intrested in this info.
|
||||
|
||||
if( Level.TimeSeconds > NextCheckTime && Health > 0 )
|
||||
{
|
||||
NextCheckTime = Level.TimeSeconds + 0.5;
|
||||
|
||||
if( LocalKFHumanPawn != none && LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers() &&
|
||||
VSizeSquared(Location - LocalKFHumanPawn.Location) < LocalKFHumanPawn.GetStalkerViewDistanceMulti() * 640000.0 ) // 640000 = 800 Units
|
||||
{
|
||||
bSpotted = True;
|
||||
}
|
||||
else
|
||||
{
|
||||
bSpotted = false;
|
||||
}
|
||||
|
||||
if ( !bSpotted && !bCloaked && Skins[0] != Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb' )
|
||||
{
|
||||
UncloakStalker();
|
||||
}
|
||||
else if ( Level.TimeSeconds - LastUncloakTime > 1.2 )
|
||||
{
|
||||
// if we're uberbrite, turn down the light
|
||||
if( bSpotted && Skins[0] != Finalblend'KFX.StalkerGlow' )
|
||||
{
|
||||
bUnlit = false;
|
||||
CloakStalker();
|
||||
}
|
||||
else if ( Skins[0] != Shader'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible' )
|
||||
{
|
||||
CloakStalker();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simulated function CloakStalker()
|
||||
{
|
||||
if ( bSpotted )
|
||||
{
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
return;
|
||||
|
||||
Skins[0] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[1] = Finalblend'KFX.StalkerGlow';
|
||||
Skins[2] = Finalblend'KFX.StalkerGlow';
|
||||
bUnlit = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !bDecapitated && !bCrispified ) // No head, no cloak, honey. updated : Being charred means no cloak either :D
|
||||
{
|
||||
Visibility = 1;
|
||||
bCloaked = true;
|
||||
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
Return;
|
||||
|
||||
Skins[0] = Shader'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible';
|
||||
Skins[1] = Shader'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible';
|
||||
|
||||
// Invisible - no shadow
|
||||
if(PlayerShadow != none)
|
||||
PlayerShadow.bShadowActive = false;
|
||||
if(RealTimeShadow != none)
|
||||
RealTimeShadow.Destroy();
|
||||
|
||||
// Remove/disallow projectors on invisible people
|
||||
Projectors.Remove(0, Projectors.Length);
|
||||
bAcceptsProjectors = false;
|
||||
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simulated function UnCloakStalker()
|
||||
{
|
||||
if( !bCrispified )
|
||||
{
|
||||
LastUncloakTime = Level.TimeSeconds;
|
||||
|
||||
Visibility = default.Visibility;
|
||||
bCloaked = false;
|
||||
|
||||
// 25% chance of our Enemy saying something about us being invisible
|
||||
if( Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller.Enemy!=none &&
|
||||
PlayerController(Controller.Enemy.Controller)!=none )
|
||||
{
|
||||
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 17, "");
|
||||
KFGameType(Level.Game).bDidStalkerInvisibleMessage = true;
|
||||
}
|
||||
if( Level.NetMode == NM_DedicatedServer )
|
||||
Return;
|
||||
|
||||
if ( Skins[0] != Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb' )
|
||||
{
|
||||
Skins[1] = FinalBlend'ScrnZedPack_T.stalker_grittier.stalker_grittier_fb';
|
||||
Skins[0] = Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb';
|
||||
|
||||
if (PlayerShadow != none)
|
||||
PlayerShadow.bShadowActive = true;
|
||||
|
||||
bAcceptsProjectors = true;
|
||||
|
||||
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveHead()
|
||||
{
|
||||
Super.RemoveHead();
|
||||
|
||||
if (!bCrispified)
|
||||
{
|
||||
Skins[1] = FinalBlend'ScrnZedPack_T.stalker_grittier.stalker_grittier_fb';
|
||||
Skins[0] = Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb';
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
|
||||
{
|
||||
Super.PlayDying(DamageType,HitLoc);
|
||||
|
||||
if(bUnlit)
|
||||
bUnlit=!bUnlit;
|
||||
|
||||
LocalKFHumanPawn = none;
|
||||
|
||||
if (!bCrispified)
|
||||
{
|
||||
Skins[1] = FinalBlend'ScrnZedPack_T.stalker_grittier.stalker_grittier_fb';
|
||||
Skins[0] = Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb';
|
||||
}
|
||||
}
|
||||
|
||||
static simulated function PreCacheMaterials(LevelInfo myLevel)
|
||||
{//should be derived and used.
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_cmb');
|
||||
myLevel.AddPrecacheMaterial(Combiner'ScrnZedPack_T.stalker_grittier.stalker_grittier_env_cmb');
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.stalker_grittier.stalker_grittier_diff');
|
||||
myLevel.AddPrecacheMaterial(Texture'ScrnZedPack_T.stalker_grittier.stalker_grittier_spec');
|
||||
myLevel.AddPrecacheMaterial(Material'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible');
|
||||
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.StalkerCloakOpacity_cmb');
|
||||
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.StalkerCloakEnv_rot');
|
||||
myLevel.AddPrecacheMaterial(Material'ScrnZedPack_T.stalker_grittier.stalker_grittier_opacity_osc');
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Talk'
|
||||
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_HitPlayer'
|
||||
JumpSound=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Jump'
|
||||
DetachedArmClass=Class'KFChar.SeveredArmStalker'
|
||||
DetachedLegClass=Class'KFChar.SeveredLegStalker'
|
||||
DetachedHeadClass=Class'KFChar.SeveredHeadStalker'
|
||||
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Pain'
|
||||
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Death'
|
||||
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.Stalker.Stalker_Challenge'
|
||||
MenuName="Grittier Stalker"
|
||||
AmbientSound=Sound'KF_BaseStalker.Stalker_IdleLoop'
|
||||
Mesh=SkeletalMesh'KF_Freaks_Trip.Stalker_Freak'
|
||||
Skins(0)=Shader'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible'
|
||||
Skins(1)=Shader'ScrnZedPack_T.stalker_grittier.stalker_grittier_invisible'
|
||||
}
|
||||
55
kf_sources/ScrnZedPack/Classes/index.html
Normal file
55
kf_sources/ScrnZedPack/Classes/index.html
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<html>
|
||||
<head><title>Index of /kf_sources/ScrnZedPack/Classes/</title></head>
|
||||
<body>
|
||||
<h1>Index of /kf_sources/ScrnZedPack/Classes/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="BlockHitEmitter.uc">BlockHitEmitter.uc</a> 01-Jul-2020 18:13 193
|
||||
<a href="BrainDeadFemaleFP.uc">BrainDeadFemaleFP.uc</a> 01-Jul-2020 18:13 200
|
||||
<a href="BruteAvoidArea.uc">BruteAvoidArea.uc</a> 01-Jul-2020 18:13 1195
|
||||
<a href="BruteZombieController.uc">BruteZombieController.uc</a> 01-Jul-2020 18:13 1785
|
||||
<a href="DamTypeEMP.uc">DamTypeEMP.uc</a> 01-Jul-2020 18:13 137
|
||||
<a href="DamTypeTesla.uc">DamTypeTesla.uc</a> 01-Jul-2020 18:13 263
|
||||
<a href="FFPController.uc">FFPController.uc</a> 01-Jul-2020 18:13 3128
|
||||
<a href="FFPKarma.uc">FFPKarma.uc</a> 01-Jul-2020 18:13 1877
|
||||
<a href="FFPVentEmitter.uc">FFPVentEmitter.uc</a> 01-Jul-2020 18:13 3960
|
||||
<a href="FemaleFP.uc">FemaleFP.uc</a> 01-Jul-2020 18:13 27072
|
||||
<a href="FemaleFP_MKII.uc">FemaleFP_MKII.uc</a> 01-Jul-2020 18:13 5180
|
||||
<a href="HardPat.uc">HardPat.uc</a> 01-Jul-2020 18:13 15970
|
||||
<a href="HardPatController.uc">HardPatController.uc</a> 01-Jul-2020 18:13 3350
|
||||
<a href="HardPat_CIRCUS.uc">HardPat_CIRCUS.uc</a> 01-Jul-2020 18:13 5047
|
||||
<a href="HardPat_GRITTIER.uc">HardPat_GRITTIER.uc</a> 01-Jul-2020 18:13 223
|
||||
<a href="HardPat_HALLOWEEN.uc">HardPat_HALLOWEEN.uc</a> 01-Jul-2020 18:13 4471
|
||||
<a href="HardPat_XMAS.uc">HardPat_XMAS.uc</a> 01-Jul-2020 18:13 5116
|
||||
<a href="HuskFireProjectileSE.uc">HuskFireProjectileSE.uc</a> 01-Jul-2020 18:13 2497
|
||||
<a href="HuskZombieControllerSE.uc">HuskZombieControllerSE.uc</a> 01-Jul-2020 18:13 8456
|
||||
<a href="JasonZombieController.uc">JasonZombieController.uc</a> 01-Jul-2020 18:13 1504
|
||||
<a href="SeveredArmBrute.uc">SeveredArmBrute.uc</a> 01-Jul-2020 18:13 136
|
||||
<a href="SeveredArmFFP.uc">SeveredArmFFP.uc</a> 01-Jul-2020 18:13 138
|
||||
<a href="SeveredArmShiver.uc">SeveredArmShiver.uc</a> 01-Jul-2020 18:13 133
|
||||
<a href="SeveredArmTeslaHusk.uc">SeveredArmTeslaHusk.uc</a> 01-Jul-2020 18:13 147
|
||||
<a href="SeveredGunTeslaHusk.uc">SeveredGunTeslaHusk.uc</a> 01-Jul-2020 18:13 147
|
||||
<a href="SeveredHeadBrute.uc">SeveredHeadBrute.uc</a> 01-Jul-2020 18:13 632
|
||||
<a href="SeveredHeadShiver.uc">SeveredHeadShiver.uc</a> 01-Jul-2020 18:13 136
|
||||
<a href="SeveredHeadTeslaHusk.uc">SeveredHeadTeslaHusk.uc</a> 01-Jul-2020 18:13 150
|
||||
<a href="SeveredLegBrute.uc">SeveredLegBrute.uc</a> 01-Jul-2020 18:13 135
|
||||
<a href="SeveredLegFFP.uc">SeveredLegFFP.uc</a> 01-Jul-2020 18:13 138
|
||||
<a href="SeveredLegShiver.uc">SeveredLegShiver.uc</a> 01-Jul-2020 18:13 133
|
||||
<a href="SeveredLegTeslaHusk.uc">SeveredLegTeslaHusk.uc</a> 01-Jul-2020 18:13 147
|
||||
<a href="TeslaBeam.uc">TeslaBeam.uc</a> 01-Jul-2020 18:13 5855
|
||||
<a href="TeslaHusk.uc">TeslaHusk.uc</a> 01-Jul-2020 18:13 28383
|
||||
<a href="TeslaHuskEMPCharge.uc">TeslaHuskEMPCharge.uc</a> 01-Jul-2020 18:13 4911
|
||||
<a href="ZombieBloat_GRITTIER.uc">ZombieBloat_GRITTIER.uc</a> 01-Jul-2020 18:13 3863
|
||||
<a href="ZombieBoss_GRITTIER.uc">ZombieBoss_GRITTIER.uc</a> 01-Jul-2020 18:13 1320
|
||||
<a href="ZombieBrute.uc">ZombieBrute.uc</a> 01-Jul-2020 18:13 21116
|
||||
<a href="ZombieClot_GRITTIER.uc">ZombieClot_GRITTIER.uc</a> 01-Jul-2020 18:13 1109
|
||||
<a href="ZombieCrawler_GRITTIER.uc">ZombieCrawler_GRITTIER.uc</a> 01-Jul-2020 18:13 1887
|
||||
<a href="ZombieFleshpound_GRITTIER.uc">ZombieFleshpound_GRITTIER.uc</a> 01-Jul-2020 18:13 1187
|
||||
<a href="ZombieGhost.uc">ZombieGhost.uc</a> 01-Jul-2020 18:13 8892
|
||||
<a href="ZombieGorefast_GRITTIER.uc">ZombieGorefast_GRITTIER.uc</a> 01-Jul-2020 18:13 3160
|
||||
<a href="ZombieHusk_GRITTIER.uc">ZombieHusk_GRITTIER.uc</a> 01-Jul-2020 18:13 5990
|
||||
<a href="ZombieJason.uc">ZombieJason.uc</a> 01-Jul-2020 18:13 5997
|
||||
<a href="ZombieScrake_GRITTIER.uc">ZombieScrake_GRITTIER.uc</a> 01-Jul-2020 18:13 1460
|
||||
<a href="ZombieShiver.uc">ZombieShiver.uc</a> 01-Jul-2020 18:13 16674
|
||||
<a href="ZombieSiren_GRITTIER.uc">ZombieSiren_GRITTIER.uc</a> 01-Jul-2020 18:13 758
|
||||
<a href="ZombieStalker_GRITTIER.uc">ZombieStalker_GRITTIER.uc</a> 01-Jul-2020 18:13 6580
|
||||
</pre><hr></body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue