You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
6.9 KiB
174 lines
6.9 KiB
/** |
|
* This feature fixes a bug that can allow players to bypass server's |
|
* friendly fire limitations and teamkill. |
|
* Usual fixes apply friendly fire scale to suspicious damage themselves, which |
|
* also disables some of the environmental damage. |
|
* In order to avoid that, this fix allows server owner to define precisely |
|
* to what damage types to apply the friendly fire scaling. |
|
* It should be all damage types related to projectiles. |
|
* Copyright 2019 - 2021 Anton Tarasenko |
|
*------------------------------------------------------------------------------ |
|
* This file is part of Acedia. |
|
* |
|
* Acedia is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* Acedia is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
|
*/ |
|
class FixFFHack extends Feature |
|
config(AcediaFixes); |
|
|
|
/** |
|
* It's possible to bypass friendly fire damage scaling and always deal |
|
* full damage to other players, if one were to either leave the server or |
|
* spectate right after shooting a projectile. We use game rules to catch |
|
* such occurrences and apply friendly fire scaling to weapons, |
|
* specified by server admins. |
|
* To specify required subset of weapons, one must first |
|
* chose a general rule (scale by default / don't scale by default) and then, |
|
* optionally, add exceptions to it. |
|
* Choosing `scaleByDefault == true` as a general rule will make this fix |
|
* behave in the similar way to `KFExplosiveFix` by mutant and will disable |
|
* some environmental sources of damage on some maps. One can then add relevant |
|
* damage classes as exceptions to fix that downside, but making an extensive |
|
* list of such sources might prove problematic. |
|
* On the other hand, setting `scaleByDefault == false` will allow to get |
|
* rid of team-killing exploits by simply adding damage types of all |
|
* projectile weapons, used on a server. This fix comes with such filled-in |
|
* list of all vanilla projectile classes. |
|
*/ |
|
|
|
// Defines a general rule for choosing whether or not to apply |
|
// friendly fire scaling. |
|
// This can be overwritten by exceptions (`alwaysScale` or `neverScale`). |
|
// Enabling scaling by default without any exceptions in `neverScale` will |
|
// make this fix behave almost identically to Mutant's |
|
// 'Explosives Fix Mutator'. |
|
var private config const bool scaleByDefault; |
|
// Damage types, for which we should always reapply friendly fire scaling. |
|
var private config const array< class<DamageType> > alwaysScale; |
|
// Damage types, for which we should never reapply friendly fire scaling. |
|
var private config const array< class<DamageType> > neverScale; |
|
|
|
protected function OnEnabled() |
|
{ |
|
_.unreal.gameRules.OnNetDamage(self).connect = NetDamage; |
|
} |
|
|
|
protected function OnDisabled() |
|
{ |
|
_.unreal.gameRules.OnNetDamage(self).Disconnect(); |
|
} |
|
|
|
function int NetDamage( |
|
int originalDamage, |
|
int damage, |
|
Pawn injured, |
|
Pawn instigator, |
|
Vector hitLocation, |
|
out Vector momentum, |
|
class<DamageType> damageType) |
|
{ |
|
// Something is very wrong and we can just bail on this damage |
|
if (damageType == none) { |
|
return 0; |
|
} |
|
// We only check when suspicious instigators that aren't a world |
|
if (!damageType.default.bCausedByWorld && IsSuspicious(instigator)) |
|
{ |
|
if (ShouldScaleDamage(damageType)) |
|
{ |
|
// Remove pushback to avoid environmental kills |
|
momentum = Vect(0.0, 0.0, 0.0); |
|
damage *= _.unreal.GetKFGameType().friendlyFireScale; |
|
} |
|
} |
|
return damage; |
|
} |
|
|
|
private function bool IsSuspicious(Pawn instigator) |
|
{ |
|
// Instigator vanished |
|
if (instigator == none) return true; |
|
|
|
// Instigator already became spectator |
|
if (KFPawn(instigator) != none) |
|
{ |
|
if (instigator.playerReplicationInfo != none) { |
|
return instigator.playerReplicationInfo.bOnlySpectator; |
|
} |
|
return true; // Replication info is gone => suspicious |
|
} |
|
return false; |
|
} |
|
|
|
// Checks general rule and exception list |
|
public final function bool ShouldScaleDamage(class<DamageType> damageType) |
|
{ |
|
local int i; |
|
local array< class<DamageType> > exceptions; |
|
if (damageType == none) return false; |
|
|
|
if (scaleByDefault) { |
|
exceptions = neverScale; |
|
} |
|
else { |
|
exceptions = alwaysScale; |
|
} |
|
for (i = 0; i < exceptions.length; i += 1) |
|
{ |
|
if (exceptions[i] == damageType) { |
|
return (!scaleByDefault); |
|
} |
|
} |
|
return scaleByDefault; |
|
} |
|
|
|
defaultproperties |
|
{ |
|
scaleByDefault = false |
|
// Vanilla damage types for projectiles |
|
alwaysScale(0) = class'KFMod.DamTypeCrossbuzzsawHeadShot' |
|
alwaysScale(1) = class'KFMod.DamTypeCrossbuzzsaw' |
|
alwaysScale(2) = class'KFMod.DamTypeFrag' |
|
alwaysScale(3) = class'KFMod.DamTypePipeBomb' |
|
alwaysScale(4) = class'KFMod.DamTypeM203Grenade' |
|
alwaysScale(5) = class'KFMod.DamTypeM79Grenade' |
|
alwaysScale(6) = class'KFMod.DamTypeM79GrenadeImpact' |
|
alwaysScale(7) = class'KFMod.DamTypeM32Grenade' |
|
alwaysScale(8) = class'KFMod.DamTypeLAW' |
|
alwaysScale(9) = class'KFMod.DamTypeLawRocketImpact' |
|
alwaysScale(10) = class'KFMod.DamTypeFlameNade' |
|
alwaysScale(11) = class'KFMod.DamTypeFlareRevolver' |
|
alwaysScale(12) = class'KFMod.DamTypeFlareProjectileImpact' |
|
alwaysScale(13) = class'KFMod.DamTypeBurned' |
|
alwaysScale(14) = class'KFMod.DamTypeTrenchgun' |
|
alwaysScale(15) = class'KFMod.DamTypeHuskGun' |
|
alwaysScale(16) = class'KFMod.DamTypeCrossbow' |
|
alwaysScale(17) = class'KFMod.DamTypeCrossbowHeadShot' |
|
alwaysScale(18) = class'KFMod.DamTypeM99SniperRifle' |
|
alwaysScale(19) = class'KFMod.DamTypeM99HeadShot' |
|
alwaysScale(20) = class'KFMod.DamTypeShotgun' |
|
alwaysScale(21) = class'KFMod.DamTypeNailGun' |
|
alwaysScale(22) = class'KFMod.DamTypeDBShotgun' |
|
alwaysScale(23) = class'KFMod.DamTypeKSGShotgun' |
|
alwaysScale(24) = class'KFMod.DamTypeBenelli' |
|
alwaysScale(25) = class'KFMod.DamTypeSPGrenade' |
|
alwaysScale(26) = class'KFMod.DamTypeSPGrenadeImpact' |
|
alwaysScale(27) = class'KFMod.DamTypeSeekerSixRocket' |
|
alwaysScale(28) = class'KFMod.DamTypeSeekerRocketImpact' |
|
alwaysScale(29) = class'KFMod.DamTypeSealSquealExplosion' |
|
alwaysScale(30) = class'KFMod.DamTypeRocketImpact' |
|
alwaysScale(31) = class'KFMod.DamTypeBlowerThrower' |
|
alwaysScale(32) = class'KFMod.DamTypeSPShotgun' |
|
alwaysScale(33) = class'KFMod.DamTypeZEDGun' |
|
alwaysScale(34) = class'KFMod.DamTypeZEDGunMKII' |
|
} |