rott/kf_sources/KFOldSchoolZeds/Classes/ZombieRangedPoundOS.uc
2026-07-14 20:27:09 +07:00

633 lines
19 KiB
Ucode

class ZombieRangedPoundOS extends KFMonsterOS;
var bool bFireAtWill,bMinigunning;
var float LastChainGunTime;
var vector TraceHitPos;
var Emitter mTracer,mMuzzleFlash;
var int MGFireCounter;
var bool bClientMiniGunning;
var float MGLostSightTimeout;
var() float MGDamage;
var() float MGAccuracy;
var() float MGFireRate;
var() int MGFireBurst;
var() float BurnDamageScale;
var() float MGFireInterval;
var bool bDisableIncendiaryRounds;
var bool bDisableIncendiaryResistance;
var () class <DamageType> MGDamageType;
replication
{
reliable if( Role==ROLE_Authority )
TraceHitPos,bMinigunning;
}
function vector ComputeTrajectoryByTime( vector StartPosition, vector EndPosition, float fTimeEnd )
{
local vector NewVelocity;
NewVelocity = super.ComputeTrajectoryByTime( StartPosition, EndPosition, fTimeEnd );
if( PhysicsVolume.IsA( 'KFPhysicsVolume' ) && StartPosition.Z < EndPosition.Z )
{
if( PhysicsVolume.Gravity.Z < class'PhysicsVolume'.default.Gravity.Z )
{
if( Mass > 900 )
{
NewVelocity.Z += 90;
}
}
}
return NewVelocity;
}
function bool CanGetOutOfWay()
{
return false;
}
function bool FlipOver()
{
if( Physics==PHYS_Falling )
{
SetPhysics(PHYS_Walking);
}
bShotAnim = true;
GoToState('');
SetAnimAction('RangedKnockDown');
HandleWaitForAnim('RangedKnockDown');
Acceleration = vect(0, 0, 0);
Velocity.X = 0;
Velocity.Y = 0;
KFMonsterController(Controller).Focus = none;
KFMonsterController(Controller).FocalPoint = KFMonsterController(Controller).LastSeenPos;
Controller.GoToState('WaitForAnim');
KFMonsterController(Controller).bUseFreezeHack = true;
return true;
}
simulated function PostBeginPlay()
{
if( Role < ROLE_Authority )
{
return;
}
if (Level.Game != none)
{
if( Level.Game.GameDifficulty < 2.0 )
{
BurnDamageScale = default.BurnDamageScale * 2.0;
MGFireInterval = default.MGFireInterval * 1.25;
MGDamage = default.MGDamage * 0.5;
MGAccuracy = default.MGAccuracy * 1.25;
MGFireBurst = default.MGFireBurst * 0.7;
MGFireRate = default.MGFireRate * 1.5;
}
else if( Level.Game.GameDifficulty < 4.0 )
{
BurnDamageScale = default.BurnDamageScale * 1.0;
MGFireInterval = default.MGFireInterval * 1;
MGDamage = default.MGDamage * 1.0;
MGAccuracy = default.MGAccuracy * 1.0;
MGFireBurst = default.MGFireBurst * 1.0;
MGFireRate = default.MGFireRate * 1.0;
}
else if( Level.Game.GameDifficulty < 5.0 )
{
BurnDamageScale = default.BurnDamageScale * 0.75;
MGFireInterval = default.MGFireInterval * 0.75;
MGDamage = default.MGDamage * 1.0;
MGAccuracy = default.MGAccuracy * 0.9;
MGFireBurst = default.MGFireBurst * 1.33;
MGFireRate = default.MGFireRate * 0.833333;
}
else
{
BurnDamageScale = default.BurnDamageScale * 0.5;
MGFireInterval = default.MGFireInterval * 0.6;
MGDamage = default.MGDamage * 1.0;
MGAccuracy = default.MGAccuracy * 0.80;
MGFireBurst = default.MGFireBurst * 1.67;
MGFireRate = default.MGFireRate * 0.68;
}
}
if(bDisableIncendiaryRounds)
MGDamageType=class'ZombieMeleeDamage';
super.PostBeginPlay();
}
simulated function bool HitCanInterruptAction()
{
if( bShotAnim )
{
return false;
}
return true;
}
simulated function Destroyed()
{
if( mTracer!=none )
mTracer.Destroy();
if( mMuzzleFlash!=none )
mMuzzleFlash.Destroy();
super.Destroyed();
}
simulated Function PostNetBeginPlay()
{
EnableChannelNotify ( 1,1);
AnimBlendParams(1, 1.0, 0.0,, 'Bip01 Spine1');
super.PostNetBeginPlay();
TraceHitPos = vect(0,0,0);
bNetNotify = true;
}
function RangedAttack(Actor A)
{
local float Dist;
local int LastFireTime;
if ( bShotAnim )
return;
Dist = VSize(A.Location-Location);
if ( Physics == PHYS_Swimming )
{
SetAnimAction('Claw');
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
}
else if ( Dist < MeleeRange + CollisionRadius + A.CollisionRadius )
{
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
SetAnimAction('Claw');
PlaySound(sound'Claw2s', SLOT_Interact);
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
}
else if ( !bWaitForAnim && !bShotAnim && !bDecapitated && LastChainGunTime<Level.TimeSeconds )
{
if (!Controller.LineOfSightTo(A))
{
//Maybe lower this further?
LastChainGunTime = Level.TimeSeconds + MGFireInterval + (FRand() *1.0);
return;
}
LastChainGunTime = Level.TimeSeconds + MGFireInterval + (FRand() *2.0);
bShotAnim = true;
Acceleration = vect(0,0,0);
SetAnimAction('RangedPreFireMG');
HandleWaitForAnim('RangedPreFireMG');
MGFireCounter = MGFireBurst;
GoToState('FireChaingun');
}
}
simulated function AddTraceHitFX( vector HitPos )
{
local vector Start,SpawnVel,SpawnDir;
local float hitDist;
PlaySound(sound'KFOldSchoolZeds_Sounds.MinigunFire',SLOT_Misc,2,,1400,0.9+FRand()*0.2);
Start = GetBoneCoords('FireBone').Origin;
if( mTracer==none )
mTracer = Spawn(class'KFMod.KFNewTracer',,,Start);
else mTracer.SetLocation(Start);
if( mMuzzleFlash==none )
{
mMuzzleFlash = Spawn(class'NewMinigunMFlashOS');
AttachToBone(mMuzzleFlash, 'FireBone');
}
else mMuzzleFlash.SpawnParticle(1);
hitDist = VSize(HitPos - Start) - 50.f;
if( hitDist>10 )
{
SpawnDir = Normal(HitPos - Start);
SpawnVel = SpawnDir * 10000.f;
mTracer.Emitters[0].StartVelocityRange.X.Min = SpawnVel.X;
mTracer.Emitters[0].StartVelocityRange.X.Max = SpawnVel.X;
mTracer.Emitters[0].StartVelocityRange.Y.Min = SpawnVel.Y;
mTracer.Emitters[0].StartVelocityRange.Y.Max = SpawnVel.Y;
mTracer.Emitters[0].StartVelocityRange.Z.Min = SpawnVel.Z;
mTracer.Emitters[0].StartVelocityRange.Z.Max = SpawnVel.Z;
mTracer.Emitters[0].LifetimeRange.Min = hitDist / 10000.f;
mTracer.Emitters[0].LifetimeRange.Max = mTracer.Emitters[0].LifetimeRange.Min;
mTracer.SpawnParticle(1);
}
Instigator = self;
if( HitPos != vect(0,0,0) )
{
Spawn(class'ROBulletHitEffect',,, HitPos, Rotator(Normal(HitPos - Start)));
}
}
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 != 'RangedPreFireMG' && Sequence != 'RangedFireMG' )
{
super.AnimEnd(Channel);
return;
}
PlayAnim('RangedFireMG');
bWaitForAnim = true;
bShotAnim = true;
IdleTime = Level.TimeSeconds;
}
else super.AnimEnd(Channel);
}
state FireChaingun
{
function RangedAttack(Actor A)
{
Controller.Target = A;
Controller.Focus = A;
}
function EndState()
{
TraceHitPos = vect(0,0,0);
bMinigunning = false;
AmbientSound = default.AmbientSound;
SoundVolume=default.SoundVolume;
SoundRadius=default.SoundRadius;
MGFireCounter=0;
LastChainGunTime = Level.TimeSeconds + MGFireInterval + (FRand() *2.0);
}
function BeginState()
{
bFireAtWill = false;
Acceleration = vect(0,0,0);
MGLostSightTimeout = 0.0;
bMinigunning = true;
}
function AnimEnd( int Channel )
{
if( MGFireCounter <= 0 )
{
bShotAnim = true;
Acceleration = vect(0,0,0);
SetAnimAction('RangedFireMGEnd');
HandleWaitForAnim('RangedFireMGEnd');
GoToState('');
}
else
{
if ( Controller.Enemy != none )
{
if ( Controller.LineOfSightTo(Controller.Enemy) && FastTrace(GetBoneCoords('FireBone').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 ( FRand() < 0.03 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none )
{
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 9, "");
}
bFireAtWill = true;
bShotAnim = true;
Acceleration = vect(0,0,0);
SetAnimAction('RangedFireMG');
bWaitForAnim = true;
}
}
function FireMGShot()
{
local vector Start,End,HL,HN,Dir;
local rotator R;
local Actor A;
local KFPawn KFP;
local float Dist;
KFP = KFPawn(Controller.Target);
Dist = VSize(Controller.Target.Location-Location);
MGFireCounter--;
Start = GetBoneCoords('FireBone').Origin;
if( Controller.Focus!=none )
R = rotator(Controller.Focus.Location-Start);
else R = rotator(Controller.FocalPoint-Start);
if( NeedToTurnFor(R) )
R = Rotation;
Dir = Normal(vector(R)+VRand()*MGAccuracy);
End = Start+Dir*10000;
bBlockHitPointTraces = false;
A = Trace(HL,HN,End,Start,true);
bBlockHitPointTraces = true;
if( A==none )
return;
TraceHitPos = HL;
if( Level.NetMode!=NM_DedicatedServer )
AddTraceHitFX(HL);
if( A!=Level && ( A == KFPawn(A) || A == KFGlassMover(A) || A == KFDoorMover(A)) )
{
// This spams server logs with "Accessed None PlayerReplicationInfo"
if(KFPlayerReplicationInfo(KFP.PlayerReplicationInfo).ClientVeteranSkill != class'KFVetBerserker')
A.TakeDamage(MGDamage,self,HL,Dir*500,MGDamageType);
else
A.TakeDamage((MGDamage + 1),self,HL,Dir*500,MGDamageType);
}
else return;
}
function bool NeedToTurnFor( rotator targ )
{
local int YawErr;
targ.Yaw = DesiredRotation.Yaw & 65535;
YawErr = (targ.Yaw - (Rotation.Yaw & 65535)) & 65535;
return !((YawErr < 2000) || (YawErr > 64535));
}
Begin:
While( true )
{
Acceleration = vect(0,0,0);
if( MGLostSightTimeout > 0 && Level.TimeSeconds > MGLostSightTimeout )
{
bShotAnim = true;
Acceleration = vect(0,0,0);
SetAnimAction('RangedFireMGEnd');
HandleWaitForAnim('RangedFireMGEnd');
GoToState('');
}
if( MGFireCounter <= 0 )
{
bShotAnim = true;
Acceleration = vect(0,0,0);
SetAnimAction('RangedFireMGEnd');
HandleWaitForAnim('RangedFireMGEnd');
GoToState('');
}
if( bFireAtWill )
FireMGShot();
Sleep(MGFireRate);
}
}
simulated function PostNetReceive()
{
if( bClientMiniGunning != bMinigunning )
{
bClientMiniGunning = bMinigunning;
if( bMinigunning )
{
IdleHeavyAnim='RangedFireMG';
IdleRifleAnim='RangedFireMG';
IdleCrouchAnim='RangedFireMG';
IdleWeaponAnim='RangedFireMG';
IdleRestAnim='RangedFireMG';
}
else
{
IdleHeavyAnim='RangedIdle';
IdleRifleAnim='RangedIdle';
IdleCrouchAnim='RangedIdle';
IdleWeaponAnim='RangedIdle';
IdleRestAnim='RangedIdle';
}
}
if( TraceHitPos!=vect(0,0,0) )
{
AddTraceHitFX(TraceHitPos);
TraceHitPos = vect(0,0,0);
}
}
simulated function int DoAnimAction( name AnimName )
{
if(AnimName=='PoundPunch2' || AnimName=='RangedHitF')
{
AnimBlendParams(1, 1.0, 0.0,, 'Bip01 Spine1');
PlayAnim(AnimName,, 0.0, 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];
}
ExpectingChannel = DoAnimAction(NewAction);
if( Controller != none )
{
ControllerRangedPoundOS(Controller).AnimWaitChannel = ExpectingChannel;
}
if( AnimNeedsWait(NewAction) )
{
bWaitForAnim = true;
}
else
{
bWaitForAnim = false;
}
if( Level.NetMode!=NM_Client )
{
AnimAction = NewAction;
bResetAnimAct = true;
ResetAnimActTime = Level.TimeSeconds+0.3;
}
}
simulated function HandleWaitForAnim( name NewAnim )
{
local float RageAnimDur;
Controller.GoToState('WaitForAnim');
RageAnimDur = GetAnimDuration(NewAnim);
ControllerRangedPoundOS(Controller).SetWaitForAnimTimout(RageAnimDur,NewAnim);
}
simulated function bool AnimNeedsWait(name TestAnim)
{
if( TestAnim == 'RangedFireMG' || TestAnim == 'RangedPreFireMG' || TestAnim == 'RangedFireMGEnd' || TestAnim == 'RangedKnockDown')
{
return true;
}
return false;
}
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
{
if ((DamageType == class 'DamTypeBurned' || DamageType == class 'DamTypeFlamethrower') && !bDisableIncendiaryResistance)
{
Damage *= BurnDamageScale;
}
super.TakeDamage(Damage,instigatedBy,hitlocation,momentum,damageType,HitIndex);
}
function OldPlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum, optional int HitIndex)
{
if(LastChainGunTime<Level.TimeSeconds + 1)
return;
else
super.OldPlayHit(Damage,InstigatedBy,HitLocation,damageType,Momentum,HitIndex);
}
static simulated function PreCacheMaterials(LevelInfo myLevel)
{
myLevel.AddPrecacheMaterial(Shader'KFOldSchoolZeds_Textures.Fleshpound.PoundBitsShader');
myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.GunPound.AutoTurretGunTex');
myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.GunPound.GunPoundSkin');
}
defaultproperties
{
MGDamage=2.000000
MGAccuracy=0.040000
MGFireRate=0.060000
MGFireBurst=15
BurnDamageScale=0.250000
MGFireInterval=5.500000
MGDamageType=Class'KFMod.DamTypeBurned'
MeleeAnims(0)="PoundPunch2"
MeleeAnims(1)="PoundPunch2"
MeleeAnims(2)="PoundPunch2"
MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.Fleshpound.Fleshpound_Speech'
BleedOutDuration=6.000000
ZapThreshold=0.750000
bHarpoonToBodyStuns=False
ZombieFlag=1
MeleeDamage=15
damageForce=70000
bFatAss=True
KFRagdollName="FleshPoundRag"
JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieJump'
Intelligence=BRAINS_Mammal
bUseExtendedCollision=True
ColOffset=(Z=65.000000)
ColRadius=27.000000
ColHeight=25.000000
PlayerCountHealthScale=0.100000
BurningWalkFAnims(0)="RangedWalkF"
BurningWalkFAnims(1)="RangedWalkF"
BurningWalkFAnims(2)="RangedWalkF"
BurningWalkAnims(0)="RangedWalkF"
BurningWalkAnims(1)="RangedWalkF"
BurningWalkAnims(2)="RangedWalkF"
OnlineHeadshotOffset=(X=5.000000,Y=7.000000,Z=71.000000)
OnlineHeadshotScale=1.200000
HeadHealth=200.000000
PlayerNumHeadHealthScale=0.050000
HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombiePain'
DeathSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombieDeath'
ScoringValue=17
IdleHeavyAnim="RangedIdle"
IdleRifleAnim="RangedIdle"
MeleeRange=30.000000
GroundSpeed=115.000000
WaterSpeed=102.000000
HealthMax=600.000000
Health=600
HeadRadius=8.750000
HeadHeight=11.000000
MenuName="Flesh Pound Chaingunner"
ControllerClass=Class'KFOldSchoolZeds.ControllerRangedPoundOS'
MovementAnims(0)="RangedWalkF"
MovementAnims(1)="RangedWalkF"
MovementAnims(2)="RangedWalkF"
MovementAnims(3)="RangedWalkF"
TurnLeftAnim="RangedBossHitF"
TurnRightAnim="RangedBossHitF"
WalkAnims(0)="RangedWalkF"
WalkAnims(1)="RangedWalkF"
WalkAnims(2)="RangedWalkF"
WalkAnims(3)="RangedWalkF"
AirAnims(0)="RangedJumpInAir"
AirAnims(1)="RangedJumpInAir"
AirAnims(2)="RangedJumpInAir"
AirAnims(3)="RangedJumpInAir"
TakeoffAnims(0)="RangedJumpTakeOff"
TakeoffAnims(1)="RangedJumpTakeOff"
TakeoffAnims(2)="RangedJumpTakeOff"
TakeoffAnims(3)="RangedJumpTakeOff"
LandAnims(0)="RangedJumpLanded"
LandAnims(1)="RangedJumpLanded"
LandAnims(2)="RangedJumpLanded"
LandAnims(3)="RangedJumpLanded"
AirStillAnim="RangedJumpInAir"
TakeoffStillAnim="RangedJumpTakeOff"
IdleCrouchAnim="RangedIdle"
IdleWeaponAnim="RangedIdle"
IdleRestAnim="RangedIdle"
Mesh=SkeletalMesh'KFCharacterModelsOldSchool.RangedPound'
PrePivot=(Z=0.000000)
Skins(0)=Shader'KFOldSchoolZeds_Textures.Fleshpound.PoundBitsShader'
Skins(1)=Texture'KFOldSchoolZeds_Textures.Gunpound.AutoTurretGunTex'
Skins(2)=Texture'KFOldSchoolZeds_Textures.Gunpound.GunPoundSkin'
Mass=400.000000
RotationRate=(Yaw=45000,Roll=0)
}