update16 #35

Merged
NikC- merged 11 commits from update16 into master 2024-11-27 20:00:56 +03:00
32 changed files with 619 additions and 89 deletions

View File

@ -260,6 +260,21 @@ function PostRender(Canvas C)
}
}
//// Draw quad damage bar
if (nicePawn != none && nicePawn.quadDamageRemaining > 0.0)
{
C.SetDrawColor(255, 255, 255);
barTexture = redBar;
center = C.ClipX * 0.5;
y = C.ClipY * 0.45;
barWidth = C.ClipX * 0.2;
barWidth *= nicePawn.quadDamageRemaining / class'NiceSkillEnforcerBruteA'.default.maximumDamageAdded;
x = center - (barWidth / 2);
C.SetPos(x, y);
Log("DRAWING" @ x @ y @ barWidth);
C.DrawTile(barTexture, barWidth, 32, 0, 0, barTexture.MaterialUSize(), barTexture.MaterialVSize());
}//native(466) final function DrawTile( material Mat, float XL, float YL, float U, float V, float UL, float VL );
team = C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team;
//// Draw health still in regen timer
healthToGive = ScrnHumanPawn(C.ViewPort.Actor.Pawn).clientHealthToGive;

View File

@ -74,6 +74,8 @@ State MatchInProgress{
function ScoreKill(Controller Killer, Controller Other)
{
local NicePlayerController niceKiller;
local NiceHumanPawn niceKillerPawn;
local PlayerReplicationInfo OtherPRI;
local float KillScore;
local Controller C;
@ -198,7 +200,15 @@ function ScoreKill(Controller Killer, Controller Other)
}
/* End Marco's Kill Messages */
niceKiller = NicePlayerController(killer);
if (niceKiller != none && niceKiller.abilityManager != none) {
niceKillerPawn = NiceHumanPawn(niceKiller.pawn);
niceKiller.abilityManager.AddToAllCooldowns(-1);
}
if ( niceKillerPawn != none && NiceBoomStick(niceKillerPawn.weapon) != none
&& other != none && other.pawn != none && other.pawn.default.health >= 1000) {
niceKillerPawn.invincibilityTimer += 1.0;
}
}
function DramaticEvent(float BaseZedTimePossibility, optional float DesiredZedTimeDuration){

View File

@ -46,10 +46,11 @@ struct InvincExtentions{
var array<InvincExtentions> zedInvExtList;
var int headshotStack;
var float bruteTimer;
var float quadDamageRemaining;
replication{
reliable if(Role == ROLE_Authority)
headshotStack, hmgShieldLevel, forcedZedTimeCountDown, maniacTimeout, invincibilityTimer, safeMeleeMisses, ffScale,
currentCalibrationState, calibrationScore, gunslingerTimer;
currentCalibrationState, calibrationScore, gunslingerTimer, quadDamageRemaining;
reliable if(Role == ROLE_Authority)
ClientChangeWeapon;
reliable if(Role < ROLE_AUTHORITY)
@ -736,6 +737,7 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation,
local float healPotency;
local bool bOldArmorStops;
local float adrResistance;
local float oldHealthToGive;
local NicePlayerController nicePlayer;
ApplyWeaponStats(Weapon);
if(invincibilityTimer > 0)
@ -766,7 +768,12 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation,
damageType.default.bArmorStops = true;
}
lastExplosionDistance = 0.0; // hack, but scrn fucks with usotherwise
oldHealthToGive = healthToGive; // remember this to restore this value, in case we are using safeguard skill
super.TakeDamage(Damage, InstigatedBy, hitLocation, Momentum, damageType, HitIndex);
if (class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillHeavySafeguard')) {
healthToGive = oldHealthToGive;
clientHealthToGive = healthToGive;
}
// Commando's zed time
if( forcedZedTimeCountDown <= 0.0
&& health < class'NiceSkillCommandoCriticalFocus'.default.healthBoundary && KFGameType(Level.Game) != none
@ -789,7 +796,7 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation,
if(ShieldStrength < 0)
ShieldStrength = 0;
health += HealAmount * 0.5;
TakeHealing(self, HealAmount * 0.5, HealPotency);
TakeHealing(self, HealAmount * 0.5 + 1, HealPotency);
}
if(ShieldStrength <= 0)
getFreeJacket();

View File

@ -334,7 +334,7 @@ simulated function UpdateMeleeInvincibility
nicePawn.TryExtendingInv(niceZed, false, headshotLevel > 0.0);
// Handle melee-cases
if(mainTarget && class<niceDamageTypeVetBerserker>(damageType) != none)
nicePawn.TryExtendingInv(niceZed, true, headshotLevel > 0.0);
nicePawn.TryExtendingInv(niceZed, true, headshotLevel > 0.0);
nicePawn.ApplyWeaponStats(nicePawn.weapon);
}
simulated function UpdateArdour(bool isKill, NicePlayerController nicePlayer){

View File

@ -29,19 +29,19 @@ struct NiceAbilityDescription{
// Image to be used as an ability's icon
var Texture icon;
// Default cooldown duration
var float cooldownLength;
var int cooldownLength;
// Can ability be canceled once activated?
var bool canBeCancelled;
var bool canBeCancelled;
};
// Complete description of current status of an ability,
// including it's complete description.
struct NiceAbilityStatus{
// Complete description of ability in question
var NiceAbilityDescription description;
var NiceAbilityDescription description;
// Current cooldown value
var float cooldown;
var int cooldown;
// Current state of an ability
var EAbilityState myState;
var EAbilityState myState;
};
var NiceAbilityStatus currentAbilities[5];
var int currentAbilitiesAmount;
@ -65,7 +65,7 @@ function AddAbility(NiceAbilityDescription description){
if(currentAbilities[i].description.ID ~= description.ID)
return;
newRecord.description = description;
newRecord.cooldown = 0.0;
newRecord.cooldown = 0;
newRecord.myState = ASTATE_READY;
currentAbilities[currentAbilitiesAmount] = newRecord;
currentAbilitiesAmount += 1;
@ -120,34 +120,34 @@ function SetAbilityState(int abilityIndex, EAbilityState newState){
if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return;
currentState = currentAbilities[abilityIndex].myState;
if(currentState == newState)
return;
return;
if( currentState == ASTATE_ACTIVE && newState == ASTATE_READY
&& !currentAbilities[abilityIndex].description.canBeCancelled)
return;
&& !currentAbilities[abilityIndex].description.canBeCancelled)
return;
currentAbilities[abilityIndex].myState = newState;
if(newState == ASTATE_COOLDOWN){
cooldown = currentAbilities[abilityIndex].description.cooldownLength;
events.static.CallModAbilityCooldown(
currentAbilities[abilityIndex].description.ID,
relatedPlayer,
cooldown
);
currentAbilities[abilityIndex].cooldown = cooldown;
cooldown = currentAbilities[abilityIndex].description.cooldownLength;
events.static.CallModAbilityCooldown(
currentAbilities[abilityIndex].description.ID,
relatedPlayer,
cooldown
);
currentAbilities[abilityIndex].cooldown = cooldown;
}
hackCounter ++;
netUpdateTime = level.timeSeconds - 1;
// Fire off events
if(newState == ASTATE_ACTIVE){
events.static.CallAbilityActivated(
currentAbilities[abilityIndex].description.ID,
relatedPlayer
);
events.static.CallAbilityActivated(
currentAbilities[abilityIndex].description.ID,
relatedPlayer
);
}
}
// Changes ability's cooldown by a given amount.
// If this brings cooldown to zero or below -
// resets current ability to a 'ready' (ASTATE_READY) state.
function AddToCooldown(int abilityIndex, float delta){
function AddToCooldown(int abilityIndex, int delta){
if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return;
if(currentAbilities[abilityIndex].myState != ASTATE_COOLDOWN) return;
currentAbilities[abilityIndex].cooldown += delta;
@ -155,12 +155,21 @@ function AddToCooldown(int abilityIndex, float delta){
SetAbilityState(abilityIndex, ASTATE_READY);
hackCounter ++;
}
function Tick(float deltaTime){
function AddToAllCooldowns(int delta){
local int i;
if(Role != Role_AUTHORITY) return;
for(i = 0;i < currentAbilitiesAmount;i ++)
AddToCooldown(i, -deltaTime);
for (i = 0; i < currentAbilitiesAmount; i += 1) {
if (currentAbilities[i].myState == ASTATE_COOLDOWN) {
currentAbilities[i].cooldown += delta;
if(currentAbilities[i].cooldown <= 0) {
SetAbilityState(i, ASTATE_READY);
}
}
}
hackCounter ++;
}
defaultproperties
{
maxAbilitiesAmount=5

View File

@ -15,7 +15,6 @@ static function AbilityActivated(
NicePlayerController relatedPlayer)
{
local NiceHumanPawn nicePawn;
local NiceMonster victim;
if (relatedPlayer == none) return;
nicePawn = NiceHumanPawn(relatedPlayer.pawn);
@ -37,6 +36,23 @@ static function AbilityActivated(
{
nicePawn.bruteTimer =
class'NiceSkillEnforcerBruteA'.default.abilityDuration;
nicePawn.quadDamageRemaining = class'NiceSkillEnforcerBruteA'.default.maximumDamageAdded;
}
}
static function ModAbilityCooldown( string abilityID,
NicePlayerController relatedPlayer,
out float cooldown)
{
local NiceHumanPawn nicePawn;
if (relatedPlayer == none) return;
nicePawn = NiceHumanPawn(relatedPlayer.pawn);
if (nicePawn == none) return;
if (abilityID == "brute")
{
nicePawn.quadDamageRemaining = 0;
}
}

View File

@ -16,12 +16,15 @@ static function array<int> GetProgressArray(byte ReqNum, optional out int Double
// Other bonuses
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType)
{
local float fDamage;
local int bruteAbilityIndex;
local float fDamage, addedDamage;
local NicePlayerController nicePlayer;
local NiceHumanPawn nicePawn;
local NiceMonster niceTarget;
fDamage = float(InDamage);
nicePlayer = NicePlayerController(KFPRI.Owner);
nicePawn = NiceHumanPawn(nicePlayer.pawn);
niceTarget = NiceMonster(injured);
if ( niceTarget != none
&& niceTarget.bFrozenZed
@ -31,9 +34,20 @@ static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured,
(1 + class'NiceSkillEnforcerFinisherRounds'.default.damageBonus);
}
if( nicePlayer != none && nicePlayer.abilityManager != none
&& nicePawn != none && nicePawn.quadDamageRemaining > 0
&& nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillEnforcerBruteA'.default.abilityID))
{
fDamage *= class'NiceSkillEnforcerBruteA'.default.damageMult;
addedDamage = fDamage * class'NiceSkillEnforcerBruteA'.default.damageMult - fDamage;
if (addedDamage >= nicePawn.quadDamageRemaining) {
addedDamage = nicePawn.quadDamageRemaining;
nicePawn.quadDamageRemaining = 0.0;
bruteAbilityIndex = nicePlayer.abilityManager.GetAbilityIndex(class'NiceSkillEnforcerBruteA'.default.abilityID);
nicePlayer.abilityManager.SetAbilityState(bruteAbilityIndex, ASTATE_COOLDOWN);
}
else {
nicePawn.quadDamageRemaining -= addedDamage;
}
fDamage += addedDamage;
}
return int(fDamage);
}
@ -45,7 +59,7 @@ static function float GetPenetrationDamageMulti(KFPlayerReplicationInfo KFPRI, f
return DefaultPenDamageReduction;
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillSupportStubbornness'))
bonusReduction = class'NiceSkillSupportStubbornness'.default.penLossRed;
PenDamageInverse = (1.0 - FMax(0, DefaultPenDamageReduction));
PenDamageInverse = (1.0 - FMax(0, DefaultPenDamageReduction));
return DefaultPenDamageReduction + PenDamageInverse * (0.6 + 0.4 * bonusReduction); // 60% better penetrations + bonus
}
@ -64,15 +78,6 @@ static function class<Grenade> GetNadeType(KFPlayerReplicationInfo KFPRI){
return class'NiceCryoNade';
}
static function float AddExtraAmmoFor(KFPlayerReplicationInfo KFPRI, Class<Ammunition> AmmoType){
local float bonusNades;
// Default bonus
bonusNades = 2;
if(AmmoType == class'FragAmmo')
return 1.0 + 0.2 * bonusNades;
return 1.0;
}
static function int ReduceDamage(KFPlayerReplicationInfo KFPRI, KFPawn Injured, Pawn Instigator, int InDamage, class<DamageType> DmgType){
local float fDamage;
fDamage = float(inDamage);
@ -180,7 +185,7 @@ defaultproperties
SkillGroupA(4)=class'NiceSkillEnforcerZEDBarrage'
SkillGroupB(0)=class'NiceSkillEnforcerUnkillable'
SkillGroupB(1)=class'NiceSkillEnforcerMultitasker'
SkillGroupB(2)=class'NiceSkillEnforcerFinisherRounds'
SkillGroupB(2)=class'NiceSkillHeavySafeguard'
SkillGroupB(3)=class'NiceSkillEnforcerBruteA'
SkillGroupB(4)=class'NiceSkillEnforcerZEDIceGiant'
progressArray0(0)=100

View File

@ -7,5 +7,5 @@ defaultproperties
stunMult=3.000000
spreadMult=0.500000
SkillName="Bombard"
SkillEffects="Your perked weapons are 3 times as good at stunning."
SkillEffects="Your perked weapons are 3 times as good at stunning and have omly half as much spread."
}

View File

@ -5,6 +5,7 @@ var string abilityID;
var float coolDown;
var float abilityDuration;
var float damageMult;
var float maximumDamageAdded;
function static SkillSelected(NicePlayerController nicePlayer)
{
@ -29,6 +30,7 @@ function static SkillDeSelected(NicePlayerController nicePlayer)
defaultproperties
{
maximumDamageAdded=10000
abilityID="brute"
cooldown=60.000000
abilityDuration=5.0

View File

@ -2,5 +2,6 @@ class NiceHeavyFire extends NiceFire;
defaultproperties
{
maxBonusContLenght=3
maxBonusContLenght = 3
aimingSpreadReductionCoefficient = 0.0
}

View File

@ -272,19 +272,19 @@ 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
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

@ -14,6 +14,7 @@ var float prReqPrecise; // How precise must head-shot be
var float lockonTime;
var float flinchMultiplier; // How effective is weapon for flinching zeds
var float stunMultiplier; // How effective is weapon for stunning zeds
var float stunLengthMultiplier; // For how long is weapon going to stun zeds
var float heatPart; // How much of this damage should be a heat component?
var float freezePower; // How good is weapon at freezing?
var float bodyDestructionMult; // How much more damage do to body on a head-shot?
@ -84,6 +85,7 @@ defaultproperties
prReqPrecise=0.750000
flinchMultiplier=1.000000
stunMultiplier=1.000000
stunLengthMultiplier=1.000000
bodyDestructionMult=1.000000
headSizeModifier=1.000000
BigZedPenDmgReduction=0.500000

View File

@ -20,6 +20,7 @@ var() bool bSemiMustBurst;
var() int MaxBurstLength;
var() int burstShotsMade;
var bool bResetRecoil; // Set this flag to 'true' to disable recoil for the next shot; flag will be automatically reset to 'false' after that
var float aimingSpreadReductionCoefficient;
var bool zoomOutOnShot;
var bool bShouldBounce;
var bool bCausePain;
@ -487,7 +488,7 @@ simulated function HandleRecoil(float Rec)
KFW= KFWeapon(Weapon);
if (KFW.bAimingRifle)
{
Rec *= 0.5;
Rec *= aimingSpreadReductionCoefficient;
}
if (nicePawn.stationaryTime > 0.0 && class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillHeavyStablePosition'))
{
@ -697,7 +698,8 @@ simulated function UpdateFireSpeed(){
ReloadAnimRate = default.ReloadAnimRate * fireSpeedMod;
}
// This function is called when next fire time needs to be updated
simulated function float UpdateNextFireTime(float fireTimeVar){
simulated function float UpdateNextFireTime(float fireTimeVar) {
local float usedFireRate;
local float burstSlowDown;
local NiceHumanPawn nicePawn;
local class<NiceVeterancyTypes> niceVet;
@ -705,11 +707,19 @@ simulated function float UpdateNextFireTime(float fireTimeVar){
if(nicePawn != none)
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePawn.PlayerReplicationInfo);
fireTimeVar = FMax(fireTimeVar, Level.TimeSeconds);
usedFireRate = fireRate;
if (maxBonusContLenght > 1) {
if (currentContLenght <= maxBonusContLenght) {
usedFireRate *= 0.8 + 0.2 * (maxBonusContLenght - currentContLenght);
} else {
usedFireRate *= 0.8;
}
}
if(bFireOnRelease){
if(bIsFiring)
fireTimeVar += MaxHoldTime + FireRate;
fireTimeVar += MaxHoldTime + usedFireRate;
else
fireTimeVar = Level.TimeSeconds + FireRate;
fireTimeVar = Level.TimeSeconds + usedFireRate;
}
else{
if(currentContext.bIsBursting && GetBurstLength() > 1){
@ -720,10 +730,10 @@ simulated function float UpdateNextFireTime(float fireTimeVar){
burstSlowDown = 1.0;
else
burstSlowDown = 1.3;
fireTimeVar += FireRate * burstSlowDown;
fireTimeVar += usedFireRate * burstSlowDown;
}
else
fireTimeVar += FireRate;
fireTimeVar += usedFireRate;
fireTimeVar = FMax(fireTimeVar, Level.TimeSeconds);
}
return fireTimeVar;
@ -745,4 +755,5 @@ defaultproperties
spreadGainedPerShot=0
spreadLostPerSecond=0
RecoilVelocityScale = 0
aimingSpreadReductionCoefficient = 0.5
}

View File

@ -4,8 +4,8 @@ defaultproperties
ProjectileSpeed=48250.000000
FireAimedAnim="Fire"
RecoilRate=0.040000
maxVerticalRecoilAngle=550
maxHorizontalRecoilAngle=225
maxVerticalRecoilAngle=115
maxHorizontalRecoilAngle=0
ShellEjectClass=Class'ROEffects.KFShellEjectAK'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True

View File

@ -10,4 +10,6 @@ defaultproperties
KDeathVel=1400.000000
KDeathUpKick=150.000000
VehicleDamageScaling=0.700000
stunMultiplier=3.0
stunLengthMultiplier=2.0
}

View File

@ -5,8 +5,8 @@ defaultproperties
contBonus=1.400000
FireAimedAnim="Fire_Iron"
RecoilRate=0.050000
maxVerticalRecoilAngle=400
maxHorizontalRecoilAngle=200
maxVerticalRecoilAngle=100
maxHorizontalRecoilAngle=0
ShellEjectClass=Class'ROEffects.KFShellEjectAK'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True

View File

@ -17,7 +17,7 @@ defaultproperties
MagazineBone="clip"
bHasScope=True
ZoomedDisplayFOVHigh=50.000000
MagCapacity=30
MagCapacity=60
ReloadRate=3.500000
ReloadAnim="Reload"
ReloadAnimRate=1.000000

View File

@ -2,7 +2,7 @@ class NiceSA80LSWAmmo extends NiceAmmo;
defaultproperties
{
WeaponPickupClass=class'NiceSA80LSWPickup'
AmmoPickupAmount=30
AmmoPickupAmount=60
MaxAmmo=360
InitialAmount=90
PickupClass=class'NiceSA80LSWAmmoPickup'

View File

@ -1,7 +1,7 @@
class NiceSA80LSWAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
AmmoAmount=60
InventoryType=class'NiceSA80LSWAmmo'
PickupMessage="5.56x45"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'

View File

@ -4,8 +4,8 @@ defaultproperties
ProjectileSpeed=46500.000000
FireAimedAnim="Iron_Idle"
RecoilRate=0.050000
maxVerticalRecoilAngle=300
maxHorizontalRecoilAngle=150
maxVerticalRecoilAngle=75
maxHorizontalRecoilAngle=0
ShellEjectClass=Class'ROEffects.KFShellEjectBullpup'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True

View File

@ -3,8 +3,8 @@ defaultproperties
{
cost=200
Weight=5.000000
AmmoCost=5
BuyClipSize=30
AmmoCost=10
BuyClipSize=60
PowerValue=41
SpeedValue=60
RangeValue=60

View File

@ -12,12 +12,12 @@ simulated function HandleRecoil(float Rec)
defaultproperties
{
ProjectileSpeed=42650.000000
maxBonusContLenght=5
maxBonusContLenght=10
contBonusReset=false
FireAimedAnim="FireLoop"
RecoilRate=0.040000
maxVerticalRecoilAngle=450
maxHorizontalRecoilAngle=225
maxVerticalRecoilAngle=25
maxHorizontalRecoilAngle=0
ShellEjectClass=Class'ROEffects.KFShellEjectSCAR'
ShellEjectBoneName="ejector"
FireSoundRef="HMG_S.XMV.XMV-Fire-1"

View File

@ -1,13 +1,13 @@
class NiceBoomStickAltFire extends NiceBoomStickFire;
// Overload to force last shot to have a different animation with reload
// NICETODO: uncomment this
function name GetCorrectAnim(bool bLoop, bool bAimed){
function name GetCorrectAnim(bool bLoop, bool bAimed) {
if(currentContext.sourceWeapon != none && currentContext.sourceWeapon.MagAmmoRemainingClient > 0)
return super.GetCorrectAnim(bLoop, bAimed);
return super.GetCorrectAnim(bLoop, bAimed);
if(bAimed)
return 'Fire_Last_Iron';
return 'Fire_Last_Iron';
else
return 'Fire_Last';
return 'Fire_Last';
return FireAnim;
}
defaultproperties

View File

@ -58,6 +58,6 @@ defaultproperties
ShakeOffsetTime=3.500000
BotRefireRate=2.500000
aimerror=2.000000
Spread=3000.000000
Spread=2000.000000
FireAnimRate=1.25
}

View File

@ -1,6 +1,7 @@
class NiceSpasAltFire extends NiceSpasFire;
defaultproperties
{
ProjPerFire=8
maxVerticalRecoilAngle=300
maxHorizontalRecoilAngle=180
FireAnimRate=0.650000

View File

@ -0,0 +1,108 @@
class NiceSyringe extends NiceMeleeWeapon;
var () int HealBoostAmount;
var float RegenTimer;
var localized string SuccessfulHealMessage;
replication
{
reliable if( Role == ROLE_Authority )
ClientSuccessfulHeal;
}
simulated function PostBeginPlay()
{
// Weapon will handle FireMode instantiation
Super.PostBeginPlay();
if( Role == ROLE_Authority ) {
HealBoostAmount = default.HealBoostAmount;
}
}
// The server lets the client know they successfully healed someone
simulated function ClientSuccessfulHeal(String HealedName)
{
if( PlayerController(Instigator.Controller) != none )
{
PlayerController(Instigator.controller).ClientMessage(SuccessfulHealMessage$HealedName, 'CriticalEvent');
}
}
simulated function Timer()
{
Super.Timer();
if( KFPawn(Instigator)!=None && KFPawn(Instigator).bIsQuickHealing>0 && ClientState==WS_ReadyToFire )
{
if( KFPawn(Instigator).bIsQuickHealing==1 )
{
if( !HackClientStartFire() )
{
if( Instigator.Health>=Instigator.HealthMax || ChargeBar()<0.75 )
KFPawn(Instigator).bIsQuickHealing = 2; // Was healed by someone else or some other error occurred.
SetTimer(0.2,False);
return;
}
KFPawn(Instigator).bIsQuickHealing = 2;
SetTimer(FireMode[1].FireRate+0.5,False);
}
else
{
Instigator.SwitchToLastWeapon();
KFPawn(Instigator).bIsQuickHealing = 0;
}
}
else if( ClientState==WS_Hidden && KFPawn(Instigator)!=None )
KFPawn(Instigator).bIsQuickHealing = 0; // Weapon was changed, ensure to reset this.
}
simulated function bool HackClientStartFire()
{
if( StartFire(1) )
{
if( Role<ROLE_Authority )
ServerStartFire(1);
FireMode[1].ModeDoFire(); // Force to start animating.
return true;
}
return false;
}
defaultproperties
{
MagCapacity=1
bChangeClipIcon=True
hudClipTexture=Texture'KillingFloorHUD.HUD.Hud_Syringe'
BloodSkinSwitchArray=0
HealBoostAmount = 100
TraderInfoTexture=Texture'KillingFloorHUD.WeaponSelect.Syringe'
FireModeClass(0)=Class'NicePack.NiceSyringeFire'
FireModeClass(1)=Class'NicePack.NiceSyringeAltFire'
PickupClass=Class'NicePack.NiceSyringePickup'
bKFNeverThrow = false
Skins(0)=Combiner'KF_Weapons_Trip_T.equipment.medInjector_cmb'
weaponRange=90.000000
Weight=0.000000
AIRating=-2.000000
bMeleeWeapon=False
Priority=6
InventoryGroup=5
GroupOffset=2
BobDamping=8.000000
AttachmentClass=Class'KFMod.SyringeAttachment'
IconCoords=(X1=169,Y1=39,X2=241,Y2=77)
ItemName="Med-Syringe"
Mesh=SkeletalMesh'KF_Weapons_Trip.Syringe_Trip'
AmbientGlow=2
AmmoCharge(0)=500
DisplayFOV=85.000000
StandardDisplayFOV=85.0
HudImage=texture'KillingFloorHUD.WeaponSelect.Syring_unselected'
SelectedHudImage=texture'KillingFloorHUD.WeaponSelect.Syringe'
bConsumesPhysicalAmmo=true
SuccessfulHealMessage="You healed "
}

View File

@ -0,0 +1,90 @@
class NiceSyringeAltFire extends NiceMeleeFire;
var float InjectDelay;
var float HealeeRange;
function DoFireEffect()
{
SetTimer(InjectDelay, False);
if ( Level.NetMode != NM_StandAlone && Level.Game.NumPlayers > 1 && KFPlayerController(Instigator.Controller) != none &&
KFSteamStatsAndAchievements(KFPlayerController(Instigator.Controller).SteamStatsAndAchievements) != none )
{
KFSteamStatsAndAchievements(KFPlayerController(Instigator.Controller).SteamStatsAndAchievements).AddSelfHeal();
}
}
function Timer()
{
local float HealSum, HealPotency;
local KFPlayerReplicationInfo KFPRI;
KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
HealSum = NiceSyringe(Weapon).HealBoostAmount;
HealPotency = 1.0;
if ( KFPRI != none && KFPRI.ClientVeteranSkill != none )
HealPotency = KFPRI.ClientVeteranSkill.Static.GetHealPotency(KFPRI);
HealSum *= HealPotency;
Load = 1;
ReduceAmmoClient();
if ( NiceHumanPawn(Instigator) != none )
NiceHumanPawn(Instigator).TakeHealing(NiceHumanPawn(Instigator), HealSum, HealPotency, KFWeapon(Instigator.Weapon));
else
KFPawn(Instigator).GiveHealth(HealSum, Instigator.HealthMax);
}
function bool AllowFire()
{
if (Instigator.Health >= Instigator.HealthMax)
return false;
return Weapon.AmmoAmount(ThisModeNum) >= AmmoPerFire;
}
event ModeDoFire()
{
Load = 1;
Super.ModeDoFire();
}
function PlayFiring()
{
if ( Weapon.Mesh != None )
{
if ( FireCount > 0 )
{
if ( Weapon.HasAnim(FireLoopAnim) )
{
Weapon.PlayAnim(FireLoopAnim, FireLoopAnimRate, 0.0);
}
else
{
Weapon.PlayAnim(FireAnim, FireAnimRate, 0.0);
}
}
else
{
Weapon.PlayAnim(FireAnim, FireAnimRate, 0.0);
}
}
Weapon.PlayOwnedSound(FireSound,SLOT_Interact,TransientSoundVolume,,TransientSoundRadius,Default.FireAnimRate/FireAnimRate,false);
ClientPlayForceFeedback(FireForce); // jdf
FireCount++;
}
defaultproperties {
AmmoClass=class'NiceSyringeAmmo'
AmmoPerFire=1
TweenTime=0.1
TransientSoundVolume=1.8
FireAnim="AltFire"
FireRate=3.60000
bModeExclusive=true
InjectDelay=0.1
HealeeRange=70.000000
}

View File

@ -0,0 +1,12 @@
class NiceSyringeAmmo extends NiceAmmo;
defaultproperties {
WeaponPickupClass=class'NiceSyringePickup'
AmmoPickupAmount=0
MaxAmmo=4
InitialAmount=1
PickupClass=class'NiceSyringeAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=336,Y1=82,X2=382,Y2=125)
ItemName="Healing juice"
}

View File

@ -0,0 +1,8 @@
class NiceSyringeAmmoPickup extends NiceAmmoPickup;
defaultproperties {
AmmoAmount=1
InventoryType=class'NiceSyringe'
PickupMessage="Healing juice"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'
}

View File

@ -0,0 +1,208 @@
class NiceSyringeFire extends NiceMeleeFire;
var float LastHealAttempt;
var float HealAttemptDelay;
var float LastHealMessageTime;
var float HealMessageDelay;
var localized string NoHealTargetMessage;
var KFHumanPawn CachedHealee;
var transient float PendingHealTime;
simulated function DestroyEffects()
{
super.DestroyEffects();
if (CachedHealee != None)
CachedHealee = none;
}
simulated function bool AllowFire() {
local KFHumanPawn Healtarget;
local string healeeName;
if (!super.AllowFire()) {
return false;
}
if (CanFindHealee()) {
if( CachedHealee.PlayerReplicationInfo != none &&
CachedHealee.PlayerReplicationInfo.PlayerName != "")
{
HealeeName = CachedHealee.PlayerReplicationInfo.PlayerName;
}
else {
HealeeName = CachedHealee.MenuName;
}
NiceSyringe(Weapon).ClientSuccessfulHeal(HealeeName);
// Give the messages if we missed our heal, can't find a target, etc
if ( KFPlayerController(Instigator.Controller) != none )
{
if ( LastHealAttempt + HealAttemptDelay < Level.TimeSeconds)
{
PlayerController(Instigator.controller).ClientMessage(NoHealTargetMessage, 'CriticalEvent');
LastHealAttempt = Level.TimeSeconds;
}
if ( Level.TimeSeconds - LastHealMessageTime > HealMessageDelay )
{
// if there's a Player within 2 meters who needs healing, say that we're trying to heal them
foreach Instigator.VisibleCollidingActors(class'KFHumanPawn', Healtarget, 100)
{
if ( Healtarget != Instigator && Healtarget.Health < Healtarget.HealthMax )
{
PlayerController(Instigator.Controller).Speech('AUTO', 5, "");
LastHealMessageTime = Level.TimeSeconds;
break;
}
}
}
}
return true;
}
return false;
}
function Timer()
{
local KFPlayerReplicationInfo PRI;
local int MedicReward;
local KFHumanPawn Healed;
local float HealSum, HealPotency; // for modifying based on perks
PRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
Healed = CachedHealee;
HealPotency = 1.0;
CachedHealee = none;
if ( Healed != none && Healed.Health > 0 && Healed != Instigator )
{
Load = 1;
ReduceAmmoClient();
if ( PRI != none && PRI.ClientVeteranSkill != none )
HealPotency = PRI.ClientVeteranSkill.Static.GetHealPotency(PRI);
HealSum = NiceSyringe(Weapon).HealBoostAmount;
HealSum *= HealPotency;
MedicReward = HealSum;
if ( (Healed.Health + Healed.healthToGive + MedicReward) > Healed.HealthMax )
{
MedicReward = Healed.HealthMax - (Healed.Health + Healed.healthToGive);
if ( MedicReward < 0 )
{
MedicReward = 0;
}
}
if ( NiceHumanPawn(Healed) != none )
NiceHumanPawn(Healed).TakeHealing(NiceHumanPawn(Instigator), HealSum, HealPotency, KFWeapon(Instigator.Weapon));
else
Healed.GiveHealth(HealSum, Healed.HealthMax);
// Tell them we're healing them
PlayerController(Instigator.Controller).Speech('AUTO', 5, "");
LastHealMessageTime = Level.TimeSeconds;
if ( PRI != None )
{
if ( MedicReward > 0 && KFSteamStatsAndAchievements(PRI.SteamStatsAndAchievements) != none )
{
KFSteamStatsAndAchievements(PRI.SteamStatsAndAchievements).AddDamageHealed(MedicReward);
}
// Give the medic reward money as a percentage of how much of the person's health they healed
MedicReward = int((FMin(float(MedicReward),Healed.HealthMax)/Healed.HealthMax) * 60); // Increased to 80 in Balance Round 6, reduced to 60 in Round 7
if ( class'ScrnBalance'.default.Mut.bMedicRewardFromTeam && Healed.PlayerReplicationInfo != none && Healed.PlayerReplicationInfo.Team != none ) {
// give money from team wallet
if ( Healed.PlayerReplicationInfo.Team.Score >= MedicReward ) {
Healed.PlayerReplicationInfo.Team.Score -= MedicReward;
PRI.Score += MedicReward;
}
}
else
PRI.Score += MedicReward;
if ( KFHumanPawn(Instigator) != none )
{
KFHumanPawn(Instigator).AlphaAmount = 255;
}
}
}
}
function KFHumanPawn GetHealee()
{
local KFHumanPawn KFHP, BestKFHP;
local vector Dir;
local float TempDot, BestDot;
Dir = vector(Instigator.GetViewRotation());
foreach Instigator.VisibleCollidingActors(class'KFHumanPawn', KFHP, 80.0)
{
if ( KFHP.Health < KFHP.HealthMax && KFHP.Health > 0 )
{
TempDot = Dir dot (KFHP.Location - Instigator.Location);
if ( TempDot > 0.7 && TempDot > BestDot )
{
BestKFHP = KFHP;
BestDot = TempDot;
}
}
}
return BestKFHP;
}
// Can we find someone to heal
function bool CanFindHealee()
{
local KFHumanPawn Healtarget;
Healtarget = GetHealee();
CachedHealee = Healtarget;
// Can't use syringe if we can't find a target
if ( Healtarget == none )
{
if ( KFPlayerController(Instigator.Controller) != none )
{
KFPlayerController(Instigator.Controller).CheckForHint(53);
}
return false;
}
// Can't use syringe if our target is already being healed to full health.
if ( (Healtarget.Health == Healtarget.Healthmax) || ((Healtarget.healthToGive + Healtarget.Health) >= Healtarget.Healthmax) )
{
return false;
}
return true;
}
function float GetFireSpeed()
{
if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none )
{
return KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetFireSpeedMod(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), Weapon);
}
return 1;
}
defaultproperties {
AmmoClass=class'NiceSyringeAmmo'
ammoPerFire=1
FireAnims(0)="Fire"
FireRate=2.800000
damageDelay=0.36
HealAttemptDelay=0.5
HealMessageDelay=10.0
NoHealTargetMessage="You must be near another player to heal them!"
bWaitForRelease=true
}

View File

@ -0,0 +1,19 @@
class NiceSyringePickup extends NiceWeaponPickup;
defaultproperties {
ItemName="Med-Syringe"
InventoryType=Class'NicePack.NiceSyringe'
Weight=0.000000
cost=100
AmmoCost=40
BuyClipSize=1
PickupMessage="You got the Med-Syringe."
PickupSound=Sound'Inf_Weapons_Foley.AmmoPickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.Syringe_pickup'
CollisionHeight=5.000000
EquipmentCategoryID=0
ItemShortName="Syringe"
AmmoItemName="Healing juice"
Description="Basic equipment, necessary for survival."
}

View File

@ -825,13 +825,16 @@ function int ModBodyDamage( out int damage,
local NicePlayerController nicePlayer;
painDamage = damage;
bIsHeadShot = (headshotLevel > 0.0);
if(instigatedBy != none)
if (instigatedBy != none)
nicePlayer = NicePlayerController(instigatedBy.Controller);
if (bFrozenZed && damageType != none && damageType.default.bIsExplosive) {
damage *= 1.5;
}
// On damaging critical spot (so far only head) - do body destruction
if(bIsHeadShot && damageType != none)
if (bIsHeadShot && damageType != none)
damage *= damageType.default.bodyDestructionMult;
// Skill bonuses
if(nicePlayer == none)
if (nicePlayer == none)
return painDamage;
bHasMessy = class'NiceVeterancyTypes'.static.
someoneHasSkill(nicePlayer, class'NiceSkillSharpshooterDieAlready');
@ -1286,8 +1289,9 @@ function float GetstunDurationMult( Pawn instigatedBy,
if(KFPRI == none) return stunDurationMultiplier;
niceVet = class<NiceVeterancyTypes>(KFPRI.ClientVeteranSkill);
if(niceVet == none) return stunDurationMultiplier;
if(damageType == none) return stunDurationMultiplier;
// Perk's bonuses out
return stunDurationMultiplier *
return stunDurationMultiplier * damageType.default.stunLengthMultiplier *
niceVet.static.stunDurationMult( KFPRI, self, KFPawn(instigatedBy),
damageType);
}