Revert weapon conversion

This patch reverts first step of global weapon conversion
that would have halted the release of the next version for too long.
This commit is contained in:
Anton Tarasenko 2020-04-17 23:06:41 +07:00
commit 12d95e387e
757 changed files with 10788 additions and 4046 deletions

View file

@ -0,0 +1,306 @@
class NiceAssaultRifle extends NiceWeapon;
var bool newStatesLoaded;
var bool bAutoFireEnabled;
var bool bSemiAutoFireEnabled;
var bool bBurstFireEnabled;
var bool bIsBursting;
var bool bIsAltSwitches;
var bool bMustSwitchMode; // Switch between auto and semi-auto/burst modes as soon as possible
var Pawn rememberedOwner;
enum EFireType{
ETYPE_NONE,
ETYPE_AUTO,
ETYPE_SEMI,
ETYPE_BURST
};
var EFireType MainFire;
var EFireType SndFire;
var EFireType PendingFire;
replication
{
reliable if(Role < ROLE_Authority)
ServerForceBurst, ServerApplyFireModes, ServerChangeFireTypes;
reliable if(Role == ROLE_Authority)
MainFire, SndFire, PendingFire, ClientNiceChangeFireMode, ClientChangeBurstLength;
}
simulated function EFireType GetComplimentaryFire(EFireType type){
if(type == ETYPE_AUTO || type == ETYPE_none)
return ETYPE_AUTO;
if(type == ETYPE_SEMI)
return ETYPE_BURST;
return ETYPE_SEMI;
}
simulated function int AmountOfActiveModes(){
if(bAutoFireEnabled && bSemiAutoFireEnabled && bBurstFireEnabled)
return 3;
else if(!bAutoFireEnabled && !bSemiAutoFireEnabled && !bBurstFireEnabled)
return 0;
else if( (bAutoFireEnabled && bSemiAutoFireEnabled) || (bAutoFireEnabled && bBurstFireEnabled) || (bSemiAutoFireEnabled && bBurstFireEnabled) )
return 2;
return 1;
}
function ServerApplyFireModes(){
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
niceRifleFire = NiceFire(FireMode[0]);
if(Instigator != none)
nicePlayer = NicePlayerController(Instigator.Controller);
if(niceRifleFire == none)
return;
if(MainFire == ETYPE_AUTO)
niceRifleFire.bWaitForRelease = false;
else if(MainFire == ETYPE_SEMI){
niceRifleFire.bSemiMustBurst = false;
niceRifleFire.bWaitForRelease = true;
}
else if(MainFire == ETYPE_BURST){
niceRifleFire.bSemiMustBurst = true;
niceRifleFire.bWaitForRelease = true;
niceRifleFire.currentContext.burstLength = niceRifleFire.MaxBurstLength;
if(SndFire == ETYPE_SEMI)
SndFire = ETYPE_BURST;
}
if(nicePlayer != none && !nicePlayer.bFlagAltSwitchesModes){
if(SndFire == ETYPE_SEMI)
niceRifleFire.currentContext.burstLength = 1;
else if(SndFire == ETYPE_BURST)
niceRifleFire.currentContext.burstLength = niceRifleFire.MaxBurstLength;
}
if(!bIsReloading && IsFiring()){
StopFire(0);
StopFire(1);
}
ClientNiceChangeFireMode(niceRifleFire.bWaitForRelease, niceRifleFire.bSemiMustBurst);
ClientChangeBurstLength(niceRifleFire.currentContext.burstLength);
}
simulated function ResetFireModes(){
local int modesCount;
local NicePlayerController nicePlayer;
modesCount = AmountOfActiveModes();
nicePlayer = NicePlayerController(Instigator.Controller);
if(modesCount <= 0 || nicePlayer == none)
return;
if(nicePlayer.bFlagAltSwitchesModes){
if(modesCount == 1){
if(bAutoFireEnabled)
MainFire = ETYPE_AUTO;
else if(bSemiAutoFireEnabled)
MainFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
MainFire = ETYPE_BURST;
}
else if(modesCount == 2){
if(bAutoFireEnabled){
MainFire = ETYPE_AUTO;
if(bSemiAutoFireEnabled)
PendingFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
PendingFire = ETYPE_BURST;
}
else{
MainFire = ETYPE_SEMI;
PendingFire = ETYPE_BURST;
}
}
else{
MainFire = ETYPE_AUTO;
PendingFire = ETYPE_SEMI;
}
}
else{
if(modesCount == 1){
if(bAutoFireEnabled)
MainFire = ETYPE_AUTO;
else if(bSemiAutoFireEnabled)
MainFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
MainFire = ETYPE_BURST;
SndFire = ETYPE_none;
}
else if(modesCount == 2){
if(bAutoFireEnabled){
MainFire = ETYPE_AUTO;
if(bSemiAutoFireEnabled)
SndFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
SndFire = ETYPE_BURST;
}
else{
MainFire = ETYPE_SEMI;
SndFire = ETYPE_BURST;
}
}
else{
MainFire = ETYPE_AUTO;
SndFire = ETYPE_SEMI;
}
}
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
}
function ServerChangeFireTypes(EFireType newMain, EFireType newSnd, EFireType newPending){
MainFire = newMain;
SndFire = newSnd;
PendingFire = newPending;
}
function ServerForceBurst(){
local NiceFire niceRifleFire;
niceRifleFire = NiceFire(FireMode[0]);
if(niceRifleFire != none)
niceRifleFire.DoBurst();
}
// Use alt fire to switch fire modes
simulated function AltFire(float F){
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
niceRifleFire = NiceFire(FireMode[0]);
nicePlayer = NicePlayerController(Instigator.Controller);
if(nicePlayer != none && niceRifleFire != none && SndFire != ETYPE_NONE){
if(FireModeClass[1] == class'KFMod.NoFire'){
if(nicePlayer.bFlagAltSwitchesModes)
SwitchModes();
else{
niceRifleFire.DoBurst();
ServerForceBurst();
super.AltFire(F);
}
return;
}
}
super.AltFire(F);
}
exec simulated function SwitchModes(){
if(Role < ROLE_Authority && AmountOfActiveModes() > 1)
bMustSwitchMode = !bMustSwitchMode;
}
simulated function DoToggle(){
local EFireType tempType;
local PlayerController player;
if(IsFiring())
return;
player = Level.GetLocalPlayerController();
if(player != none && AmountOfActiveModes() > 1){
tempType = MainFire;
MainFire = PendingFire;
PendingFire = tempType;
player.bFire = 0;
player.bAltFire = 0;
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
PlayOwnedSound(ToggleSound, SLOT_none, 2.0,,,, false);
if(MainFire == ETYPE_AUTO)
player.ReceiveLocalizedMessage(class'NicePack.NiceAssaultRifleMessage', 1);
else if(MainFire == ETYPE_SEMI)
player.ReceiveLocalizedMessage(class'NicePack.NiceAssaultRifleMessage', 0);
else if(MainFire == ETYPE_BURST)
player.ReceiveLocalizedMessage(class'NicePack.NiceAssaultRifleMessage', 2);
}
}
simulated function SecondDoToggle(){
local EFireType choosenType;
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
if(FireModeClass[1] != class'KFMod.NoFire'){
DoToggle();
return;
}
niceRifleFire = NiceFire(FireMode[0]);
nicePlayer = NicePlayerController(Instigator.Controller);
if(IsFiring() || AmountOfActiveModes() < 3 || nicePlayer == none || niceRifleFire == none)
return;
if(nicePlayer.bFlagAltSwitchesModes){
if(MainFire == ETYPE_AUTO){
PendingFire = GetComplimentaryFire(PendingFire);
choosenType = PendingFire;
}
else{
MainFire = GetComplimentaryFire(MainFire);
choosenType = MainFire;
}
}
else{
SndFire = GetComplimentaryFire(SndFire);
choosenType = SndFire;
}
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
PlayOwnedSound(ToggleSound, SLOT_none, 2.0,,,, false);
if(choosenType == ETYPE_SEMI)
nicePlayer.ReceiveLocalizedMessage(class'NicePack.NiceAssaultRifleMessage', 4);
else
nicePlayer.ReceiveLocalizedMessage(class'NicePack.NiceAssaultRifleMessage', 5);
}
simulated function ClientNiceChangeFireMode(bool bNewWaitForRelease, bool bNewSemiMustBurst){
local NiceFire niceF;
if(!bIsReloading && IsFiring()){
StopFire(0);
StopFire(1);
}
niceF = NiceFire(FireMode[0]);
FireMode[0].bWaitForRelease = bNewWaitForRelease;
FireMode[0].bNowWaiting = bNewWaitForRelease;
if(niceF != none)
niceF.bSemiMustBurst = bNewSemiMustBurst;
}
simulated function ClientChangeBurstLength(int newBurstLength){
if(NiceFire(FireMode[0]) != none)
NiceFire(FireMode[0]).currentContext.burstLength = newBurstLength;
}
simulated function bool AltFireCanForceInterruptReload(){
local NicePlayerController nicePlayer;
nicePlayer = NicePlayerController(Instigator.Controller);
if(nicePlayer != none)
return (!nicePlayer.bFlagAltSwitchesModes) && (GetMagazineAmmo() > 0);
return false;
}
simulated function WeaponTick(float dt){
local NicePlayerController nicePlayer;
super.WeaponTick(dt);
if(bMustSwitchMode && FireMode[0].NextFireTime /*+ 0.1*/ < Level.TimeSeconds && Role < ROLE_Authority){
DoToggle();
bMustSwitchMode = false;
}
nicePlayer = NicePlayerController(Instigator.Controller);
if(Role == ROLE_Authority && nicePlayer != none && (bIsAltSwitches != nicePlayer.bFlagAltSwitchesModes || (rememberedOwner != Instigator))){
if(newStatesLoaded)
ServerApplyFireModes();
else
ResetFireModes();
bIsAltSwitches = nicePlayer.bFlagAltSwitchesModes;
rememberedOwner = Instigator;
}
}
function NicePlainData.Data GetNiceData(){
local NicePlainData.Data transferData;
transferData = super.GetNiceData();
class'NicePlainData'.static.SetInt(transferData, "MainFire", int(MainFire));
class'NicePlainData'.static.SetInt(transferData, "SndFire", int(SndFire));
class'NicePlainData'.static.SetInt(transferData, "PendingFire", int(PendingFire));
return transferData;
}
function SetNiceData(NicePlainData.Data transferData, optional NiceHumanPawn newOwner){
local EFireType newFireType;
super.SetNiceData(transferData, newOwner);
newStatesLoaded = false;
if(class'NicePlainData'.static.LookupVar(transferData, "MainFire") < 0)
ResetFireModes();
else{
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "MainFire"));
MainFire = newFireType;
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "SndFire"));
SndFire = newFireType;
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "PendingFire"));
PendingFire = newFireType;
newStatesLoaded = true;
}
}
defaultproperties
{
bAutoFireEnabled=True
bSemiAutoFireEnabled=True
MainFire=ETYPE_AUTO
SndFire=ETYPE_SEMI
PendingFire=ETYPE_BURST
bUseFlashlightToToggle=True
}

View file

@ -0,0 +1,9 @@
class NiceAssaultRifleMessage extends BullpupSwitchMessage;
defaultproperties
{
SwitchMessage(2)="Set to Burst Fire."
SwitchMessage(3)="Set to 5-Burst Fire."
SwitchMessage(4)="Secondary mode now set to Semi-Automatic."
SwitchMessage(5)="Secondary mode now set to Burst Fire."
}

View file

@ -0,0 +1,6 @@
class NiceHeavyFire extends NiceFire;
defaultproperties
{
maxBonusContLenght=3
}

View file

@ -0,0 +1,5 @@
class NiceHeavyGun extends NiceWeapon;
defaultproperties
{
}

View file

@ -0,0 +1,57 @@
class NiceMedicDartFire extends NiceFire;
function DoFireEffect(){
local float oldLoad;
oldLoad = Load;
Load = 1;
super.DoFireEffect();
Load = oldLoad;
}
simulated function bool AllowFire(){
local KFPawn kfPwn;
if(currentContext.sourceWeapon == none || Instigator == none)
return false;
if(currentContext.sourceWeapon.secondaryCharge < default.AmmoPerFire)
return false;
// Check reloading
if(currentContext.sourceWeapon.bIsReloading)
return false;
// Check pawn actions
kfPwn = KFPawn(Instigator);
if(kfPwn == none || kfPwn.SecondaryItem != none || kfPwn.bThrowingNade)
return false;
return true;
}
simulated function ReduceAmmoClient(){
local NiceMedicGun sourceMedGun;
currentContext.sourceWeapon.secondaryCharge -= AmmoPerFire;
sourceMedGun = NiceMedicGun(currentContext.sourceWeapon);
if(sourceMedGun != none){
sourceMedGun.ServerSetMedicCharge(currentContext.sourceWeapon.secondaryCharge);
sourceMedGun.ClientSetMedicCharge(currentContext.sourceWeapon.secondaryCharge);
}
}
defaultproperties
{
ProjectileSpeed=12500.000000
bulletClass=Class'NicePack.NiceMedicProjectile'
FireAimedAnim="Fire_Iron"
FireSoundRef="KF_MP7Snd.Medicgun_Fire"
StereoFireSoundRef="KF_MP7Snd.Medicgun_FireST"
NoAmmoSoundRef="KF_PumpSGSnd.SG_DryFire"
DamageMax=30
bWaitForRelease=True
bAttachSmokeEmitter=True
TransientSoundVolume=2.000000
TransientSoundRadius=500.000000
AmmoPerFire=50
ShakeRotMag=(X=50.000000,Y=50.000000,Z=400.000000)
ShakeRotRate=(X=12500.000000,Y=12500.000000,Z=12500.000000)
ShakeRotTime=5.000000
ShakeOffsetMag=(X=6.000000,Y=2.000000,Z=10.000000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=3.000000
BotRefireRate=0.250000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stKar'
aimerror=1.000000
}

View file

@ -0,0 +1,91 @@
class NiceMedicGun extends NiceWeapon
abstract;
var const float maxMedicCharge;
var float medicChargeRegenRate;
// This variable is dictated by client.
var float medicCharge;
// Medic charge is replicated on server via these periods
var float medicChargeUpdatePeriod;
// This variable is only relevant on a server, to predict current medic charge in-between new updates
var float lastMedicChargeServerUpdate;
// This variable is only relevant on a client, to predict current medic charge in-between weapon ticks
var float lastMedicChargeClientUpdate;
replication{
reliable if(Role < ROLE_Authority)
ServerSetMedicCharge;
reliable if(Role == ROLE_Authority)
ClientSetMedicCharge, ClientSuccessfulHeal;
}
function NicePlainData.Data GetNiceData(){
local NicePlainData.Data transferData;
transferData = super.GetNiceData();
class'NicePlainData'.static.SetFloat(transferData, "MedicCharge", GetCurrentMedicCharge());
class'NicePlainData'.static.SetFloat(transferData, "MedicChargeUpd", Level.TimeSeconds);
return transferData;
}
function SetNiceData(NicePlainData.Data transferData, optional NiceHumanPawn newOwner){
super.SetNiceData(transferData, newOwner);
medicCharge = class'NicePlainData'.static.GetFloat(transferData, "MedicCharge", 0.0);
lastMedicChargeServerUpdate = class'NicePlainData'.static.GetFloat(transferData, "MedicChargeUpd", -1.0);
if(lastMedicChargeServerUpdate >= 0.0)
medicCharge += (Level.TimeSeconds - lastMedicChargeServerUpdate) * medicChargeRegenRate;
lastMedicChargeServerUpdate = Level.TimeSeconds;
ClientSetMedicCharge(medicCharge);
}
function ServerSetMedicCharge(float newCharge){
medicCharge = newCharge;
lastMedicChargeServerUpdate = Level.TimeSeconds;
}
simulated function ClientSetMedicCharge(float newCharge){
medicCharge = newCharge;
}
// Returns current medic charge
// Uses prediction a server
simulated function float GetCurrentMedicCharge(){
if(Role < ROLE_Authority)
return medicCharge;
else
return medicCharge + (Level.TimeSeconds - lastMedicChargeServerUpdate) * medicChargeRegenRate;
}
simulated function WeaponTick(float dt){
local int prevPeriodsAmount;
local bool bWasBelowMax;
if(Role < ROLE_Authority){
// Remember the old state
bWasBelowMax = (medicCharge < maxMedicCharge);
prevPeriodsAmount = Ceil(medicCharge / medicChargeUpdatePeriod);
// Update medic charge
medicCharge += (Level.TimeSeconds - lastMedicChargeClientUpdate) * medicChargeRegenRate;
lastMedicChargeClientUpdate = Level.TimeSeconds;
medicCharge = FMin(medicCharge, maxMedicCharge);
secondaryCharge = Ceil(medicCharge);
// Replicate to server when necessary
if( (bWasBelowMax && medicCharge >= maxMedicCharge)
|| prevPeriodsAmount < Ceil(medicCharge / medicChargeUpdatePeriod) )
ServerSetMedicCharge(medicCharge);
}
super.WeaponTick(dt);
}
simulated function ClientSuccessfulHeal(NiceHumanPawn healer, NiceHumanPawn healed){
if(healed == none)
return;
if(instigator != none && PlayerController(instigator.controller) != none)
PlayerController(instigator.controller).
ClientMessage("You've healed"@healed.GetPlayerName(), 'CriticalEvent');
if(NiceHumanPawn(instigator) != none && PlayerController(healed.controller) != none)
PlayerController(healed.controller).
ClientMessage("You've been healed by"@healer.GetPlayerName(), 'CriticalEvent');
}
defaultproperties
{
maxMedicCharge=100.000000
medicChargeRegenRate=10.000000
medicChargeUpdatePeriod=10.000000
bShowSecondaryCharge=True
SecondaryCharge=0
bChangeSecondaryIcon=True
hudSecondaryTexture=Texture'KillingFloorHUD.HUD.Hud_Syringe'
activeSlowdown=0.750000
activeSpeedup=2.000000
}

View file

@ -0,0 +1,20 @@
class NiceMedicProjectile extends NiceBullet;
function GenerateImpactEffects(ImpactEffect effect, Vector hitLocation, Vector hitNormal,
optional bool bWallImpact, optional bool bGenerateDecal){
if(bWallImpact){
effect.EmitterClass = none;
effect.bPlayROEffect = true;
effect.bImportanEffect = false;
effect.noise = none;
}
super.GenerateImpactEffects(effect, hitLocation, hitNormal, bWallImpact, bGenerateDecal);
}
defaultproperties
{
trailXClass=None
regularImpact=(bImportanEffect=True,bPlayROEffect=False,decalClass=Class'KFMod.ShotgunDecal',EmitterClass=Class'KFMod.healingFX',emitterShiftWall=20.000000,emitterShiftPawn=20.000000,noiseRef="KF_MP7Snd.MP7_DartImpact",noiseVolume=2.000000)
bGenRegEffectOnPawn=True
StaticMeshRef="KF_pickups2_Trip.MP7_Dart"
AmbientSoundRef="KF_MP7Snd.MP7_DartFlyLoop"
}

View file

@ -0,0 +1,6 @@
class NiceMeleeAttachment extends NiceAttachment;
defaultproperties
{
bDoFiringEffects=False
}

View file

@ -0,0 +1,290 @@
//==============================================================================
// NicePack / NiceMeleeFire
//==============================================================================
// Adjustment of vanilla melee fire class to NicePack.
//==============================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//==============================================================================
class NiceMeleeFire extends NiceFire;
var float weaponRange;
var float damageDelay;
// How far to rot view?
var vector impactShakeRotMag;
// How fast to rot view?
var vector impactShakeRotRate;
// How much time to rot the instigator's view?
var float impactShakeRotTime;
// Max view offset vertically?
var vector impactShakeOffsetMag;
// How fast to offset view vertically?
var vector impactShakeOffsetRate;
// How much time to offset view?
var float impactShakeOffsetTime;
// Sound for this melee strike hitting a pawn (fleshy hits).
var array<sound> meleeHitSounds;
var float meleeHitVolume;
var array<name> fireAnims;
// The class to spawn for the hit effect for
// this melee weapon hitting the world (not pawns).
var class<KFMeleeHitEffect> hitEffectClass;
var array<string> meleeHitSoundRefs;
// The angle to do sweeping strikes in front of the player.
// If zero, - do no strikes.
var float wideDamageMinHitAngle;
static function PreloadAssets(LevelInfo level, optional KFFire spawned){
local int i;
local NiceMeleeFire niceFire;
super.PreloadAssets(level, spawned);
for(i = 0; i < default.meleeHitSoundRefs.length;i ++){
if(default.meleeHitSoundRefs[i] == "")
continue;
if( default.meleeHitSounds.length >= i + 1
&& default.meleeHitSounds[i] != none)
continue;
default.meleeHitSounds[i] = Sound(
DynamicLoadObject( default.meleeHitSoundRefs[i],
class'Sound', true));
}
niceFire = NiceMeleeFire(spawned);
if(niceFire != none)
for(i = 0; i < default.meleeHitSoundRefs.length;i ++)
niceFire.meleeHitSounds[i] = default.meleeHitSounds[i];
}
static function bool UnloadAssets(){
local int i;
super.UnloadAssets();
for(i = 0; i < default.meleeHitSoundRefs.length;i ++)
default.meleeHitSounds[i] = none;
return true;
}
simulated function DoBurst(optional bool bSkipFirstShot){}
function DoFireEffect(){}
function float MaxRange(){
local bool hasWindCutterSkill;
traceRange = weaponRange;
if(instigator == none) return traceRange;
hasWindCutterSkill = class'NiceVeterancyTypes'.static.
HasSkill( NicePlayerController(instigator.controller),
class'NiceSkillZerkWindCutter');
if(hasWindCutterSkill)
traceRange *= class'NiceSkillZerkWindCutter'.default.rangeBonus;
return traceRange;
}
simulated function bool AllowFire(){
local KFPawn kfPwn;
// Check pawn actions
kfPwn = KFPawn(instigator);
if(kfPwn == none || kfPwn.SecondaryItem != none || kfPwn.bThrowingNade)
return false;
return true;
}
function name GetCorrectAnim(bool bLoop, bool bAimed){
local int AnimToPlay;
if(fireAnims.length > 0){
AnimToPlay = rand(fireAnims.length);
fireAnim = fireAnims[AnimToPlay];
}
return FireAnim;
}
simulated function NiceMonster DealTargetMeleeDamage
(
NiceReplicationInfo niceRI,
class<NiceWeaponDamageType> niceDmgType
){
local float headSizeModifier;
local float headshotLevel;
local NiceMonster niceZed;
local Vector hitLocation, hitNormal;
local KFPlayerReplicationInfo KFPRI;
local class<NiceVeterancyTypes> niceVet;
if(niceRI == none || instigator == none) return none;
KFPRI = KFPlayerReplicationInfo(instigator.PlayerReplicationInfo);
if(KFPRI == none)
return none;
niceVet = class<NiceVeterancyTypes>(KFPRI.ClientVeteranSkill);
if(niceVet == none)
return none;
if(niceDmgType != none)
headSizeModifier = niceDmgType.default.headSizeModifier;
headSizeModifier = 1.0;
headSizeModifier *=
niceVet.static.GetHeadshotCheckMultiplier(KFPRI, niceDmgType);
headshotLevel = TraceZed(niceZed, hitLocation, hitNormal, headSizeModifier);
if(niceZed != none)
HitZed(niceZed, headshotLevel, niceRI, niceDmgType);
else
HitWall(niceRI, niceDmgType);
return niceZed;
}
function HitZed(NiceMonster niceZed,
float headshotLevel,
NiceReplicationInfo niceRI,
class<NiceWeaponDamageType> niceDmgType){
local Vector hitLocation, hitNormal;
local NiceMeleeWeapon niceWeap;
ImpactShakeView();
niceWeap = NiceMeleeWeapon(weapon);
if(niceWeap != none && niceWeap.BloodyMaterial != none)
niceWeap.Skins[niceWeap.BloodSkinSwitchArray] = niceWeap.BloodyMaterial;
niceRI.ServerDealMeleeDamage( niceZed, damageMax, instigator,
hitLocation, -hitNormal,
niceDmgType, true, headshotLevel);
}
function HitWall( NiceReplicationInfo niceRI,
class<NiceWeaponDamageType> niceDmgType){
local Actor wall;
local Vector hitLocation, hitNormal;
local Rotator rotation;
TraceWall(wall, hitLocation, hitNormal);
if(wall != none){
niceRI.ServerDealMeleeDamage( wall, damageMax, instigator,
hitLocation, -hitNormal, niceDmgType,
false);
rotation = Rotator
(
HitLocation - instigator.location - instigator.EyePosition()
);
instigator.spawn(hitEffectClass,,, hitLocation, rotation);
}
}
simulated function DealArcMeleeDamage
(
NiceMonster niceZed,
NiceReplicationInfo niceRI,
class<NiceWeaponDamageType> niceDmgType
){
local NiceMonster otherZed;
local float actualMinAngle, tempRadians;
local bool hasCleave;
if(weapon == none) return;
hasCleave = class'NiceVeterancyTypes'.static.
HasSkill( NicePlayerController(instigator.controller),
class'NiceSkillZerkCleave');
actualMinAngle = wideDamageMinHitAngle;
if(hasCleave){
tempRadians = acos(actualMinAngle);
tempRadians += class'NiceSkillZerkCleave'.default.bonusDegrees;
tempRadians = FMin(tempRadians, Pi);
actualMinAngle = cos(tempRadians);
}
foreach weapon.VisibleCollidingActors(
class'NiceMonster', otherZed, weaponRange * 2,
instigator.location + instigator.EyePosition()){
if(niceZed != none && otherZed == niceZed) continue;
if(otherZed == instigator || otherZed.Health <= 0) continue;
TryHitZedArc(actualMinAngle, otherZed, niceRI, niceDmgType);
}
}
function TryHitZedArc(float minAngle, NiceMonster niceZed,
NiceReplicationInfo niceRI,
class<NiceWeaponDamageType> niceDmgType){
local vector hitLocation, hitNormal;
local vector dir, lookDir;
local float diffAngle, victimDist;
victimDist = VSize(instigator.location - niceZed.location);
if(victimDist + niceZed.CollisionRadius > weaponRange * 1.1)
return;
lookDir = Normal(Vector(instigator.GetViewRotation()));
dir = Normal(niceZed.location - instigator.location);
diffAngle = lookDir dot dir;
if(diffAngle <= minAngle)
return;
hitLocation =
niceZed.location + niceZed.CollisionHeight * vect(0,0,0.7);
niceRI.ServerDealMeleeDamage( niceZed, damageMax * 0.5, instigator,
hitLocation, hitNormal, niceDmgType,
false, 0.0);
if(meleeHitSounds.Length > 0)
niceZed.PlaySound( meleeHitSounds[Rand(meleeHitSounds.length)],
SLOT_None, meleeHitVolume,,,, false);
}
simulated function Timer(){
local NiceMonster niceZed;
local NiceReplicationInfo niceRI;
local class<NiceWeaponDamageType> niceDmgType;
niceRI = GetNiceRI();
niceDmgType = class<NiceWeaponDamageType>(damageType);
if(niceRI == none || instigator == none || niceDmgType == none)
return;
niceZed = DealTargetMeleeDamage(niceRI, niceDmgType);
DealArcMeleeDamage(niceZed, niceRI, niceDmgType);
}
simulated function MDFEffectsClient(float newAmmoPerFire, float rec){
local float fireSpeedMod;
fireSpeedMod = GetFireSpeed();
super.MDFEffectsClient(newAmmoPerFire, rec);
SetTimer(damageDelay / fireSpeedMod, false);
}
function PlayFiring_animation(){
if(weapon == none) return;
if(weapon.Mesh == none) return;
if(fireCount <= 0){
weapon.PlayAnim(GetCorrectAnim(false, false), fireAnimRate, 0.0);
return;
}
if(weapon.HasAnim(FireLoopAnim))
weapon.PlayAnim(GetCorrectAnim(true, false), fireLoopAnimRate, 0.0);
else
weapon.PlayAnim(GetCorrectAnim(false, false), fireAnimRate, 0.0);
}
function PlayFiring(){
local float randPitch;
local bool shouldPlayStereo;
if(weapon == none) return;
if(weapon.instigator == none) return;
PlayFiring_animation();
if(bRandomPitchFireSound){
randPitch = FRand() * RandomPitchAdjustAmt;
if(FRand() < 0.5)
randPitch *= -1.0;
}
shouldPlayStereo = weapon.instigator.IsLocallyControlled()
&& weapon.instigator.IsFirstPerson()
&& StereoFireSound != none;
if(shouldPlayStereo){
weapon.PlayOwnedSound( StereoFireSound, SLOT_Interact,
TransientSoundVolume * 0.85,,
TransientSoundRadius, 1.0 + randPitch, false);
}
else{
weapon.PlayOwnedSound( FireSound, SLOT_Interact, TransientSoundVolume,,
TransientSoundRadius, 1.0 + randPitch, false);
}
ClientPlayForceFeedback(fireForce);
if(!currentContext.bIsBursting)
fireCount ++;
}
function ImpactShakeView(){
local NicePlayerController nicePlayer;
if(instigator == none) return;
nicePlayer = NicePlayerController(instigator.controller);
if(nicePlayer == none)
return;
nicePlayer.WeaponShakeView( impactShakeRotMag, impactShakeRotRate,
impactShakeRotTime, impactShakeOffsetMag,
impactShakeOffsetRate, impactShakeOffsetTime);
}
simulated function HandleRecoil(float Rec){}
defaultproperties
{
weaponRange=70.000000
damageDelay=0.300000
ImpactShakeRotMag=(X=50.000000,Y=50.000000,Z=50.000000)
ImpactShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
ImpactShakeRotTime=2.000000
ImpactShakeOffsetMag=(X=10.000000,Y=10.000000,Z=10.000000)
ImpactShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ImpactShakeOffsetTime=2.000000
MeleeHitVolume=1.000000
HitEffectClass=Class'KFMod.KFMeleeHitEffect'
WideDamageMinHitAngle=1.000000
bFiringDoesntAffectMovement=True
FireEndAnim=
FireForce="ShockRifleFire"
aimerror=100.000000
}

View file

@ -0,0 +1,42 @@
class NiceMeleeWeapon extends NiceWeapon;
var class<damageType> hitDamType;
var float weaponRange;
var Material BloodyMaterial;
var int BloodSkinSwitchArray;
var string BloodyMaterialRef;
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount){
super.PreloadAssets(Inv, bSkipRefCount);
if(default.BloodyMaterial == none && default.BloodyMaterialRef != "")
default.BloodyMaterial = Combiner(DynamicLoadObject(default.BloodyMaterialRef, class'Combiner', true));
if(NiceMeleeWeapon(Inv) != none)
NiceMeleeWeapon(Inv).BloodyMaterial = default.BloodyMaterial;
}
static function bool UnloadAssets(){
if(super.UnloadAssets())
default.BloodyMaterial = none;
return true;
}
//simulated function IncrementFlashCount(int mode){
//}
simulated function BringUp(optional Weapon PrevWeapon){
if(BloodyMaterial!=none && Skins[BloodSkinSwitchArray] == BloodyMaterial ){
Skins[BloodSkinSwitchArray] = default.Skins[BloodSkinSwitchArray];
Texture = default.Texture;
}
super.BringUp(PrevWeapon);
}
simulated function Fire(float F){
}
simulated function AltFire(float F){
}
simulated function bool HasAmmo(){
return true;
}
defaultproperties
{
weaponRange=70.000000
BloodSkinSwitchArray=2
PutDownAnim="PutDown"
bMeleeWeapon=True
}

View file

@ -0,0 +1,123 @@
class NiceHighROFFire extends NiceFire;
// sound
var sound FireEndSound; // The sound to play at the end of the ambient fire sound
var sound FireEndStereoSound; // The sound to play at the end of the ambient fire sound in first person stereo
var float AmbientFireSoundRadius; // The sound radius for the ambient fire sound
var sound AmbientFireSound; // How loud to play the looping ambient fire sound
var byte AmbientFireVolume; // The ambient fire sound
var string FireEndSoundRef;
var string FireEndStereoSoundRef;
var string AmbientFireSoundRef;
//MEANTODO
/*
static function PreloadAssets(LevelInfo LevelInfo, optional KFFire Spawned){
super.PreloadAssets(LevelInfo, Spawned);
if(default.FireEndSound != none && default.FireEndSoundRef != "")
default.FireEndSound = sound(DynamicLoadObject(default.FireEndSoundRef, class'sound', true));
if(default.FireEndStereoSound == none){
if(default.FireEndStereoSoundRef != "")
default.FireEndStereoSound = sound(DynamicLoadObject(default.FireEndStereoSoundRef, class'Sound', true));
else
default.FireEndStereoSound = default.FireEndSound;
}
if(default.AmbientFireSoundRef != "")
default.AmbientFireSound = sound(DynamicLoadObject(default.AmbientFireSoundRef, class'sound', true));
if(NiceHighROFFire(Spawned) != none){
NiceHighROFFire(Spawned).FireEndSound = default.FireEndSound;
NiceHighROFFire(Spawned).FireEndStereoSound = default.FireEndStereoSound;
NiceHighROFFire(Spawned).AmbientFireSound = default.AmbientFireSound;
}
}
static function bool UnloadAssets(){
super.UnloadAssets();
default.FireEndSound = none;
default.FireEndStereoSound = none;
default.AmbientFireSound = none;
return true;
}
// Sends the fire class to the looping state
function StartFiring(){
if(!bWaitForRelease && !currentContext.bIsBursting)
GotoState('FireLoop');
else
Super.StartFiring();
}
// Handles toggling the weapon attachment's ambient sound on and off
function PlayAmbientSound(Sound aSound){
local WeaponAttachment WA;
WA = WeaponAttachment(Weapon.ThirdPersonActor);
if(Weapon == none || (WA == none))
return;
if(aSound == none){
WA.SoundVolume = WA.default.SoundVolume;
WA.SoundRadius = WA.default.SoundRadius;
}
else{
WA.SoundVolume = AmbientFireVolume;
WA.SoundRadius = AmbientFireSoundRadius;
}
WA.AmbientSound = aSound;
}
// Make sure we are in the fire looping state when we fire
event ModeDoFire(){
if(!bWaitForRelease && !currentContext.bIsBursting){
if(AllowFire() && IsInState('FireLoop'))
Super.ModeDoFire();
}
else
Super.ModeDoFire();
}
state FireLoop
{
function BeginState(){
NextFireTime = Level.TimeSeconds - 0.1;
if(KFWeap.bAimingRifle)
Weapon.LoopAnim(FireLoopAimedAnim, FireLoopAnimRate, TweenTime);
else
Weapon.LoopAnim(FireLoopAnim, FireLoopAnimRate, TweenTime);
PlayAmbientSound(AmbientFireSound);
}
function PlayFiring(){}
function ServerPlayFiring(){}
function EndState(){
Weapon.AnimStopLooping();
PlayAmbientSound(none);
if(Weapon.Instigator != none && Weapon.Instigator.IsLocallyControlled() &&
Weapon.Instigator.IsFirstPerson() && StereoFireSound != none)
Weapon.PlayOwnedSound(FireEndStereoSound,SLOT_none,AmbientFireVolume/127,,AmbientFireSoundRadius,,false);
else
Weapon.PlayOwnedSound(FireEndSound,SLOT_none,AmbientFireVolume/127,,AmbientFireSoundRadius);
Weapon.StopFire(ThisModeNum);
}
function StopFiring(){
GotoState('');
}
function ModeTick(float dt){
Super.ModeTick(dt);
if(!bIsFiring || !AllowFire()){
GotoState('');
return;
}
}
}
function PlayFireEnd(){
if(!bWaitForRelease)
Super.PlayFireEnd();
}*/
defaultproperties
{
AmbientFireSoundRadius=500.000000
AmbientFireVolume=255
FireAimedAnim="Fire_Iron"
FireEndAimedAnim="Fire_Iron_End"
FireLoopAimedAnim="Fire_Iron_Loop"
bAccuracyBonusForSemiAuto=True
bPawnRapidFireAnim=True
TransientSoundVolume=1.800000
FireLoopAnim="Fire_Loop"
FireEndAnim="Fire_End"
TweenTime=0.025000
FireForce="AssaultRifleFire"
BotRefireRate=0.100000
aimerror=30.000000
}

View file

@ -0,0 +1,441 @@
class NiceScopedWeapon extends NiceWeapon
abstract;
#exec OBJ LOAD FILE=ScopeShaders.utx
#exec OBJ LOAD FILE=..\Textures\NicePackT.utx
#exec OBJ LOAD FILE=ScrnWeaponPack_T.utx
#exec OBJ LOAD FILE=ScrnWeaponPack_A.ukx
var() Material ZoomMat;
var() Sound ZoomSound;
var() int lenseMaterialID; // used since material id's seem to change alot
var() float scopePortalFOVHigh; // The FOV to zoom the scope portal by.
var() float scopePortalFOV; // The FOV to zoom the scope portal by.
var() vector XoffsetScoped;
var() vector XoffsetHighDetail;
var() int tileSize;
// 3d Scope vars
var ScriptedTexture ScopeScriptedTexture; // Scripted texture for 3d scopes
var Shader ScopeScriptedShader; // The shader that combines the scripted texture with the sight overlay
var Material ScriptedTextureFallback; // The texture to render if the users system doesn't support shaders
// new scope vars
var Combiner ScriptedScopeCombiner;
var texture TexturedScopeTexture;
var bool bInitializedScope; // Set to true when the scope has been initialized
var string ZoomMatRef;
var string ScriptedTextureFallbackRef;
var texture CrosshairTex;
var string CrosshairTexRef;
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount){
local NiceScopedWeapon W;
super.PreloadAssets(Inv, bSkipRefCount);
if(default.ZoomMat == none && default.ZoomMatRef != ""){
// Try to load as various types of materials
default.ZoomMat = FinalBlend(DynamicLoadObject(default.ZoomMatRef, class'FinalBlend', true));
if(default.ZoomMat == none)
default.ZoomMat = Combiner(DynamicLoadObject(default.ZoomMatRef, class'Combiner', true));
if(default.ZoomMat == none)
default.ZoomMat = Shader(DynamicLoadObject(default.ZoomMatRef, class'Shader', true));
if(default.ZoomMat == none)
default.ZoomMat = Texture(DynamicLoadObject(default.ZoomMatRef, class'Texture', true));
if(default.ZoomMat == none)
default.ZoomMat = Material(DynamicLoadObject(default.ZoomMatRef, class'Material'));
}
if(default.ScriptedTextureFallback == none && default.ScriptedTextureFallbackRef != "")
default.ScriptedTextureFallback = texture(DynamicLoadObject(default.ScriptedTextureFallbackRef, class'texture'));
if(default.CrosshairTex == none && default.CrosshairTexRef != "")
default.CrosshairTex = Texture(DynamicLoadObject(default.CrosshairTexRef, class'texture'));
W = NiceScopedWeapon(Inv);
if(W != none){
W.ZoomMat = default.ZoomMat;
W.ScriptedTextureFallback = default.ScriptedTextureFallback;
W.CrosshairTex = default.CrosshairTex;
}
}
static function bool UnloadAssets(){
if(super.UnloadAssets()){
default.ZoomMat = none;
default.ScriptedTextureFallback = none;
default.CrosshairTex = none;
}
return true;
}
simulated function bool ShouldDrawPortal()
{
if(bAimingRifle)
return true;
else
return false;
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
// Get new scope detail value from KFWeapon
KFScopeDetail = class'KFMod.KFWeapon'.default.KFScopeDetail;
UpdateScopeMode();
}
// Handles initializing and swithing between different scope modes
simulated function UpdateScopeMode()
{
if (Level.NetMode != NM_DedicatedServer && Instigator != none && Instigator.IsLocallyControlled() && Instigator.IsHumanControlled()){
if(KFScopeDetail == KF_ModelScope){
scopePortalFOV = default.scopePortalFOV;
ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV);
if (bUsingSights || bAimingRifle)
PlayerViewOffset = XoffsetScoped;
if(ScopeScriptedTexture == none)
ScopeScriptedTexture = ScriptedTexture(Level.ObjectPool.AllocateObject(class'ScriptedTexture'));
ScopeScriptedTexture.FallBackMaterial = ScriptedTextureFallback;
ScopeScriptedTexture.SetSize(512,512);
ScopeScriptedTexture.Client = Self;
if(ScriptedScopeCombiner == none){
ScriptedScopeCombiner = Combiner(Level.ObjectPool.AllocateObject(class'Combiner'));
ScriptedScopeCombiner.Material1 = CrosshairTex;
ScriptedScopeCombiner.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader';
ScriptedScopeCombiner.CombineOperation = CO_Multiply;
ScriptedScopeCombiner.AlphaOperation = AO_Use_Mask;
ScriptedScopeCombiner.Material2 = ScopeScriptedTexture;
}
if(ScopeScriptedShader == none){
ScopeScriptedShader = Shader(Level.ObjectPool.AllocateObject(class'Shader'));
ScopeScriptedShader.Diffuse = ScriptedScopeCombiner;
ScopeScriptedShader.SelfIllumination = ScriptedScopeCombiner;
ScopeScriptedShader.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader';
}
bInitializedScope = true;
}
else if( KFScopeDetail == KF_ModelScopeHigh )
{
scopePortalFOV = scopePortalFOVHigh;
ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOVHigh);
if(bUsingSights || bAimingRifle)
PlayerViewOffset = XoffsetHighDetail;
if(ScopeScriptedTexture == none)
ScopeScriptedTexture = ScriptedTexture(Level.ObjectPool.AllocateObject(class'ScriptedTexture'));
ScopeScriptedTexture.FallBackMaterial = ScriptedTextureFallback;
ScopeScriptedTexture.SetSize(1024,1024);
ScopeScriptedTexture.Client = Self;
if(ScriptedScopeCombiner == none){
ScriptedScopeCombiner = Combiner(Level.ObjectPool.AllocateObject(class'Combiner'));
ScriptedScopeCombiner.Material1 = CrosshairTex;
ScriptedScopeCombiner.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader';
ScriptedScopeCombiner.CombineOperation = CO_Multiply;
ScriptedScopeCombiner.AlphaOperation = AO_Use_Mask;
ScriptedScopeCombiner.Material2 = ScopeScriptedTexture;
}
if(ScopeScriptedShader == none){
ScopeScriptedShader = Shader(Level.ObjectPool.AllocateObject(class'Shader'));
ScopeScriptedShader.Diffuse = ScriptedScopeCombiner;
ScopeScriptedShader.SelfIllumination = ScriptedScopeCombiner;
ScopeScriptedShader.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader';
}
bInitializedScope = true;
}
else if (KFScopeDetail == KF_TextureScope){
ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV);
PlayerViewOffset.X = default.PlayerViewOffset.X;
bInitializedScope = true;
}
}
}
simulated event RenderTexture(ScriptedTexture Tex)
{
local rotator RollMod;
RollMod = Instigator.GetViewRotation();
if(Owner != none && Instigator != none && Tex != none && Tex.Client != none)
Tex.DrawPortal(0,0,Tex.USize,Tex.VSize,Owner,(Instigator.Location + Instigator.EyePosition()), RollMod, scopePortalFOV );
}
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;
}
//Handles all the functionality for zooming in including
// setting the parameters for the weapon, pawn, and playercontroller
simulated function ZoomIn(bool bAnimateTransition)
{
default.ZoomTime = default.recordedZoomTime;
PlayerIronSightFOV = default.PlayerIronSightFOV;
scopePortalFOVHigh = default.scopePortalFOVHigh;
scopePortalFOV = default.scopePortalFOV;
PlayerIronSightFOV = default.PlayerIronSightFOV;
if(instigator != none && instigator.bIsCrouched && class'NiceVeterancyTypes'.static.hasSkill(NicePlayerController(Instigator.Controller), class'NiceSkillSharpshooterHardWork')){
default.ZoomTime *= class'NiceSkillSharpshooterHardWork'.default.zoomSpeedBonus;
if(instigator != none && instigator.bIsCrouched){
PlayerIronSightFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
scopePortalFOVHigh *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
scopePortalFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
PlayerIronSightFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
}
}
super(BaseKFWeapon).ZoomIn(bAnimateTransition);
bAimingRifle = True;
if(KFHumanPawn(Instigator) != none)
KFHumanPawn(Instigator).SetAiming(True);
if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ){
if(AimInSound != none)
PlayOwnedSound(AimInSound, SLOT_Interact,,,,, false);
}
}
// Handles all the functionality for zooming out including
// setting the parameters for the weapon, pawn, and playercontroller
simulated function ZoomOut(bool bAnimateTransition)
{
default.ZoomTime = default.recordedZoomTime;
PlayerIronSightFOV = default.PlayerIronSightFOV;
scopePortalFOVHigh = default.scopePortalFOVHigh;
scopePortalFOV = default.scopePortalFOV;
PlayerIronSightFOV = default.PlayerIronSightFOV;
if(class'NiceVeterancyTypes'.static.hasSkill(NicePlayerController(Instigator.Controller), class'NiceSkillSharpshooterHardWork')){
default.ZoomTime *= class'NiceSkillSharpshooterHardWork'.default.zoomSpeedBonus;
PlayerIronSightFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
scopePortalFOVHigh *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
scopePortalFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
PlayerIronSightFOV *= class'NiceSkillSharpshooterHardWork'.default.zoomBonus;
}
super.ZoomOut(bAnimateTransition);
bAimingRifle = False;
if( KFHumanPawn(Instigator)!=none )
KFHumanPawn(Instigator).SetAiming(False);
if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none )
{
if( AimOutSound != none )
{
PlayOwnedSound(AimOutSound, SLOT_Interact,,,,, false);
}
KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0);
}
}
simulated function WeaponTick(float dt)
{
super.WeaponTick(dt);
if(bAimingRifle && ForceZoomOutTime > 0 && Level.TimeSeconds - ForceZoomOutTime > 0)
{
ForceZoomOutTime = 0;
ZoomOut(false);
if(Role < ROLE_Authority)
ServerZoomOut(false);
}
}
// Called by the native code when the interpolation of the first person weapon to the zoomed position finishes
simulated event OnZoomInFinished()
{
local name anim;
local float frame, rate;
GetAnimParams(0, anim, frame, rate);
if (ClientState == WS_ReadyToFire)
{
// Play the iron idle anim when we're finished zooming in
if (anim == IdleAnim)
{
PlayIdle();
}
}
if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none &&
KFScopeDetail == KF_TextureScope )
{
KFPlayerController(Instigator.Controller).TransitionFOV(PlayerIronSightFOV,0.0);
}
}
simulated function bool CanZoomNow()
{
Return (!FireMode[0].bIsFiring && !FireMode[1].bIsFiring && Instigator!=none && Instigator.Physics!=PHYS_Falling);
}
simulated event RenderOverlays(Canvas Canvas)
{
local int m;
local PlayerController PC;
if (Instigator == none)
return;
PC = PlayerController(Instigator.Controller);
if(PC == none)
return;
if(!bInitializedScope && PC != none )
{
UpdateScopeMode();
}
Canvas.DrawActor(none, false, true);
for (m = 0; m < NUM_FIRE_MODES; m++)
{
if (FireMode[m] != none)
{
FireMode[m].DrawMuzzleFlash(Canvas);
}
}
SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self) );
SetRotation( Instigator.GetViewRotation() + ZoomRotInterp);
PreDrawFPWeapon();
if(bAimingRifle && PC != none && (KFScopeDetail == KF_ModelScope || KFScopeDetail == KF_ModelScopeHigh)){
if(ShouldDrawPortal()){
if(ScopeScriptedTexture != none){
Skins[LenseMaterialID] = ScopeScriptedShader;
ScopeScriptedTexture.Client = Self;
ScopeScriptedTexture.Revision = (ScopeScriptedTexture.Revision + 1);
}
}
bDrawingFirstPerson = true;
Canvas.DrawBoundActor(self, false, false,DisplayFOV,PC.Rotation,rot(0,0,0),Instigator.CalcZoomedDrawOffset(self));
bDrawingFirstPerson = false;
}
else if(KFScopeDetail == KF_TextureScope && PC.DesiredFOV == PlayerIronSightFOV && bAimingRifle){
Skins[LenseMaterialID] = ScriptedTextureFallback;
SetZoomBlendColor(Canvas);
Canvas.Style = ERenderStyle.STY_Normal;
Canvas.SetPos(0, 0);
Canvas.DrawTile(ZoomMat, (Canvas.SizeX - Canvas.SizeY) / 2, Canvas.SizeY, 0.0, 0.0, 8, 8);
Canvas.SetPos(Canvas.SizeX, 0);
Canvas.DrawTile(ZoomMat, -(Canvas.SizeX - Canvas.SizeY) / 2, Canvas.SizeY, 0.0, 0.0, 8, 8);
Canvas.Style = 255;
Canvas.SetPos((Canvas.SizeX - Canvas.SizeY) / 2,0);
Canvas.DrawTile(ZoomMat, Canvas.SizeY, Canvas.SizeY, 0.0, 0.0, tileSize, tileSize);
Canvas.Font = Canvas.MedFont;
Canvas.SetDrawColor(200,150,0);
Canvas.SetPos(Canvas.SizeX * 0.16, Canvas.SizeY * 0.43);
Canvas.DrawText(" ");
Canvas.SetPos(Canvas.SizeX * 0.16, Canvas.SizeY * 0.47);
}
else{
Skins[LenseMaterialID] = ScriptedTextureFallback;
bDrawingFirstPerson = true;
Canvas.DrawActor(self, false, false, DisplayFOV);
bDrawingFirstPerson = false;
}
}
// Adjust a single FOV based on the current aspect ratio. Adjust FOV is the default NON-aspect ratio adjusted FOV to adjust
simulated function float CalcAspectRatioAdjustedFOV(float AdjustFOV)
{
local KFPlayerController KFPC;
local float ResX, ResY;
local float AspectRatio;
KFPC = KFPlayerController(Level.GetLocalPlayerController());
if( KFPC == none )
{
return AdjustFOV;
}
ResX = float(GUIController(KFPC.Player.GUIController).ResX);
ResY = float(GUIController(KFPC.Player.GUIController).ResY);
AspectRatio = ResX / ResY;
if ( KFPC.bUseTrueWideScreenFOV && AspectRatio >= 1.60 ) //1.6 = 16/10 which is 16:10 ratio and 16:9 comes to 1.77
{
return CalcFOVForAspectRatio(AdjustFOV);
}
else
{
return AdjustFOV;
}
}
// AdjustIngameScope(RO) - Takes the changes to the ScopeDetail variable and
// sets the scope to the new detail mode. Called when the player switches the
// scope setting ingame, or when the scope setting is changed from the menu
simulated function AdjustIngameScope()
{
local PlayerController PC;
if(Instigator == none || PlayerController(Instigator.Controller) == none)
return;
PC = PlayerController(Instigator.Controller);
if(!bHasScope)
return;
switch (KFScopeDetail)
{
case KF_ModelScope:
if(bAimingRifle)
DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV);
if (PC.DesiredFOV == PlayerIronSightFOV && bAimingRifle){
if(Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none)
KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0);
}
break;
case KF_TextureScope:
if(bAimingRifle)
DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV);
if (bAimingRifle && PC.DesiredFOV != PlayerIronSightFOV){
if(Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none)
KFPlayerController(Instigator.Controller).TransitionFOV(PlayerIronSightFOV,0.0);
}
break;
case KF_ModelScopeHigh:
if(bAimingRifle){
if(default.ZoomedDisplayFOVHigh > 0)
DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOVHigh);
else
DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV);
}
if ( bAimingRifle && PC.DesiredFOV == PlayerIronSightFOV )
{
if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none )
{
KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0);
}
}
break;
}
// Make any chagned to the scope setup
UpdateScopeMode();
}
simulated event Destroyed()
{
PreTravelCleanUp();
Super.Destroyed();
}
simulated function PreTravelCleanUp()
{
if(ScopeScriptedTexture != none){
ScopeScriptedTexture.Client = none;
Level.ObjectPool.FreeObject(ScopeScriptedTexture);
ScopeScriptedTexture=none;
}
if(ScriptedScopeCombiner != none){
ScriptedScopeCombiner.Material2 = none;
Level.ObjectPool.FreeObject(ScriptedScopeCombiner);
ScriptedScopeCombiner = none;
}
if(ScopeScriptedShader != none){
ScopeScriptedShader.Diffuse = none;
ScopeScriptedShader.SelfIllumination = none;
Level.ObjectPool.FreeObject(ScopeScriptedShader);
ScopeScriptedShader = none;
}
}
defaultproperties
{
tileSize=1024
}

View file

@ -0,0 +1,466 @@
class NiceDualies extends NiceWeapon;
var class<NiceSingle> SingleClass;
var name altFlashBoneName;
var name altTPAnim;
var Actor altThirdPersonActor;
var name altWeaponAttach;
// Track ammo in each gun separately
var int MagAmmoRemLeft, MagAmmoRemLeftClient;
var int MagAmmoRemRight, MagAmmoRemRightClient;
// Variables for managing dual-pistols reload
var const string leftEjectStr, rightEjectStr; // Event names that trigger when magazines ejected
var const string leftInsertStr, rightInsertStr; // Event names that trigger when magazines inserted
var float leftEject, rightEject; // Frame at which magazines ejected
var float leftInsert, rightInsert; // Frame at which magazines inserted
// This weapon is currently switching and soon won't exist
var bool bSwitching;
replication{
reliable if(Role < ROLE_Authority)
ServerUpdateWeaponMag, ServerSetDualMagSize, ServerReduceDualMag, ServerSwitchToSingle, ServerSwitchToGivenSingle;
reliable if(Role == ROLE_Authority)
MagAmmoRemLeft, MagAmmoRemRight, ClientSetDualMagSize;
reliable if(bNetOwner && bNetDirty && (Role == ROLE_Authority))
altThirdPersonActor;
}
simulated function PostBeginPlay(){
super.PostBeginPlay();
SetupDualReloadEvents();
reloadPreEndFrame = FMin(leftEject, rightEject);
reloadEndFrame = FMax(leftInsert, rightInsert);
DemoReplacement = SingleClass;
}
simulated function SetupDualReloadEvents(){
local EventRecord record;
relEvents.Length = 0;
record.eventName = leftEjectStr;
record.eventFrame = leftEject;
relEvents[relEvents.Length] = record;
record.eventName = rightEjectStr;
record.eventFrame = rightEject;
relEvents[relEvents.Length] = record;
record.eventName = leftInsertStr;
record.eventFrame = leftInsert;
relEvents[relEvents.Length] = record;
record.eventName = rightInsertStr;
record.eventFrame = rightInsert;
relEvents[relEvents.Length] = record;
}
// Don't use that one for dualies
simulated function AddReloadedAmmo(){}
// Use this one
simulated function ReloadEvent(string eventName){
local int halfMag;
local int totalAvailableAmmo;
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
halfMag = GetSingleMagCapacity();
totalAvailableAmmo = AmmoAmount(0);
totalAvailableAmmo -= (MagAmmoRemLeftClient + MagAmmoRemRightClient);
// Handle ejection
if(eventName ~= leftEjectStr){
MagAmmoRemLeftClient = 0;
ServerSetDualMagSize(MagAmmoRemLeftClient, MagAmmoRemRightClient, Level.TimeSeconds);
NiceDualies(Instigator.Weapon).GetMagazineAmmo();
return;
}
else if(eventName ~= rightEjectStr){
MagAmmoRemRightClient = 0;
ServerSetDualMagSize(MagAmmoRemLeftClient, MagAmmoRemRightClient, Level.TimeSeconds);
NiceDualies(Instigator.Weapon).GetMagazineAmmo();
return;
}
// Handle reload
if(totalAvailableAmmo < 0)
return;
if(eventName ~= leftInsertStr){
MagAmmoRemLeftClient += totalAvailableAmmo;
MagAmmoRemLeftClient = Min(MagAmmoRemLeftClient, halfMag);
}
else if(eventName ~= rightInsertStr){
MagAmmoRemRightClient += totalAvailableAmmo;
MagAmmoRemRightClient = Min(MagAmmoRemRightClient, halfMag);
}
NiceDualies(Instigator.Weapon).GetMagazineAmmo();
ServerSetDualMagSize(MagAmmoRemLeftClient, MagAmmoRemRightClient, Level.TimeSeconds);
}
simulated function BringUp(optional Weapon PrevWeapon){
super.BringUp(PrevWeapon);
ApplyLaserState();
}
simulated function ApplyLaserState(){
super.ApplyLaserState();
if(NiceAttachment(altThirdPersonActor) != none)
NiceAttachment(altThirdPersonActor).SetLaserType(LaserType);
}
simulated function ZoomIn(bool bAnimateTransition){
super.ZoomIn(bAnimateTransition);
if(bAnimateTransition){
if(bZoomOutInterrupted)
PlayAnim('GOTO_Iron',1.0,0.1);
else
PlayAnim('GOTO_Iron',1.0,0.1);
}
}
simulated function ZoomOut(bool bAnimateTransition){
local float AnimLength, AnimSpeed;
super.ZoomOut(false);
if(bAnimateTransition){
AnimLength = GetAnimDuration('GOTO_Hip', 1.0);
if(ZoomTime > 0 && AnimLength > 0)
AnimSpeed = AnimLength/ZoomTime;
else
AnimSpeed = 1.0;
PlayAnim('GOTO_Hip',AnimSpeed,0.1);
}
}
function AttachToPawn(Pawn P){
local name BoneName;
Super.AttachToPawn(P);
if(altThirdPersonActor == none){
altThirdPersonActor = Spawn(AttachmentClass, Owner);
InventoryAttachment(altThirdPersonActor).InitFor(self);
}
else
altThirdPersonActor.NetUpdateTime = Level.TimeSeconds - 1;
BoneName = P.GetOffhandBoneFor(self);
if(BoneName == ''){
altThirdPersonActor.SetLocation(P.Location);
altThirdPersonActor.SetBase(P);
}
else
P.AttachToBone(altThirdPersonActor, BoneName);
if(altThirdPersonActor != none)
NiceDualiesAttachment(altThirdPersonActor).bIsOffHand = true;
if(altThirdPersonActor != none && ThirdPersonActor != none){
NiceDualiesAttachment(altThirdPersonActor).brother = NiceDualiesAttachment(ThirdPersonActor);
NiceDualiesAttachment(ThirdPersonActor).brother = NiceDualiesAttachment(altThirdPersonActor);
altThirdPersonActor.LinkMesh(NiceDualiesAttachment(ThirdPersonActor).BrotherMesh);
}
}
simulated function DetachFromPawn(Pawn P){
super.DetachFromPawn(P);
if(altThirdPersonActor != none){
altThirdPersonActor.Destroy();
altThirdPersonActor = none;
}
}
simulated function Destroyed(){
super.Destroyed();
if(ThirdPersonActor != none)
ThirdPersonActor.Destroy();
if(altThirdPersonActor != none)
altThirdPersonActor.Destroy();
}
simulated function vector GetEffectStart(){
local Vector RightFlashLoc,LeftFlashLoc;
RightFlashLoc = GetBoneCoords(default.FlashBoneName).Origin;
LeftFlashLoc = GetBoneCoords(default.altFlashBoneName).Origin;
if(Instigator.IsFirstPerson()){
if(WeaponCentered())
return CenteredEffectStart();
if(bAimingRifle){
if(KFFire(GetFireMode(0)).FireAimedAnim != 'FireLeft_Iron')
return RightFlashLoc;
else
return LeftFlashLoc;
}
else{
if(GetFireMode(0).FireAnim != 'FireLeft')
return RightFlashLoc;
else
return LeftFlashLoc;
}
}
else{
return (Instigator.Location + Instigator.EyeHeight * Vect(0, 0, 0.5) + vector(Instigator.Rotation) * 40.0);
}
}
function NicePlainData.Data GetNiceData(){
local NicePlainData.Data transferData;
transferData = super.GetNiceData();
class'NicePlainData'.static.SetInt(transferData, "leftMag", MagAmmoRemLeft);
class'NicePlainData'.static.SetInt(transferData, "rightMag", MagAmmoRemRight);
return transferData;
}
function SetNiceData(NicePlainData.Data transferData, optional NiceHumanPawn newOwner){
local int halfMag;
super.SetNiceData(transferData, newOwner);
if(newOwner != none)
UpdateMagCapacity(newOwner.PlayerReplicationInfo);
halfMag = GetSingleMagCapacity();
MagAmmoRemLeft = class'NicePlainData'.static.GetInt(transferData, "leftMag", halfMag);
MagAmmoRemRight = class'NicePlainData'.static.GetInt(transferData, "rightMag", halfMag);
ClientSetDualMagSize(MagAmmoRemLeft, MagAmmoRemRight);
}
simulated function AltFire(float F){
if(NicePlayerController(Instigator.Controller) != none)
ClientForceInterruptReload(CANCEL_PASSIVESWITCH);
if(!bIsReloading)
ServerSwitchToSingle();
}
simulated function FireGivenGun(bool bFireLeft){
local NiceDualiesFire niceFireMode;
niceFireMode = NiceDualiesFire(FireMode[0]);
if(niceFireMode != none){
if(bFireLeft)
niceFireMode.ModeDoFireLeft();
else
niceFireMode.ModeDoFireRight();
}
}
function NiceSingle ServerSwitchToGivenSingle(bool bSwitchToLeft){
local int m;
local int origAmmo;
local NiceHumanPawn nicePawn;
local NiceSingle singlePistol;
local NicePlainData.Data transferData;
nicePawn = NiceHumanPawn(Instigator);
if(nicePawn == none || SingleClass == none || nicePawn.Health <= 0)
return none;
nicePawn.CurrentWeight -= Weight;
Weight = 0;
bSwitching = true;
origAmmo = AmmoAmount(0);
for(m = 0; m < NUM_FIRE_MODES;m ++)
if(FireMode[m].bIsFiring)
StopFire(m);
DetachFromPawn(nicePawn);
singlePistol = nicePawn.Spawn(SingleClass);
if(singlePistol != none){
singlePistol.Weight = default.Weight;
singlePistol.DemoReplacement = DemoReplacement;
transferData = GetNiceData();
singlePistol.GiveTo(nicePawn);
singlePistol.SetNiceData(transferData, nicePawn);
singlePistol.bIsDual = true;
singlePistol.Weight = default.Weight;
singlePistol.SellValue = SellValue;
if(bSwitchToLeft){
singlePistol.otherMagazine = MagAmmoRemRight;
singlePistol.MagAmmoRemaining = MagAmmoRemLeft;
singlePistol.Ammo[0].AmmoAmount = origAmmo - MagAmmoRemRight;
}
else{
singlePistol.otherMagazine = MagAmmoRemLeft;
singlePistol.MagAmmoRemaining = MagAmmoRemRight;
singlePistol.Ammo[0].AmmoAmount = origAmmo - MagAmmoRemLeft;
}
singlePistol.ClientSetMagSize(singlePistol.MagAmmoRemaining, false);
//nicePawn.ServerChangedWeapon(self, singlePistol);
//nicePawn.ClientChangeWeapon(singlePistol);
}
Destroy();
return singlePistol;
}
function NiceSingle ServerSwitchToSingle(){
return ServerSwitchToGivenSingle(MagAmmoRemLeft > MagAmmoRemRight);
}
function DropFrom(vector StartLocation){
local int m;
local int magKeep, magGive;
local NiceHumanPawn nicePawn;
local KFWeaponPickup weapPickup;
local NiceSingle singlePistol;
local int AmmoThrown, OtherAmmo;
nicePawn = NiceHumanPawn(Instigator);
if(nicePawn == none || !bCanThrow || SingleClass == none)
return;
nicePawn.CurrentWeight -= Weight;
Weight = 0;
bSwitching = true;
if(MagAmmoRemLeft > MagAmmoRemRight){
magKeep = MagAmmoRemLeft;
magGive = MagAmmoRemRight;
}
else{
magKeep = MagAmmoRemRight;
magGive = MagAmmoRemLeft;
}
OtherAmmo = AmmoAmount(0);
ClientWeaponThrown();
for(m = 0; m < NUM_FIRE_MODES;m ++)
if(FireMode[m].bIsFiring)
StopFire(m);
DetachFromPawn(nicePawn);
AmmoThrown = magGive;
OtherAmmo = OtherAmmo - AmmoThrown;
singlePistol = nicePawn.Spawn(SingleClass);
if(singlePistol != none){
singlePistol.DemoReplacement = none;
singlePistol.GiveTo(nicePawn);
singlePistol.Ammo[0].AmmoAmount = OtherAmmo;
singlePistol.MagAmmoRemaining = magKeep;
singlePistol.ClientSetMagSize(singlePistol.MagAmmoRemaining, false);
MagAmmoRemaining = magGive;
//nicePawn.ServerChangedWeapon(self, singlePistol);
//nicePawn.ClientChangeWeapon(singlePistol);
}
weapPickup = KFWeaponPickup(nicePawn.Spawn(SingleClass.default.PickupClass,,, StartLocation));
if(weapPickup != none){
weapPickup.InitDroppedPickupFor(self);
weapPickup.Weight = default.Weight;
weapPickup.Velocity = Velocity;
weapPickup.AmmoAmount[0] = AmmoThrown;
weapPickup.SellValue = SellValue / 2;
singlePistol.SellValue = weapPickup.SellValue;
weapPickup.MagAmmoRemaining = magGive;
if(nicePawn.Health > 0)
weapPickup.bThrown = true;
}
Destroy();
if(KFGameType(Level.Game) != none)
KFGameType(Level.Game).WeaponDestroyed(class);
}
function bool HandlePickupQuery(pickup Item){
if(Item.InventoryType == SingleClass){
if(LastHasGunMsgTime < Level.TimeSeconds && PlayerController(Instigator.Controller) != none){
LastHasGunMsgTime = Level.TimeSeconds + 0.5;
PlayerController(Instigator.Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 1);
}
return true;
}
return super.HandlePickupQuery(Item);
}
// Nice functions
simulated function int GetSingleMagCapacity(){
return int(float(MagCapacity) * 0.5);
}
function UpdateWeaponMag(){
ServerUpdateWeaponMag();
}
function ServerUpdateWeaponMag(){
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
MagAmmoRemLeft = Min(MagAmmoRemLeft, GetSingleMagCapacity());
MagAmmoRemRight = Min(MagAmmoRemRight, GetSingleMagCapacity());
ClientSetDualMagSize(MagAmmoRemLeft, MagAmmoRemRight);
}
simulated function ClientUpdateWeaponMag(){
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
MagAmmoRemLeftClient = Min(MagAmmoRemLeftClient, GetSingleMagCapacity());
MagAmmoRemRightClient = Min(MagAmmoRemRightClient, GetSingleMagCapacity());
ServerSetDualMagSize(MagAmmoRemLeftClient, MagAmmoRemRightClient, Level.TimeSeconds);
}
// Forces update for client's magazine ammo counter
// In case we are using client-side hit-detection, client itself manages remaining ammunition in magazine, but in some cases we want server to dictate current magazine amount
// This function sets client's mag size to a given value
simulated function ClientSetDualMagSize(int newLeftMag, int newRightMag){
MagAmmoRemLeftClient = newLeftMag;
MagAmmoRemRightClient = newRightMag;
MagAmmoRemainingClient = MagAmmoRemLeftClient + MagAmmoRemRightClient;
}
// This function allows clients to change magazine size without altering total ammo amount
// It allows clients to provide time-stamps, so that older change won't override a newer one
function ServerSetDualMagSize(int newLeftMag, int newRightMag, float updateTime){
MagAmmoRemLeft = newLeftMag;
MagAmmoRemRight = newRightMag;
magAmmoRemaining = MagAmmoRemLeft + MagAmmoRemRight;
if(LastMagUpdateFromClient <= updateTime){
LastMagUpdateFromClient = updateTime;
if(magAmmoRemaining > 0)
bServerFiredLastShot = false;
}
}
// This function allows clients to change magazine size along with total ammo amount on the server (to update ammo counter in client-side mode)
// It allows clients to provide time-stamps, so that older change won't override a newer one
// Intended to be used for decreasing ammo count from shooting and cannot increase magazine size
function ServerReduceDualMag(int newLeftMag, int newRightMag, float updateTime, int Mode){
local int delta;
delta = MagAmmoRemLeft - newLeftMag;
delta += MagAmmoRemRight - newRightMag;
// Only update later changes that actually decrease magazine
if(LastMagUpdateFromClient <= updateTime && delta > 0){
LastMagUpdateFromClient = updateTime;
MagAmmoRemLeft = newLeftMag;
MagAmmoRemRight = newRightMag;
ConsumeAmmo(Mode, delta);
MagAmmoRemaining = MagAmmoRemLeft + MagAmmoRemRight;
}
}
simulated function int GetMagazineAmmoLeft(){
if(Role < ROLE_Authority)
return MagAmmoRemLeftClient;
else
return MagAmmoRemLeft;
}
simulated function int GetMagazineAmmoRight(){
if(Role < ROLE_Authority)
return MagAmmoRemRightClient;
else
return MagAmmoRemRight;
}
simulated function bool AllowReload(){
UpdateMagCapacity(Instigator.PlayerReplicationInfo);
if(FireMode[0].IsFiring() ||
bIsReloading || (GetMagazineAmmoLeft() >= GetSingleMagCapacity() && GetMagazineAmmoRight() >= GetSingleMagCapacity()) ||
ClientState == WS_BringUp ||
AmmoAmount(0) <= GetMagazineAmmo())
return false;
return true;
}
simulated function WeaponTick(float dt){
if(Role == Role_AUTHORITY)
MagAmmoRemaining = MagAmmoRemLeft + MagAmmoRemRight;
else
MagAmmoRemainingClient = MagAmmoRemLeftClient + MagAmmoRemRightClient;
super.WeaponTick(dt);
}
// Some functions reloaded to force update of magazine size on client's side
function GiveAmmo(int m, WeaponPickup WP, bool bJustSpawned){
super.GiveAmmo(m, WP, bJustSpawned);
ClientSetDualMagSize(MagAmmoRemLeft, MagAmmoRemRight);
}
defaultproperties
{
SingleClass=Class'NicePack.NiceSingle'
altFlashBoneName="Tip_Left"
altTPAnim="DualiesAttackLeft"
altWeaponAttach="Bone_weapon2"
leftEjectStr="LEFT_EJECT"
rightEjectStr="RIGHT_EJECT"
leftInsertStr="LEFT_INSERT"
rightInsertStr="RIGHT_INSERT"
leftEject=0.130000
rightEject=0.102000
leftInsert=0.444000
rightInsert=0.787000
reloadChargeEndFrame=-1.000000
reloadMagStartFrame=-1.000000
reloadChargeStartFrame=-1.000000
MagazineBone=
bHasChargePhase=False
FirstPersonFlashlightOffset=(X=-15.000000,Z=5.000000)
MagCapacity=30
ReloadRate=3.500000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
FlashBoneName="Tip_Right"
WeaponReloadAnim="Reload_Dual9mm"
Weight=4.000000
bDualWeapon=True
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=70.000000
TraderInfoTexture=Texture'KillingFloorHUD.Trader_Weapon_Images.Trader_Dual_9mm'
ZoomInRotation=(Pitch=0,Roll=0)
ZoomedDisplayFOV=65.000000
FireModeClass(0)=Class'NicePack.NiceDualiesFire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
AIRating=0.440000
CurrentRating=0.440000
bShowChargingBar=True
Description="A pair of custom 9mm pistols. What they lack in stopping power, they compensate for with a quick refire."
EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
DisplayFOV=70.000000
Priority=65
InventoryGroup=2
GroupOffset=2
PickupClass=Class'NicePack.NiceDualiesPickup'
PlayerViewOffset=(X=20.000000,Z=-7.000000)
BobDamping=7.000000
AttachmentClass=Class'NicePack.NiceDualiesAttachment'
IconCoords=(X1=229,Y1=258,X2=296,Y2=307)
ItemName="!!!Dual something"
DrawScale=0.900000
TransientSoundVolume=1.000000
}

View file

@ -0,0 +1,13 @@
class NiceDualiesAmmo extends NiceAmmo;
#EXEC OBJ LOAD FILE=InterfaceContent.utx
defaultproperties
{
AmmoPickupAmount=30
MaxAmmo=480
InitialAmount=240
PickupClass=Class'NicePack.NiceDualiesAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=413,Y1=82,X2=457,Y2=125)
ItemName="Dualies bullets"
}

View file

@ -0,0 +1,9 @@
class NiceDualiesAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=Class'NicePack.NiceDualiesAmmo'
PickupMessage="Rounds (9mm)"
StaticMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
}

View file

@ -0,0 +1,128 @@
class NiceDualiesAttachment extends NiceAttachment;
var bool bIsOffHand, bMyFlashTurn;
var NiceDualiesAttachment brother;
var Mesh BrotherMesh;
replication{
reliable if(Role == ROLE_Authority)
brother;
}
simulated function DoFlashEmitter(){
if(bIsOffHand)
return;
if(bMyFlashTurn)
ActuallyFlash();
else if(brother != none)
brother.ActuallyFlash();
}
simulated function ActuallyFlash(){
super.DoFlashEmitter();
}
simulated event ThirdPersonEffects(){
local NicePlayerController PC;
if((Level.NetMode == NM_DedicatedServer) || (Instigator == none))
return;
PC = NicePlayerController(Level.GetLocalPlayerController());
if(FiringMode == 0){
if(OldSpawnHitCount != SpawnHitCount){
OldSpawnHitCount = SpawnHitCount;
GetHitInfo();
if(((Instigator != none) && (Instigator.Controller == PC)) || (VSize(PC.ViewTarget.Location - mHitLocation) < 4000)){
if(PC != Instigator.Controller){
if(mHitActor != none)
Spawn(class'ROBulletHitEffect',,, mHitLocation, Rotator(-mHitNormal));
CheckForSplash();
SpawnTracer();
}
}
}
}
if(FlashCount > 0){
if(KFPawn(Instigator) != none){
if(bMyFlashTurn)
KFPawn(Instigator).StartFiringX(false, bRapidFire);
else
KFPawn(Instigator).StartFiringX(true, bRapidFire);
}
if(bDoFiringEffects){
if((Level.TimeSeconds - LastRenderTime > 0.2) && (Instigator.Controller != PC))
return;
if(bSpawnLight)
WeaponLight();
DoFlashEmitter();
if(!bIsOffHand){
if(!bMyFlashTurn)
ThirdPersonShellEject();
else if(brother != none)
brother.ThirdPersonShellEject();
}
}
}
else{
GotoState('');
if(KFPawn(Instigator) != none)
KFPawn(Instigator).StopFiring();
}
}
simulated function vector GetTracerStart(){
local Pawn p;
p = Pawn(Owner);
if((p != none) && p.IsFirstPerson() && p.Weapon != none)
return p.Weapon.GetEffectStart();
if(mMuzFlash3rd != none && bMyFlashTurn)
return mMuzFlash3rd.Location;
else if(brother != none && brother.mMuzFlash3rd != none && !bMyFlashTurn)
return brother.mMuzFlash3rd.Location;
}
defaultproperties
{
bMyFlashTurn=True
BrotherMesh=SkeletalMesh'KF_Weapons3rd_Trip.Dual9mm_3rd'
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdPistol'
mTracerClass=Class'KFMod.KFNewTracer'
mShellCaseEmitterClass=Class'KFMod.KFShellSpewer'
MovementAnims(0)="JogF_Dual9mm"
MovementAnims(1)="JogB_Dual9mm"
MovementAnims(2)="JogL_Dual9mm"
MovementAnims(3)="JogR_Dual9mm"
TurnLeftAnim="TurnL_Dual9mm"
TurnRightAnim="TurnR_Dual9mm"
CrouchAnims(0)="CHwalkF_Dual9mm"
CrouchAnims(1)="CHwalkB_Dual9mm"
CrouchAnims(2)="CHwalkL_Dual9mm"
CrouchAnims(3)="CHwalkR_Dual9mm"
WalkAnims(0)="WalkF_Dual9mm"
WalkAnims(1)="WalkB_Dual9mm"
WalkAnims(2)="WalkL_Dual9mm"
WalkAnims(3)="WalkR_Dual9mm"
CrouchTurnRightAnim="CH_TurnR_Dual9mm"
CrouchTurnLeftAnim="CH_TurnL_Dual9mm"
IdleCrouchAnim="CHIdle_Dual9mm"
IdleWeaponAnim="Idle_Dual9mm"
IdleRestAnim="Idle_Dual9mm"
IdleChatAnim="Idle_Dual9mm"
IdleHeavyAnim="Idle_Dual9mm"
IdleRifleAnim="Idle_Dual9mm"
FireAnims(0)="DualiesAttackRight"
FireAnims(1)="DualiesAttackRight"
FireAnims(2)="DualiesAttackRight"
FireAnims(3)="DualiesAttackRight"
FireAltAnims(0)="DualiesAttackLeft"
FireAltAnims(1)="DualiesAttackLeft"
FireAltAnims(2)="DualiesAttackLeft"
FireAltAnims(3)="DualiesAttackLeft"
FireCrouchAnims(0)="CHDualiesAttackRight"
FireCrouchAnims(1)="CHDualiesAttackRight"
FireCrouchAnims(2)="CHDualiesAttackRight"
FireCrouchAnims(3)="CHDualiesAttackRight"
FireCrouchAltAnims(0)="CHDualiesAttackLeft"
FireCrouchAltAnims(1)="CHDualiesAttackLeft"
FireCrouchAltAnims(2)="CHDualiesAttackLeft"
FireCrouchAltAnims(3)="CHDualiesAttackLeft"
HitAnims(0)="HitF_Dual9mmm"
HitAnims(1)="HitB_Dual9mm"
HitAnims(2)="HitL_Dual9mm"
HitAnims(3)="HitR_Dual9mm"
PostFireBlendStandAnim="Blend_Dual9mm"
PostFireBlendCrouchAnim="CHBlend_Dual9mm"
}

View file

@ -0,0 +1,247 @@
class NiceDualiesFire extends NiceFire;
var bool bWasInZedTime;
var Emitter Flash2Emitter;
var Emitter ShellEject2Emitter;
var name ShellEject2BoneName;
var name FireAnim2, FireAimedAnim2;
var bool bIsLeftShot;
var float leftNextFireTime;
var float rightNextFireTime;
var bool bLastFiredLeft;
simulated function ModeTick(float delta){
local float timeCutScale;
local NicePlayerController nicePlayer;
if(instigator != none)
nicePlayer = NicePlayerController(instigator.controller);
if(nicePlayer != none && nicePlayer.IsZedTimeActive() != bWasInZedTime){
bWasInZedTime = !bWasInZedTime;
timeCutScale = 1.0;
if(bWasInZedTime)
timeCutScale = KFGameType(Level.Game).ZedTimeSlomoScale;
niceNextFireTime = Level.TimeSeconds + (niceNextFireTime - Level.TimeSeconds) * timeCutScale;
nextFireTime = niceNextFireTime;
leftNextFireTime = Level.TimeSeconds + (leftNextFireTime - Level.TimeSeconds) * timeCutScale;
rightNextFireTime = Level.TimeSeconds + (rightNextFireTime - Level.TimeSeconds) * timeCutScale;
}
super.ModeTick(delta);
}
simulated function InitEffects(){
local NiceDualies dualWeapon;
dualWeapon = NiceDualies(Weapon);
if((Level.NetMode == NM_DedicatedServer) || (AIController(Instigator.Controller) != none) || dualWeapon == none)
return;
if((FlashEmitterClass != none) && ((FlashEmitter == none) || FlashEmitter.bDeleteMe)){
FlashEmitter = Weapon.Spawn(FlashEmitterClass);
Weapon.AttachToBone(FlashEmitter, dualWeapon.default.FlashBoneName);
}
if((FlashEmitterClass != none) && ((Flash2Emitter == none) || Flash2Emitter.bDeleteMe)){
Flash2Emitter = Weapon.Spawn(FlashEmitterClass);
Weapon.AttachToBone(Flash2Emitter, dualWeapon.default.altFlashBoneName);
}
if((SmokeEmitterClass != none) && ((SmokeEmitter == none) || SmokeEmitter.bDeleteMe))
SmokeEmitter = Weapon.Spawn(SmokeEmitterClass);
if((ShellEjectClass != none) && ((ShellEjectEmitter == none) || ShellEjectEmitter.bDeleteMe)){
ShellEjectEmitter = Weapon.Spawn(ShellEjectClass);
Weapon.AttachToBone(ShellEjectEmitter, ShellEjectBoneName);
}
if((ShellEjectClass != none) && ((ShellEject2Emitter == none) || ShellEject2Emitter.bDeleteMe)){
ShellEject2Emitter = Weapon.Spawn(ShellEjectClass);
Weapon.AttachToBone(ShellEject2Emitter, ShellEject2BoneName);
}
}
simulated function DestroyEffects(){
super.DestroyEffects();
if(ShellEject2Emitter != none)
ShellEject2Emitter.Destroy();
if(Flash2Emitter != none)
Flash2Emitter.Destroy();
}
function DrawMuzzleFlash(Canvas Canvas){
super.DrawMuzzleFlash(Canvas);
if(ShellEject2Emitter != none)
Canvas.DrawActor( ShellEject2Emitter, false, false, Weapon.DisplayFOV );
}
function FlashMuzzleFlash(){
if(Flash2Emitter == none || FlashEmitter == none)
return;
if(KFWeap.bAimingRifle){
if(FireAimedAnim == 'FireLeft_Iron'){
Flash2Emitter.Trigger(Weapon, Instigator);
if(ShellEjectEmitter != none)
ShellEjectEmitter.Trigger(Weapon, Instigator);
}
else{
FlashEmitter.Trigger(Weapon, Instigator);
if(ShellEject2Emitter != none)
ShellEject2Emitter.Trigger(Weapon, Instigator);
}
}
else{
if(FireAnim == 'FireLeft'){
Flash2Emitter.Trigger(Weapon, Instigator);
if(ShellEjectEmitter != none)
ShellEjectEmitter.Trigger(Weapon, Instigator);
}
else{
FlashEmitter.Trigger(Weapon, Instigator);
if(ShellEject2Emitter != none)
ShellEject2Emitter.Trigger(Weapon, Instigator);
}
}
}
simulated function ModeDoFireLeft(){
local NiceDualies dualWeapon;
local NiceDualiesAttachment dualAttach, dualAttachAlt;
dualWeapon = NiceDualies(Weapon);
dualAttach = NiceDualiesAttachment(dualWeapon.ThirdPersonActor);
dualAttachAlt = NiceDualiesAttachment(dualWeapon.altThirdPersonActor);
if(dualWeapon == none || !AllowLeftFire())
return;
// Set shine turn
if(dualAttach != none)
dualAttach.bMyFlashTurn = false;
if(dualAttachAlt != none)
dualAttachAlt.bMyFlashTurn = true;
// Swap bones and animations
dualWeapon.FlashBoneName = dualWeapon.default.altFlashBoneName;
dualWeapon.altFlashBoneName = dualWeapon.default.FlashBoneName;
FireAnim = default.FireAnim2;
FireAnim2 = default.FireAnim;
FireAimedAnim = default.FireAimedAnim2;
FireAimedAnim2 = default.FireAimedAnim;
// Do left shot
bIsLeftShot = true;
super.ModeDoFire();
leftNextFireTime = UpdateNextFireTimeSingle(leftNextFireTime);
InitEffects();
bLastFiredLeft = true;
}
simulated function ModeDoFireRight(){
local NiceDualies dualWeapon;
local NiceDualiesAttachment dualAttach, dualAttachAlt;
dualWeapon = NiceDualies(Weapon);
dualAttach = NiceDualiesAttachment(dualWeapon.ThirdPersonActor);
dualAttachAlt = NiceDualiesAttachment(dualWeapon.altThirdPersonActor);
if(dualWeapon == none || !AllowRightFire())
return;
// Set shine turn
if(dualAttach != none)
dualAttach.bMyFlashTurn = true;
if(dualAttachAlt != none)
dualAttachAlt.bMyFlashTurn = false;
// Default bones and animations
dualWeapon.FlashBoneName = dualWeapon.default.FlashBoneName;
dualWeapon.altFlashBoneName = dualWeapon.default.altFlashBoneName;
FireAnim = default.FireAnim;
FireAnim2 = default.FireAnim2;
FireAimedAnim = default.FireAimedAnim;
FireAimedAnim2 = default.FireAimedAnim2;
// Do right shot
bIsLeftShot = false;
super.ModeDoFire();
rightNextFireTime = UpdateNextFireTimeSingle(rightNextFireTime);
InitEffects();
bLastFiredLeft = false;
}
simulated function bool AllowLeftFire(){
local NiceDualies niceDualWeap;
niceDualWeap = NiceDualies(currentContext.sourceWeapon);
if(niceDualWeap == none)
return false;
if(niceDualWeap.GetMagazineAmmoLeft() < default.AmmoPerFire && !bCanFireIncomplete)
return false;
return true;
}
simulated function bool AllowRightFire(){
local NiceDualies niceDualWeap;
niceDualWeap = NiceDualies(currentContext.sourceWeapon);
if(niceDualWeap == none)
return false;
if(niceDualWeap.GetMagazineAmmoRight() < default.AmmoPerFire && !bCanFireIncomplete)
return false;
return true;
}
simulated function bool AllowFire(){
return super.AllowFire() && (AllowLeftFire() || AllowRightFire());
}
event ModeDoFire(){
local NiceDualies dualWeap;
dualWeap = NiceDualies(Instigator.Weapon);
if(dualWeap == none || niceNextFireTime > Level.TimeSeconds || !AllowFire())
return;
if(niceNextFireTime + FireRate < Level.TimeSeconds)
bResetRecoil = true;
// Choose correct pistol to fire
if(Level.TimeSeconds > leftNextFireTime && Level.TimeSeconds > rightNextFireTime && AllowLeftFire() && AllowRightFire()){
if(dualWeap.GetMagazineAmmoLeft() > dualWeap.GetMagazineAmmoRight())
ModeDoFireLeft();
else if(dualWeap.GetMagazineAmmoLeft() < dualWeap.GetMagazineAmmoRight())
ModeDoFireRight();
else if(bLastFiredLeft)
ModeDoFireRight();
else
ModeDoFireLeft();
}
else if(Level.TimeSeconds > leftNextFireTime && AllowLeftFire())
ModeDoFireLeft();
else if(Level.TimeSeconds > rightNextFireTime && AllowRightFire())
ModeDoFireRight();
}
simulated function ReduceAmmoClient(){
local NiceDualies dualWeap;
dualWeap = NiceDualies(currentContext.sourceWeapon);
if(dualWeap == none)
return;
if(bIsLeftShot)
dualWeap.MagAmmoRemLeftClient -= Load;
else
dualWeap.MagAmmoRemRightClient -= Load;
if(dualWeap.MagAmmoRemLeftClient < 0)
dualWeap.MagAmmoRemLeftClient = 0;
if(dualWeap.MagAmmoRemRightClient < 0)
dualWeap.MagAmmoRemRightClient = 0;
// Force server's magazine size
dualWeap.ServerReduceDualMag(dualWeap.MagAmmoRemLeftClient, dualWeap.MagAmmoRemRightClient, Level.TimeSeconds, ThisModeNum);
}
simulated function float UpdateNextFireTimeSingle(float fireTimeVar){
FireRate *= 2;
fireTimeVar = UpdateNextFireTime(fireTimeVar);
FireRate = default.FireRate;
return fireTimeVar;
}
defaultproperties
{
ShellEject2BoneName="Shell_eject_right"
FireAnim2="FireLeft"
FireAimedAnim2="FireLeft_Iron"
FireAimedAnim="FireRight_Iron"
RecoilRate=0.070000
maxVerticalRecoilAngle=450
maxHorizontalRecoilAngle=50
ShellEjectClass=Class'ROEffects.KFShellEject9mm'
ShellEjectBoneName="Shell_eject_left"
DamageMin=35
DamageMax=35
Momentum=10500.000000
bPawnRapidFireAnim=True
bWaitForRelease=True
bAttachSmokeEmitter=True
TransientSoundVolume=1.800000
FireAnim="FireRight"
FireLoopAnim=
FireEndAnim=
TweenTime=0.025000
FireForce="AssaultRifleFire"
FireRate=0.087500
AmmoClass=Class'NicePack.NiceSingleAmmo'
ShakeRotMag=(X=75.000000,Y=75.000000,Z=250.000000)
ShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
ShakeRotTime=3.000000
ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=10.000000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=2.000000
BotRefireRate=0.250000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stMP'
aimerror=30.000000
}

View file

@ -0,0 +1,38 @@
class NiceDualiesPickup extends NiceWeaponPickup;
var int MagAmmoRemLeft;
var int MagAmmoRemRight;
function ShowDualiesInfo(Canvas C){
C.SetPos((C.SizeX - C.SizeY) / 2,0);
C.DrawTile( Texture'KillingfloorHUD.ClassMenu.Dualies', C.SizeY, C.SizeY, 0.0, 0.0, 256, 256);
}
function InitDroppedPickupFor(Inventory Inv){
local NiceDualies dualW;
super.InitDroppedPickupFor(Inv);
dualW = NiceDualies(Inv);
if(dualW != none){
MagAmmoRemLeft = dualW.MagAmmoRemLeft;
MagAmmoRemRight = dualW.MagAmmoRemRight;
}
}
defaultproperties
{
Weight=1.000000
cost=150
BuyClipSize=30
PowerValue=35
SpeedValue=85
RangeValue=35
Description="A pair of custom 9mm handguns."
ItemName="Dual 9mms"
ItemShortName="Dual 9mms"
AmmoItemName="9mm Rounds"
AmmoMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
CorrespondingPerkIndex=2
EquipmentCategoryID=1
InventoryType=Class'NicePack.NiceDualies'
PickupMessage="You found another 9mm handgun"
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.pistol.double9mm_pickup'
CollisionHeight=5.000000
}

View file

@ -0,0 +1,215 @@
class NiceSingle extends NiceWeapon;
var bool bIsDual;
var int otherMagazine;
var class<NiceDualies> DualClass;
replication{
reliable if(Role < ROLE_Authority)
ServerSwitchToOtherSingle, ServerSwitchToDual;
reliable if(Role == ROLE_Authority)
bIsDual, otherMagazine;
}
function bool HandlePickupQuery(Pickup Item){
local float AddWeight;
if(Item.InventoryType == class){
AddWeight = Weight;
if(DualClass != none)
AddWeight = dualClass.default.Weight - AddWeight;
if(bIsDual || KFHumanPawn(Owner) != none && !KFHumanPawn(Owner).CanCarry(AddWeight)){
PlayerController(Instigator.Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 2);
return true;
}
return false;
}
return super.HandlePickupQuery(Item);
}
simulated function bool AltFireCanForceInterruptReload(){
return true;
}
simulated function Fire(float F){
if(!bIsReloading && GetMagazineAmmo() <= 0 && otherMagazine > 0)
ServerSwitchToOtherSingle();
else
super.Fire(F);
}
simulated function AltFire(float F){
if(bIsDual && NicePlayerController(Instigator.Controller) != none)
ClientForceInterruptReload(CANCEL_PASSIVESWITCH);
if(!bIsReloading && bIsDual)
ServerSwitchToDual();
else
super.AltFire(F);
}
function ServerSwitchToOtherSingle(){
local int swap;
local NiceHumanPawn nicePawn;
nicePawn = NiceHumanPawn(Instigator);
if(!bIsDual || nicePawn == none || nicePawn.Health <= 0)
return;
Ammo[0].AmmoAmount += otherMagazine - MagAmmoRemaining;
swap = MagAmmoRemaining;
MagAmmoRemaining = otherMagazine;
otherMagazine = swap;
ClientSetMagSize(MagAmmoRemaining, bRoundInChamber);
//nicePawn.ClientChangeWeapon(self);
}
function ServerSwitchToDual(){
local int m;
local int origAmmo;
local NiceHumanPawn nicePawn;
local NiceDualies dualPistols;
local NicePlainData.Data transferData;
nicePawn = NiceHumanPawn(Instigator);
if(!bIsDual || DualClass == none || nicePawn == none || nicePawn.Health <= 0)
return;
nicePawn.CurrentWeight -= Weight;
Weight = 0;
origAmmo = AmmoAmount(0);
for(m = 0; m < NUM_FIRE_MODES;m ++)
if(FireMode[m].bIsFiring)
StopFire(m);
DetachFromPawn(nicePawn);
dualPistols = nicePawn.Spawn(DualClass);
if(dualPistols != none){
dualPistols.DemoReplacement = class;
transferData = GetNiceData();
dualPistols.GiveTo(nicePawn);
dualPistols.SetNiceData(transferData, nicePawn);
dualPistols.MagAmmoRemRight = MagAmmoRemaining;
dualPistols.MagAmmoRemLeft = otherMagazine;
dualPistols.MagAmmoRemaining = dualPistols.MagAmmoRemLeft + dualPistols.MagAmmoRemRight;
dualPistols.SellValue = SellValue;
dualPistols.Ammo[0].AmmoAmount = origAmmo + otherMagazine;
dualPistols.ClientSetDualMagSize(dualPistols.MagAmmoRemLeft, dualPistols.MagAmmoRemRight);
//nicePawn.ClientChangeWeapon(dualPistols);
//nicePawn.ServerChangedWeapon(self, dualPistols);
}
Destroy();
}
function DropFrom(vector StartLocation){
local int m;
local int magKeep, magGive;
local KFWeaponPickup weapPickup;
local int weightBeforeThrow;
local int AmmoThrown, OtherAmmo;
local NiceHumanPawn nicePawn;
nicePawn = NiceHumanPawn(Instigator);
if(nicePawn == none)
return;
if(!bIsDual){
super.DropFrom(StartLocation);
return;
}
weightBeforeThrow = nicePawn.CurrentWeight;
magKeep = otherMagazine;
magGive = MagAmmoRemaining;
OtherAmmo = AmmoAmount(0) - magKeep;
ClientWeaponThrown();
for(m = 0; m < NUM_FIRE_MODES;m ++)
if(FireMode[m].bIsFiring)
StopFire(m);
if(nicePawn != none)
DetachFromPawn(nicePawn);
AmmoThrown = OtherAmmo / 2;
OtherAmmo = OtherAmmo - AmmoThrown;
Ammo[0].AmmoAmount = OtherAmmo + magKeep;
MagAmmoRemaining = magKeep;
ClientSetMagSize(MagAmmoRemaining, bRoundInChamber);
weapPickup = KFWeaponPickup(nicePawn.Spawn(default.PickupClass,,, StartLocation));
if(weapPickup != none){
weapPickup.InitDroppedPickupFor(self);
weapPickup.Velocity = Velocity;
weapPickup.AmmoAmount[0] = AmmoThrown + magGive;
weapPickup.SellValue = SellValue * 0.5;
SellValue *= 0.5;
weapPickup.MagAmmoRemaining = magGive;
if(nicePawn.Health > 0)
weapPickup.bThrown = true;
nicePawn.ClientChangeWeapon(self);
}
RemoveDual(weightBeforeThrow);
}
function RemoveDual(int pawnWeight){
local NiceHumanPawn nicePawn;
nicePawn = NiceHumanPawn(Instigator);
if(!bIsDual || nicePawn == none)
return;
bIsDual = false;
DemoReplacement = none;
nicePawn.CurrentWeight = pawnWeight - (Weight - default.Weight);
Weight = default.Weight;
otherMagazine = 0;
}
//SellValue
function GiveTo(Pawn other, optional Pickup Pickup){
local int m;
local int initAmmo, initMag;
local bool bDestroy;
local NiceSingle nicePistol;
local NiceDualies niceDual;
if(other != none){
nicePistol = NiceSingle(other.FindInventoryType(class));
niceDual = NiceDualies(other.FindInventoryType(DualClass));
}
bDestroy = false;
if(nicePistol == none || (niceDual != none && niceDual.bSwitching))
super.GiveTo(other, Pickup);
else if((nicePistol != none && nicePistol.bIsDual) || niceDual != none)
bDestroy = true;
else{
nicePistol.UpdateMagCapacity(other.PlayerReplicationInfo);
initAmmo = nicePistol.FireMode[0].AmmoClass.default.InitialAmount;
initMag = nicePistol.MagCapacity;
initMag = Min(initMag, initAmmo);
initAmmo -= initMag;
if(nicePistol.Ammo[0] != none){
nicePistol.Ammo[0].AmmoAmount += initAmmo;
nicePistol.Ammo[0].AmmoAmount = Min(nicePistol.Ammo[0].AmmoAmount, nicePistol.Ammo[0].MaxAmmo);
}
nicePistol.bIsDual = true;
nicePistol.otherMagazine = initMag;
nicePistol.SellValue = 2 * min(SellValue, nicePistol.SellValue);
nicePistol.ServerSwitchToDual();
bDestroy = true;
}
if(bDestroy){
for(m = 0; m < NUM_FIRE_MODES;m ++)
Ammo[m] = none;
Destroy();
}
}
defaultproperties
{
DualClass=Class'NicePack.NiceDualies'
bHasChargePhase=False
FirstPersonFlashlightOffset=(X=-20.000000,Y=-22.000000,Z=8.000000)
MagCapacity=15
ReloadRate=2.000000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_Single9mm"
ModeSwitchAnim="LightOn"
Weight=0.000000
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=70.000000
TraderInfoTexture=Texture'KillingFloorHUD.Trader_Weapon_Images.Trader_9mm'
ZoomedDisplayFOV=65.000000
FireModeClass(0)=Class'NicePack.NiceSingleFire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
AIRating=0.250000
CurrentRating=0.250000
bShowChargingBar=True
Description="A 9mm Pistol"
DisplayFOV=70.000000
Priority=60
InventoryGroup=2
GroupOffset=1
PickupClass=Class'NicePack.NiceSinglePickup'
PlayerViewOffset=(X=20.000000,Y=25.000000,Z=-10.000000)
BobDamping=6.000000
AttachmentClass=Class'NicePack.NiceSingleAttachment'
IconCoords=(X1=434,Y1=253,X2=506,Y2=292)
ItemName="Just a single pistol"
}

View file

@ -0,0 +1,13 @@
class NiceSingleAmmo extends NiceAmmo;
#EXEC OBJ LOAD FILE=InterfaceContent.utx
defaultproperties
{
AmmoPickupAmount=30
MaxAmmo=240
InitialAmount=120
PickupClass=Class'KFMod.SingleAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=413,Y1=82,X2=457,Y2=125)
ItemName="9mm bullets"
}

View file

@ -0,0 +1,10 @@
class NiceSingleAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=20
InventoryType=Class'NicePack.NiceSingleAmmo'
RespawnTime=0.000000
PickupMessage="Rounds (9mm)"
StaticMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
}

View file

@ -0,0 +1,52 @@
class NiceSingleAttachment extends NiceAttachment;
defaultproperties
{
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdPistol'
mTracerClass=Class'KFMod.KFNewTracer'
mShellCaseEmitterClass=Class'KFMod.KFShellSpewer'
MovementAnims(0)="JogF_Single9mm"
MovementAnims(1)="JogB_Single9mm"
MovementAnims(2)="JogL_Single9mm"
MovementAnims(3)="JogR_Single9mm"
TurnLeftAnim="TurnL_Single9mm"
TurnRightAnim="TurnR_Single9mm"
CrouchAnims(0)="CHwalkF_Single9mm"
CrouchAnims(1)="CHwalkB_Single9mm"
CrouchAnims(2)="CHwalkL_Single9mm"
CrouchAnims(3)="CHwalkR_Single9mm"
CrouchTurnRightAnim="CH_TurnR_Single9mm"
CrouchTurnLeftAnim="CH_TurnL_Single9mm"
IdleCrouchAnim="CHIdle_Single9mm"
IdleWeaponAnim="Idle_Single9mm"
IdleRestAnim="Idle_Single9mm"
IdleChatAnim="Idle_Single9mm"
IdleHeavyAnim="Idle_Single9mm"
IdleRifleAnim="Idle_Single9mm"
FireAnims(0)="Fire_Single9mm"
FireAnims(1)="Fire_Single9mm"
FireAnims(2)="Fire_Single9mm"
FireAnims(3)="Fire_Single9mm"
FireAltAnims(0)="Fire_Single9mm"
FireAltAnims(1)="Fire_Single9mm"
FireAltAnims(2)="Fire_Single9mm"
FireAltAnims(3)="Fire_Single9mm"
FireCrouchAnims(0)="CHFire_Single9mm"
FireCrouchAnims(1)="CHFire_Single9mm"
FireCrouchAnims(2)="CHFire_Single9mm"
FireCrouchAnims(3)="CHFire_Single9mm"
FireCrouchAltAnims(0)="CHFire_Single9mm"
FireCrouchAltAnims(1)="CHFire_Single9mm"
FireCrouchAltAnims(2)="CHFire_Single9mm"
FireCrouchAltAnims(3)="CHFire_Single9mm"
HitAnims(0)="HitF_Single9mm"
HitAnims(1)="HitB_Single9mm"
HitAnims(2)="HitL_Single9mm"
HitAnims(3)="HitR_Single9mm"
PostFireBlendStandAnim="Blend_Single9mm"
PostFireBlendCrouchAnim="CHBlend_Single9mm"
SplashEffect=Class'ROEffects.BulletSplashEmitter'
LightType=LT_Pulse
LightRadius=0.000000
CullDistance=5000.000000
}

View file

@ -0,0 +1,46 @@
class NiceSingleFire extends NiceFire;
var bool bWasInZedTime;
simulated function ModeTick(float delta){
local NicePlayerController nicePlayer;
if(instigator != none)
nicePlayer = NicePlayerController(instigator.controller);
if(nicePlayer != none && nicePlayer.IsZedTimeActive() != bWasInZedTime){
bWasInZedTime = !bWasInZedTime;
if(bWasInZedTime)
niceNextFireTime = Level.TimeSeconds + (niceNextFireTime - Level.TimeSeconds) * KFGameType(Level.Game).ZedTimeSlomoScale;
nextFireTime = niceNextFireTime;
}
super.ModeTick(delta);
}
defaultproperties
{
FireAimedAnim="Fire_Iron"
RecoilRate=0.070000
maxVerticalRecoilAngle=300
maxHorizontalRecoilAngle=50
ShellEjectClass=Class'ROEffects.KFShellEject9mm'
ShellEjectBoneName="Shell_eject"
bRandomPitchFireSound=False
DamageMin=35
DamageMax=35
Momentum=10000.000000
bPawnRapidFireAnim=True
bWaitForRelease=True
bAttachSmokeEmitter=True
TransientSoundVolume=1.800000
FireAnimRate=1.500000
TweenTime=0.025000
FireForce="AssaultRifleFire"
FireRate=0.175000
AmmoClass=Class'NicePack.NiceSingleAmmo'
ShakeRotMag=(X=75.000000,Y=75.000000,Z=250.000000)
ShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
ShakeRotTime=3.000000
ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=10.000000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=2.000000
BotRefireRate=0.350000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stMP'
aimerror=30.000000
}

View file

@ -0,0 +1,83 @@
class NiceSinglePickup extends NiceWeaponPickup;
function Inventory SpawnCopy(Pawn other){
local Inventory CurInv;
local NiceWeapon PistolInInventory;
for(CurInv = other.Inventory;CurInv != none;CurInv = CurInv.Inventory){
PistolInInventory = NiceWeapon(CurInv);
if(PistolInInventory != none && PistolInInventory.class == default.InventoryType){
// Make dualies to cost twice of lowest value in case of PERKED+UNPERKED pistols
SellValue = 2 * min(SellValue, PistolInInventory.SellValue);
AmmoAmount[0] += PistolInInventory.AmmoAmount(0);
class'NicePlainData'.static.SetInt(weaponData, "leftMag", MagAmmoRemaining);
class'NicePlainData'.static.SetInt(weaponData, "rightMag", PistolInInventory.MagAmmoRemaining);
// destroy the inventory to force parent SpawnCopy() to make a new instance of class
// we specified below
if(Inventory != none)
Inventory.Destroy();
// spawn dual guns instead of another instance of single
if(class<NiceSingle>(default.InventoryType) != none)
InventoryType = class<NiceSingle>(default.InventoryType).default.DualClass;
if(CurInv != none){
CurInv.Destroyed();
CurInv.Destroy();
}
return super(KFWeaponPickup).SpawnCopy(other);
}
}
InventoryType = default.InventoryType;
return super(KFWeaponPickup).SpawnCopy(other);
}
function bool CheckCanCarry(KFHumanPawn Hm){
local Inventory CurInv;
local class<NiceWeapon> dualClass;
local float AddWeight;
AddWeight = class<KFWeapon>(default.InventoryType).default.Weight;
if(class<NiceWeapon>(default.InventoryType) != none)
dualClass = class<NiceSingle>(default.InventoryType).default.dualClass;
for(CurInv = Hm.Inventory; CurInv != none; CurInv = CurInv.Inventory){
if(CurInv.class == dualClass) {
// Already have duals, can't carry a single
if(LastCantCarryTime < Level.TimeSeconds && PlayerController(Hm.Controller) != none){
LastCantCarryTime = Level.TimeSeconds + 0.5;
PlayerController(Hm.Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 2);
}
return false;
}
else if(CurInv.class == default.InventoryType && dualClass != none){
AddWeight = dualClass.default.Weight - AddWeight;
break;
}
}
if(!Hm.CanCarry(AddWeight)){
if(LastCantCarryTime < Level.TimeSeconds && PlayerController(Hm.Controller) != none){
LastCantCarryTime = Level.TimeSeconds + 0.5;
PlayerController(Hm.Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 2);
}
return false;
}
return true;
}
defaultproperties
{
Weight=0.000000
cost=150
AmmoCost=10
BuyClipSize=30
PowerValue=20
SpeedValue=50
RangeValue=35
Description="A 9mm handgun."
ItemName="!!!"
ItemShortName="!!!"
AmmoItemName="9mm Rounds"
AmmoMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
CorrespondingPerkIndex=2
EquipmentCategoryID=1
InventoryType=Class'NicePack.NiceSingle'
PickupMessage="You got the 9mm handgun"
PickupSound=Sound'KF_9MMSnd.9mm_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.pistol.9mm_Pickup'
CollisionHeight=5.000000
}