463 lines
14 KiB
Ucode
463 lines
14 KiB
Ucode
class AKBaseWeapon extends KFWeapon
|
|
abstract;
|
|
|
|
#exec OBJ LOAD FILE=KillingFloorWeapons.utx
|
|
#exec OBJ LOAD FILE=KillingFloorHUD.utx
|
|
#exec OBJ LOAD FILE=Inf_Weapons_Foley.uax
|
|
|
|
var name ReloadShortAnim;
|
|
var float ReloadShortRate;
|
|
|
|
var transient KFWeaponPickup PendingPickup;
|
|
var transient bool bShortReload;
|
|
|
|
var const int OriginalMaxAmmo;
|
|
var const bool bSharedAmmoPool;
|
|
|
|
var transient class<KFVeterancyTypes> LastClientVeteranSkill;
|
|
var transient int LastClientVeteranSkillLevel;
|
|
|
|
var KFPlayerReplicationInfo OwnerPRI; // don't access it directly! Use GetOwnerPRI() instead.
|
|
|
|
simulated function AltFire(float F)
|
|
{
|
|
// if(ReadyToFire(0))
|
|
// {
|
|
DoToggle();
|
|
// }
|
|
}
|
|
|
|
exec function SwitchModes()
|
|
{
|
|
DoToggle();
|
|
}
|
|
|
|
function byte BestMode()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
simulated function int MaxAmmo(int mode)
|
|
{
|
|
if ( Ammo[mode] != none )
|
|
return Ammo[mode].MaxAmmo;
|
|
if ( AmmoClass[mode] != None )
|
|
return AmmoClass[mode].default.MaxAmmo * GetAmmoMulti();
|
|
return 0;
|
|
}
|
|
|
|
function GiveAmmo(int m, WeaponPickup WP, bool bJustSpawned)
|
|
{
|
|
local bool bJustSpawnedAmmo;
|
|
local int addAmount, InitialAmount;
|
|
|
|
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
|
|
|
|
if ( FireMode[m] != None && FireMode[m].AmmoClass != None )
|
|
{
|
|
Ammo[m] = Ammunition(Instigator.FindInventoryType(FireMode[m].AmmoClass));
|
|
bJustSpawnedAmmo = false;
|
|
|
|
if ( bNoAmmoInstances )
|
|
{
|
|
if ( (FireMode[m].AmmoClass == None) || ((m != 0) && (FireMode[m].AmmoClass == FireMode[0].AmmoClass)) )
|
|
return;
|
|
|
|
InitialAmount = FireMode[m].AmmoClass.Default.InitialAmount;
|
|
|
|
if(WP!=none && WP.bThrown==true)
|
|
InitialAmount = WP.AmmoAmount[m];
|
|
else
|
|
{
|
|
// Other change - if not thrown, give the gun a full clip
|
|
MagAmmoRemaining = MagCapacity;
|
|
}
|
|
|
|
if ( Ammo[m] != None )
|
|
{
|
|
addamount = InitialAmount + Ammo[m].AmmoAmount;
|
|
Ammo[m].Destroy();
|
|
}
|
|
else
|
|
addAmount = InitialAmount;
|
|
|
|
AddAmmo(addAmount,m);
|
|
}
|
|
else
|
|
{
|
|
if ( (Ammo[m] == None) && (FireMode[m].AmmoClass != None) )
|
|
{
|
|
Ammo[m] = Spawn(FireMode[m].AmmoClass, Instigator);
|
|
Instigator.AddInventory(Ammo[m]);
|
|
bJustSpawnedAmmo = true;
|
|
}
|
|
else if ( (m == 0) || (FireMode[m].AmmoClass != FireMode[0].AmmoClass) )
|
|
bJustSpawnedAmmo = ( bJustSpawned || ((WP != None) && !WP.bWeaponStay) );
|
|
|
|
// and here is the modification for instanced ammo actors
|
|
|
|
SetMaxAmmo();
|
|
|
|
if(WP!=none && WP.bThrown==true)
|
|
addAmount = WP.AmmoAmount[m];
|
|
else if ( bJustSpawnedAmmo ) {
|
|
if (default.MagCapacity == 0)
|
|
addAmount = 0; // prevent division by zero.
|
|
else
|
|
addAmount = Ammo[m].InitialAmount * (float(MagCapacity) / float(default.MagCapacity));
|
|
}
|
|
|
|
// Don't double add ammo if primary and secondary fire modes share the same ammo class
|
|
if ( WP != none && m > 0 && (FireMode[m].AmmoClass == FireMode[0].AmmoClass) )
|
|
return;
|
|
|
|
Ammo[m].AddAmmo(addAmount);
|
|
Ammo[m].GotoState('');
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function ClientWeaponSet(bool bPossiblySwitch)
|
|
{
|
|
super.ClientWeaponSet(bPossiblySwitch);
|
|
if ( Instigator != none )
|
|
SetMaxAmmo();
|
|
}
|
|
|
|
|
|
simulated function Destroyed()
|
|
{
|
|
SetMaxAmmo();
|
|
super.Destroyed();
|
|
}
|
|
|
|
exec simulated function SetMaxAmmo()
|
|
{
|
|
local Inventory Inv;
|
|
local AKBaseWeapon W;
|
|
local int c, NewMaxAmmo;
|
|
local Actor MyOwner;
|
|
local Ammunition MyAmmo;
|
|
|
|
if ( Instigator == none )
|
|
MyOwner = Instigator;
|
|
else
|
|
MyOwner = Owner;
|
|
|
|
if ( GetOwnerPRI() != none ) {
|
|
LastClientVeteranSkill = OwnerPRI.ClientVeteranSkill;
|
|
LastClientVeteranSkillLevel = OwnerPRI.ClientVeteranSkillLevel;
|
|
}
|
|
else
|
|
LastClientVeteranSkill = none;
|
|
if ( LastClientVeteranSkill != none )
|
|
LastAmmoResult = LastClientVeteranSkill.static.AddExtraAmmoFor(OwnerPRI, FireMode[0].AmmoClass);
|
|
else
|
|
LastAmmoResult = 1.0;
|
|
|
|
MyAmmo = Ammo[0];
|
|
|
|
if ( bSharedAmmoPool ) {
|
|
if ( PendingPickup == none && !bPendingDelete )
|
|
NewMaxAmmo = OriginalMaxAmmo;
|
|
for( Inv = MyOwner.Inventory; Inv!=none && (++c)<1000; Inv=Inv.Inventory ) {
|
|
W = AKBaseWeapon(Inv);
|
|
if ( W != none && W!= self && !W.bPendingDelete && W.Ammo[0] != none ) {
|
|
if ( W.Ammo[0] == MyAmmo )
|
|
NewMaxAmmo += W.OriginalMaxAmmo;
|
|
else if ( MyAmmo == none && W.Ammo[0].class == FireModeClass[0].default.AmmoClass ) {
|
|
MyAmmo = W.Ammo[0];
|
|
NewMaxAmmo += W.OriginalMaxAmmo;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( NewMaxAmmo == 0 )
|
|
NewMaxAmmo = FireMode[0].AmmoClass.default.MaxAmmo;
|
|
|
|
if ( MyAmmo != none ) {
|
|
MyAmmo.MaxAmmo = NewMaxAmmo * LastAmmoResult;
|
|
LastAmmoResult = float(MyAmmo.MaxAmmo) / MyAmmo.default.MaxAmmo; //used in GetAmmoMulti()
|
|
if ( MyAmmo.AmmoAmount > MyAmmo.MaxAmmo ) {
|
|
if ( PendingPickup != none ) {
|
|
PendingPickup.AmmoAmount[0] += MyAmmo.AmmoAmount - MyAmmo.MaxAmmo;
|
|
PendingPickup.MagAmmoRemaining = min(MagAmmoRemaining, PendingPickup.AmmoAmount[0]);
|
|
}
|
|
MyAmmo.AmmoAmount = MyAmmo.MaxAmmo;
|
|
}
|
|
if ( bSharedAmmoPool ) {
|
|
for( Inv = MyOwner.Inventory; Inv!=none && (++c)<1000; Inv=Inv.Inventory ) {
|
|
W = AKBaseWeapon(Inv);
|
|
if ( W != none && W != self ) {
|
|
W.LastAmmoResult = LastAmmoResult;
|
|
W.LastClientVeteranSkill = LastClientVeteranSkill;
|
|
W.LastClientVeteranSkillLevel = LastClientVeteranSkillLevel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function float GetAmmoMulti()
|
|
{
|
|
if ( GetOwnerPRI() == none ) {
|
|
LastClientVeteranSkill = none;
|
|
return 1.0;
|
|
}
|
|
if ( OwnerPRI.ClientVeteranSkill != LastClientVeteranSkill || OwnerPRI.ClientVeteranSkillLevel != LastClientVeteranSkillLevel )
|
|
SetMaxAmmo();
|
|
|
|
return LastAmmoResult;
|
|
}
|
|
|
|
simulated function KFPlayerReplicationInfo GetOwnerPRI()
|
|
{
|
|
if ( OwnerPRI == none ) {
|
|
if ( Instigator != none )
|
|
OwnerPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
|
|
if ( OwnerPRI == none && Pawn(Owner) != none )
|
|
OwnerPRI = KFPlayerReplicationInfo(Pawn(Owner).PlayerReplicationInfo);
|
|
}
|
|
return OwnerPRI;
|
|
}
|
|
|
|
// ensures that other guns with the same ammunition don't have more bullets in magazine than available
|
|
simulated function CheckSharedMags()
|
|
{
|
|
local int MaxMagAmmo, c;
|
|
local Inventory Inv;
|
|
local AKBaseWeapon W;
|
|
|
|
if ( !bSharedAmmoPool || Instigator == none || Ammo[0] == none )
|
|
return;
|
|
|
|
MaxMagAmmo = AmmoAmount(0) - MagAmmoRemaining;
|
|
for( Inv = Instigator.Inventory; Inv!=none && (++c)<1000; Inv=Inv.Inventory ) {
|
|
W = AKBaseWeapon(Inv);
|
|
if ( W != none && W!= self && W.Ammo[0] == Ammo[0] ) {
|
|
if ( W.MagAmmoRemaining > MaxMagAmmo )
|
|
W.MagAmmoRemaining = min(MaxMagAmmo, W.MagCapacity);
|
|
MaxMagAmmo -= W.MagAmmoRemaining;
|
|
if ( MaxMagAmmo < 0)
|
|
MaxMagAmmo = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function GetAmmoCount(out float MaxAmmoPrimary, out float CurAmmoPrimary)
|
|
{
|
|
if ( Ammo[0] != None ) {
|
|
MaxAmmoPrimary = Ammo[0].MaxAmmo;
|
|
CurAmmoPrimary = Ammo[0].AmmoAmount;
|
|
}
|
|
else {
|
|
MaxAmmoPrimary = 0;
|
|
CurAmmoPrimary = 0;
|
|
}
|
|
}
|
|
|
|
function DropFrom(vector StartLocation)
|
|
{
|
|
local int m;
|
|
local Pickup Pickup;
|
|
local vector Direction;
|
|
|
|
if (!bCanThrow)
|
|
return;
|
|
|
|
ClientWeaponThrown();
|
|
|
|
for (m = 0; m < NUM_FIRE_MODES; m++)
|
|
{
|
|
if (FireMode[m].bIsFiring)
|
|
StopFire(m);
|
|
}
|
|
|
|
if ( Instigator != None )
|
|
{
|
|
DetachFromPawn(Instigator);
|
|
Direction = vector(Instigator.Rotation);
|
|
}
|
|
else if ( Owner != none )
|
|
{
|
|
Direction = vector(Owner.Rotation);
|
|
}
|
|
|
|
Pickup = Spawn(PickupClass,,, StartLocation);
|
|
if ( Pickup != None )
|
|
{
|
|
Pickup.InitDroppedPickupFor(self);
|
|
Pickup.Velocity = Velocity + (Direction * 100);
|
|
if (Instigator.Health > 0)
|
|
WeaponPickup(Pickup).bThrown = true;
|
|
}
|
|
PendingPickup = KFWeaponPickup(Pickup);
|
|
|
|
Destroy();
|
|
}
|
|
|
|
|
|
|
|
|
|
simulated function SetZoomBlendColor(Canvas c)
|
|
{
|
|
local Byte val;
|
|
local Color clr;
|
|
local Color fog;
|
|
clr.R = 255;
|
|
clr.G = 255;
|
|
clr.B = 255;
|
|
clr.A = 255;
|
|
if( Instigator.Region.Zone.bDistanceFog )
|
|
{
|
|
fog = Instigator.Region.Zone.DistanceFogColor;
|
|
val = 0;
|
|
val = Max( val, fog.R);
|
|
val = Max( val, fog.G);
|
|
val = Max( val, fog.B);
|
|
if( val > 128 )
|
|
{
|
|
val -= 128;
|
|
clr.R -= val;
|
|
clr.G -= val;
|
|
clr.B -= val;
|
|
}
|
|
}
|
|
c.DrawColor = clr;
|
|
}
|
|
|
|
// copy-pasted to add (MagCapacity+1)
|
|
simulated function bool AllowReload()
|
|
{
|
|
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
|
|
|
|
if ( KFInvasionBot(Instigator.Controller) != none && !bIsReloading &&
|
|
MagAmmoRemaining < MagCapacity && AmmoAmount(0) > MagAmmoRemaining )
|
|
return true;
|
|
|
|
if ( KFFriendlyAI(Instigator.Controller) != none && !bIsReloading &&
|
|
MagAmmoRemaining < MagCapacity && AmmoAmount(0) > MagAmmoRemaining )
|
|
return true;
|
|
|
|
|
|
if( FireMode[0].IsFiring() || FireMode[1].IsFiring() ||
|
|
bIsReloading || MagAmmoRemaining >= MagCapacity ||
|
|
ClientState == WS_BringUp ||
|
|
AmmoAmount(0) <= MagAmmoRemaining ||
|
|
(FireMode[0].NextFireTime - Level.TimeSeconds) > 0.1 )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
exec function ReloadMeNow()
|
|
{
|
|
local float ReloadMulti;
|
|
|
|
if(!AllowReload())
|
|
return;
|
|
if ( bHasAimingMode && bAimingRifle )
|
|
{
|
|
FireMode[1].bIsFiring = False;
|
|
|
|
ZoomOut(false);
|
|
if( Role < ROLE_Authority)
|
|
ServerZoomOut(false);
|
|
}
|
|
if ( GetOwnerPRI() != none && OwnerPRI.ClientVeteranSkill != none )
|
|
{
|
|
ReloadMulti = OwnerPRI.ClientVeteranSkill.Static.GetReloadSpeedModifier(OwnerPRI, self);
|
|
}
|
|
else
|
|
{
|
|
ReloadMulti = 1.0;
|
|
}
|
|
bIsReloading = true;
|
|
ReloadTimer = Level.TimeSeconds;
|
|
bShortReload = MagAmmoRemaining > 0;
|
|
if ( bShortReload )
|
|
ReloadRate = Default.ReloadShortRate / ReloadMulti;
|
|
else
|
|
ReloadRate = Default.ReloadRate / ReloadMulti;
|
|
|
|
if( bHoldToReload )
|
|
{
|
|
NumLoadedThisReload = 0;
|
|
}
|
|
ClientReload();
|
|
Instigator.SetAnimAction(WeaponReloadAnim);
|
|
if ( Level.Game.NumPlayers > 1 && KFGameType(Level.Game).bWaveInProgress && KFPlayerController(Instigator.Controller) != none &&
|
|
Level.TimeSeconds - KFPlayerController(Instigator.Controller).LastReloadMessageTime > KFPlayerController(Instigator.Controller).ReloadMessageDelay )
|
|
{
|
|
KFPlayerController(Instigator.Controller).Speech('AUTO', 2, "");
|
|
KFPlayerController(Instigator.Controller).LastReloadMessageTime = Level.TimeSeconds;
|
|
}
|
|
}
|
|
|
|
simulated function ClientReload()
|
|
{
|
|
local float ReloadMulti;
|
|
if ( bHasAimingMode && bAimingRifle )
|
|
{
|
|
FireMode[1].bIsFiring = False;
|
|
|
|
ZoomOut(false);
|
|
if( Role < ROLE_Authority)
|
|
ServerZoomOut(false);
|
|
}
|
|
if ( GetOwnerPRI() != none && OwnerPRI.ClientVeteranSkill != none )
|
|
ReloadMulti = OwnerPRI.ClientVeteranSkill.Static.GetReloadSpeedModifier(OwnerPRI, self);
|
|
else
|
|
ReloadMulti = 1.0;
|
|
bIsReloading = true;
|
|
if (MagAmmoRemaining <= 0)
|
|
{
|
|
PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.1);
|
|
}
|
|
else if (MagAmmoRemaining >= 1)
|
|
{
|
|
PlayAnim(ReloadShortAnim, ReloadAnimRate*ReloadMulti, 0.1);
|
|
}
|
|
}
|
|
|
|
function AddReloadedAmmo()
|
|
{
|
|
local int a;
|
|
|
|
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
|
|
|
|
a = MagCapacity;
|
|
if ( bShortReload )
|
|
a++; // 1 bullet already bolted
|
|
|
|
if ( AmmoAmount(0) >= a )
|
|
MagAmmoRemaining = a;
|
|
else
|
|
MagAmmoRemaining = AmmoAmount(0);
|
|
|
|
// this seems redudant -- PooSH
|
|
// if( !bHoldToReload )
|
|
// {
|
|
// ClientForceKFAmmoUpdate(MagAmmoRemaining,AmmoAmount(0));
|
|
// }
|
|
|
|
if ( PlayerController(Instigator.Controller) != none && KFSteamStatsAndAchievements(PlayerController(Instigator.Controller).SteamStatsAndAchievements) != none )
|
|
{
|
|
KFSteamStatsAndAchievements(PlayerController(Instigator.Controller).SteamStatsAndAchievements).OnWeaponReloaded();
|
|
}
|
|
}
|
|
|
|
simulated function ActuallyFinishReloading()
|
|
{
|
|
super.ActuallyFinishReloading();
|
|
if ( bSharedAmmoPool )
|
|
CheckSharedMags();
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
ReloadShortAnim="Reload"
|
|
ReloadShortRate=3.000000
|
|
OriginalMaxAmmo=300
|
|
bSharedAmmoPool=True
|
|
}
|