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

360 lines
12 KiB
Ucode

class ScrnChainsaw extends Chainsaw;
var float IdleFuelConsumeTime; // time between fuel consumption on idle
var sound EngineStartSound, EngineStopSound;
var string EngineStartSoundRef, EngineStopSoundRef;
struct SoundList {
var string SoundRef;
var sound Sound;
var float Duration;
};
var array<SoundList> ReloadSounds;
var float TotalReloadSoundDuration; // total duration of all reload sounds
var transient float TimeToNextReloadSound;
var transient int NextReloadSoundIndex;
var transient bool bBlownUpThisReload;
var transient int OldMagAmmoRemaining;
var ScrnFakedProjectile FakedGasCan; //adds a faked gas can during reload
replication
{
reliable if(Role == ROLE_Authority)
HideGasCan;
}
simulated function PostNetReceive()
{
super.PostNetReceive();
if ( Role < ROLE_Authority ) {
if ( OldMagAmmoRemaining != MagAmmoRemaining ) {
if ( MagAmmoRemaining == 0 ) {
if ( ThirdPersonActor != none )
ThirdPersonActor.AmbientSound = none;
TexPanner(Skins[1]).PanRate = 0; // stop saw cycling
PlaySound(EngineStopSound);
}
else if ( OldMagAmmoRemaining < MagAmmoRemaining && MagAmmoRemaining > 0 ) {
//just reloaded
if ( IsInState('Reloading') )
GotoState('');
if ( ThirdPersonActor != none )
ThirdPersonActor.AmbientSound = ThirdPersonActor.default.AmbientSound;
TexPanner(Skins[1]).PanRate = 3; // start saw cycling
PlaySound(EngineStartSound);
if ( !IsAnimating() )
PlayIdle();
}
OldMagAmmoRemaining = MagAmmoRemaining;
}
}
}
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount)
{
local int i;
local ScrnChainsaw W;
super.PreloadAssets(Inv, bSkipRefCount);
W = ScrnChainsaw(Inv);
default.EngineStartSound = sound(DynamicLoadObject(default.EngineStartSoundRef, class'sound'));
default.EngineStopSound = sound(DynamicLoadObject(default.EngineStopSoundRef, class'sound'));
for ( i = 0; i < default.ReloadSounds.Length; ++i ) {
default.ReloadSounds[i].Sound = sound(DynamicLoadObject(default.ReloadSounds[i].SoundRef, class'sound'));
if ( W != none ) {
W.ReloadSounds[i].Sound = default.ReloadSounds[i].Sound;
}
}
if ( W != none ) {
W.EngineStartSound = default.EngineStartSound;
W.EngineStopSound = default.EngineStopSound;
W.CalcReloadSoundDuration();
default.TotalReloadSoundDuration = W.TotalReloadSoundDuration;
}
}
static function bool UnloadAssets()
{
local int i;
default.EngineStartSound = none;
default.EngineStopSound = none;
default.TotalReloadSoundDuration = 0;
for ( i = 0; i < default.ReloadSounds.Length; ++i ) {
default.ReloadSounds[i].Sound = none;
}
return super.UnloadAssets();
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
AttachGasCan();
CalcReloadSoundDuration();
}
simulated function AttachGasCan() {
if ( Level.NetMode != NM_DedicatedServer )
{
if ( FakedGasCan == none ) //only spawn FakedGasCan once
FakedGasCan = spawn(class'ScrnFakedGasCan',self);
if ( FakedGasCan != none )
{
AttachToBone(FakedGasCan, 'Chainsaw'); //attach faked shell to chainsaw
FakedGasCan.SetDrawScale(0.01);
FakedGasCan.SetRelativeLocation(vect(-3, 2, 3)); //x y z
FakedGasCan.SetRelativeRotation(rot(-4000, 38000, 12000)); //pitch yaw roll
}
}
}
simulated function CalcReloadSoundDuration()
{
local int i;
TotalReloadSoundDuration = 0;
for ( i = 0; i < default.ReloadSounds.Length; ++i ) {
ReloadSounds[i].Duration = GetSoundDuration(ReloadSounds[i].Sound);
TotalReloadSoundDuration += ReloadSounds[i].Duration;
}
}
simulated function bool ConsumeAmmo( int Mode, float Load, optional bool bAmountNeededIsMax )
{
local Inventory Inv;
local bool bOutOfAmmo;
local KFWeapon KFWeap;
if ( Super(Weapon).ConsumeAmmo(Mode, Load, bAmountNeededIsMax) )
{
if ( Load > 0 && (Mode == 0 || bReduceMagAmmoOnSecondaryFire) ) {
MagAmmoRemaining -= Load; // Changed from "MagAmmoRemaining--" -- PooSH
if ( MagAmmoRemaining < 0 )
MagAmmoRemaining = 0;
if ( MagAmmoRemaining == 0 ) {
ThirdPersonActor.AmbientSound = none;
TexPanner(Skins[1]).PanRate = 0; // stop saw cycling
PlaySound(EngineStopSound);
}
}
OldMagAmmoRemaining = MagAmmoRemaining;
NetUpdateTime = Level.TimeSeconds - 1;
if ( FireMode[Mode].AmmoPerFire > 0 && InventoryGroup > 0 && !bMeleeWeapon && bConsumesPhysicalAmmo &&
(Ammo[0] == none || FireMode[0] == none || FireMode[0].AmmoPerFire <= 0 || Ammo[0].AmmoAmount < FireMode[0].AmmoPerFire) &&
(Ammo[1] == none || FireMode[1] == none || FireMode[1].AmmoPerFire <= 0 || Ammo[1].AmmoAmount < FireMode[1].AmmoPerFire) )
{
bOutOfAmmo = true;
for ( Inv = Instigator.Inventory; Inv != none; Inv = Inv.Inventory )
{
KFWeap = KFWeapon(Inv);
if ( Inv.InventoryGroup > 0 && KFWeap != none && !KFWeap.bMeleeWeapon && KFWeap.bConsumesPhysicalAmmo &&
((KFWeap.Ammo[0] != none && KFWeap.FireMode[0] != none && KFWeap.FireMode[0].AmmoPerFire > 0 &&KFWeap.Ammo[0].AmmoAmount >= KFWeap.FireMode[0].AmmoPerFire) ||
(KFWeap.Ammo[1] != none && KFWeap.FireMode[1] != none && KFWeap.FireMode[1].AmmoPerFire > 0 && KFWeap.Ammo[1].AmmoAmount >= KFWeap.FireMode[1].AmmoPerFire)) )
{
bOutOfAmmo = false;
break;
}
}
if ( bOutOfAmmo )
{
PlayerController(Instigator.Controller).Speech('AUTO', 3, "");
}
}
return true;
}
return false;
}
simulated function ClientReload()
{
super.ClientReload();
if (FakedGasCan != none)
FakedGasCan.SetDrawScale(2); //test
// if MagAmmoRemaining == 0, chaisaw is already stopped
if ( MagAmmoRemaining > 0 )
PlaySound(EngineStopSound);
ThirdPersonActor.AmbientSound = none;
GotoState('Reloading');
}
simulated function ActuallyFinishReloading()
{
super.ActuallyFinishReloading();
IdleFuelConsumeTime = default.IdleFuelConsumeTime;
GotoState('');
if ( MagAmmoRemaining > 0) {
PlaySound(EngineStartSound);
ThirdPersonActor.AmbientSound = ThirdPersonActor.default.AmbientSound;
TexPanner(Skins[1]).PanRate = 3; // start saw cycling
PlayIdle();
}
}
simulated function ClientFinishReloading()
{
super.ClientFinishReloading();
if ( Level.NetMode != NM_DedicatedServer )
{
if (FakedGasCan != none)
FakedGasCan.SetDrawScale(0.01); //hide gas can after reload
}
}
simulated function WeaponTick(float dt)
{
super.WeaponTick(dt);
if ( Role == Role_Authority ) {
if ( !bIsReloading ) {
if ( MagAmmoRemaining <= 0) {
ThirdPersonActor.AmbientSound = none;
TexPanner(Skins[1]).PanRate = 0; // stop saw cycling
}
else {
if ( Level.TimeSeconds - FireMode[0].NextFireTime > 1.0 && Level.TimeSeconds - FireMode[1].NextFireTime > 1.0 ) {
//consume ammo on idle
IdleFuelConsumeTime -= dt;
if ( IdleFuelConsumeTime <= 0 ) {
ConsumeAmmo(0, 1);
IdleFuelConsumeTime = default.IdleFuelConsumeTime;
}
}
}
}
}
}
// there is no reload animation for Chainsaw, so play slow put down animation
// taking sounds from flamethrower reload
simulated state Reloading
{
simulated function BeginState()
{
NextReloadSoundIndex = 0;
TimeToNextReloadSound = ReloadRate * 0.2;
bBlownUpThisReload = false;
}
simulated function WeaponTick(float dt)
{
super.WeaponTick(dt);
if ( NextReloadSoundIndex < ReloadSounds.length ) {
// if ( NextReloadSoundIndex < ReloadSounds.length - 2 )
// ThirdPersonActor.AmbientSound = none;
TimeToNextReloadSound -= dt;
if ( TimeToNextReloadSound <= 0 ) {
PlaySound(ReloadSounds[NextReloadSoundIndex].Sound);
TimeToNextReloadSound += 0.8*ReloadRate * ReloadSounds[NextReloadSoundIndex].Duration/TotalReloadSoundDuration;
NextReloadSoundIndex++;
}
}
}
function TakeDamage(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional int HitIndex)
{
local ScrnFlameNade nade;
local int FuelInTank;
//blow the fuel inside a tank on fire damage received (excluding DoT)
if ( bBlownUpThisReload || DamageType == none || Damage < 5 || DamageType == class'DamTypeFlamethrower' )
return;
if ( Level.TimeSeconds > ReloadTimer + ReloadRate*0.9 ) //almost finished reloading, don't blow up
return;
if ( DamageType.default.bFlaming || (class<KFWeaponDamageType>(DamageType) != none && class<KFWeaponDamageType>(DamageType).default.bDealBurningDamage) ) {
bBlownUpThisReload = true;
FuelInTank = MagAmmoRemaining + (MagCapacity - MagAmmoRemaining) * (Level.TimeSeconds - ReloadTimer) / ReloadRate;
if ( FuelInTank > AmmoAmount(0) )
FuelInTank = AmmoAmount(0);
if ( FuelInTank < 1 )
return;
nade = spawn(class'ScrnBalanceSrv.ScrnFlameNade');
HideGasCan();
AttachToBone(nade, 'Chainsaw'); //attempt to move explosion onto chainsaw to make it obvious that the gas can caused the explosion
nade.SetRelativeLocation(vect(-3, 2, 3)); //move nade to exact gas can location
nade.SetTimer(0, false); // it will be blown up manualy
nade.Instigator = Instigator;
// the more fuel in tank, the higher is explosion
nade.Damage = FuelInTank;
AddAmmo(-FuelInTank, 0);
nade.Explode(Location, vect(0,0,1));
}
}
}
simulated function HideGasCan()
{
if ( Level.NetMode != NM_DedicatedServer )
{
FakedGasCan.SetDrawScale(0.01); //hide gas can after reload
}
}
//destroy gas can on destroy
simulated function Destroyed()
{
if ( FakedGasCan != none && !FakedGasCan.bDeleteMe )
FakedGasCan.Destroy();
super.Destroyed();
}
simulated function PlayIdle()
{
if ( MagAmmoRemaining > 0 )
super.PlayIdle();
}
defaultproperties
{
IdleFuelConsumeTime=5.000000
EngineStartSoundRef="KF_ChainsawSnd.Chainsaw_FalseStart4"
EngineStopSoundRef="KF_ChainsawSnd.Chainsaw_Deselect1"
ReloadSounds(0)=(SoundRef="KF_FlamethrowerSnd.FT_Reload1")
ReloadSounds(1)=(SoundRef="KF_FlamethrowerSnd.FT_Reload2")
ReloadSounds(2)=(SoundRef="KF_FlamethrowerSnd.FT_Reload3")
ReloadSounds(3)=(SoundRef="KF_FlamethrowerSnd.FT_Reload4")
ReloadSounds(4)=(SoundRef="KF_FlamethrowerSnd.FT_Reload5")
ReloadSounds(5)=(SoundRef="KF_FlamethrowerSnd.FT_Reload5b")
ReloadSounds(6)=(SoundRef="KF_FlamethrowerSnd.FT_Reload6")
ReloadSounds(7)=(SoundRef="KF_ChainsawSnd.Chainsaw_FalseStart1")
ReloadSounds(8)=(SoundRef="KF_ChainsawSnd.Chainsaw_FalseStart2")
MagCapacity=105
ReloadRate=2.666667
ReloadAnim="PutDown"
ReloadAnimRate=0.250000
WeaponReloadAnim="Reload_Flamethrower"
bAmmoHUDAsBar=True
FireModeClass(0)=Class'ScrnBalanceSrv.ScrnChainsawFire'
FireModeClass(1)=Class'ScrnBalanceSrv.ScrnChainsawAltFire'
bMeleeWeapon=False
bShowChargingBar=True
Description="This legendary chainsaw is used through the centuries to fight evil forces"
PickupClass=Class'ScrnBalanceSrv.ScrnChainsawPickup'
ItemName="Ash's Chainsaw"
}