diff --git a/Source/Game/SwatEquipment/Classes/Bases/Shotgun.uc b/Source/Game/SwatEquipment/Classes/Bases/Shotgun.uc index 358b60d8..1f3dd646 100644 --- a/Source/Game/SwatEquipment/Classes/Bases/Shotgun.uc +++ b/Source/Game/SwatEquipment/Classes/Bases/Shotgun.uc @@ -32,8 +32,6 @@ simulated function bool HandleBallisticImpact( Material HitMaterial, ESkeletalRegion HitRegion, out float Momentum, - out float KillEnergy, - out int BulletType, vector ExitLocation, vector ExitNormal, Material ExitMaterial @@ -106,8 +104,6 @@ simulated function bool HandleBallisticImpact( HitMaterial, HitRegion, Momentum, - KillEnergy, - BulletType, ExitLocation, ExitNormal, ExitMaterial); diff --git a/Source/Unreal/Engine/Classes/Equipment/Ammunition.uc b/Source/Unreal/Engine/Classes/Equipment/Ammunition.uc index 0d3d42a3..a9155f5c 100644 --- a/Source/Unreal/Engine/Classes/Equipment/Ammunition.uc +++ b/Source/Unreal/Engine/Classes/Equipment/Ammunition.uc @@ -109,8 +109,6 @@ simulated function bool CanRicochet(Actor Victim, vector HitLocation, vector Hit simulated function float GetRicochetMomentumModifier(); simulated function float GetDrag(); simulated function float GetMinimumMomentum() { assert(false); return 0; } // subclasses must implement -simulated function int GetAmmoType(); -simulated function int GetBulletType(); simulated function int GetPenetrationLevel(); simulated function int GetPenetrationType(); diff --git a/Source/Unreal/Engine/Classes/Equipment/Bases/SwatAmmo.uc b/Source/Unreal/Engine/Classes/Equipment/Bases/SwatAmmo.uc index cdc1d82f..2592aa2c 100644 --- a/Source/Unreal/Engine/Classes/Equipment/Bases/SwatAmmo.uc +++ b/Source/Unreal/Engine/Classes/Equipment/Bases/SwatAmmo.uc @@ -77,7 +77,6 @@ var(Ricochet) config float RicochetMinimumMomentum "Minimum momentum required to // Advanced ballstics for Elite Force var(AdvancedBallistics) config AmmoType BulletClass "What ammo type I am?"; -var int BulletType "Internal measure to know the BulletClass"; var(AdvancedBallistics) config PenetrationLevel ArmorPenetration "What level of armor can I go through?"; var int PenetrationType "Internal measure to know the BulletClass"; @@ -130,165 +129,12 @@ simulated function float GetRicochetMomentumModifier() { simulated function float GetDrag() { return Drag; } -simulated function int GetAmmoType() - { - return BulletClass; - } - + simulated function int GetPenetrationLevel() { return ArmorPenetration; } - -simulated function int GetBulletType() - { - switch(BulletClass) - { - case AmmoType_9mmAP: - BulletType = 1; - break; - case AmmoType_9mmFMJ: - BulletType = 2; - break; - case AmmoType_9mmJSP: - BulletType = 3; - break; - case AmmoType_9mmJHP: - BulletType = 4; - break; - case AmmoType_45AP: - BulletType = 5; - break; - case AmmoType_45FMJ: - BulletType = 6; - break; - case AmmoType_45JSP: - BulletType = 7; - break; - case AmmoType_45JHP: - BulletType = 8; - break; - case AmmoType_357AP: - BulletType = 9; - break; - case AmmoType_357FMJ: - BulletType = 10; - break; - case AmmoType_357JSP: - BulletType = 11; - break; - case AmmoType_357JHP: - BulletType = 12; - break; - case AmmoType_57AP: - BulletType = 13; - break; - case AmmoType_57FMJ: - BulletType = 14; - break; - case AmmoType_57JSP: - BulletType = 15; - break; - case AmmoType_57JHP: - BulletType = 16; - break; - case AmmoType_50AP: - BulletType = 17; - break; - case AmmoType_50FMJ: - BulletType = 18; - break; - case AmmoType_50JSP: - BulletType = 19; - break; - case AmmoType_50JHP: - BulletType = 20; - break; - case AmmoType_32AP: - BulletType = 21; - break; - case AmmoType_32FMJ: - BulletType = 22; - break; - case AmmoType_32JSP: - BulletType = 23; - break; - case AmmoType_32JHP: - BulletType = 24; - break; - case AmmoType_223AP: - BulletType = 25; - break; - case AmmoType_223FMJ: - BulletType = 26; - break; - case AmmoType_223JSP: - BulletType = 27; - break; - case AmmoType_223JHP: - BulletType = 28; - break; - case AmmoType_762AP: - BulletType = 29; - break; - case AmmoType_762FMJ: - BulletType = 30; - break; - case AmmoType_762JSP: - BulletType = 31; - break; - case AmmoType_762JHP: - BulletType = 32; - break; - case AmmoType_308AP: - BulletType = 33; - break; - case AmmoType_308FMJ: - BulletType = 34; - break; - case AmmoType_308JSP: - BulletType = 35; - break; - case AmmoType_308JHP: - BulletType = 36; - break; - case AmmoType_545AP: - BulletType = 37; - break; - case AmmoType_545FMJ: - BulletType = 38; - break; - case AmmoType_545JSP: - BulletType = 39; - break; - case AmmoType_545JHP: - BulletType = 40; - break; - case AmmoType_ArmorPiercing: - BulletType = 41; - break; - case AmmoType_FullMetalJacket: - BulletType = 42; - break; - case AmmoType_JacketedSoftPoint: - BulletType = 43; - break; - case AmmoType_JacketedHollowPoint: - BulletType = 44; - break; - case AmmoType_Buckshot: - BulletType = 45; - break; - case AmmoType_Special: - BulletType = 46; - break; - default: - BulletType = 42; - } - - return BulletType; - } - + simulated function int GetPenetrationType() { switch(ArmorPenetration) diff --git a/Source/Unreal/Engine/Classes/Equipment/Bases/SwatWeapon.uc b/Source/Unreal/Engine/Classes/Equipment/Bases/SwatWeapon.uc index ef4f062a..d48aa67c 100644 --- a/Source/Unreal/Engine/Classes/Equipment/Bases/SwatWeapon.uc +++ b/Source/Unreal/Engine/Classes/Equipment/Bases/SwatWeapon.uc @@ -1,5 +1,5 @@ class SwatWeapon extends FiredWeapon - config(SwatEquipment); + config(SwatEquipment); /* * Describes which "equip type" a weapon is a part of. @@ -7,9 +7,9 @@ class SwatWeapon extends FiredWeapon */ enum WeaponEquipType { - WeaponEquip_PrimaryOnly, - WeaponEquip_SecondaryOnly, - WeaponEquip_Either + WeaponEquip_PrimaryOnly, + WeaponEquip_SecondaryOnly, + WeaponEquip_Either }; /* @@ -19,17 +19,17 @@ enum WeaponEquipType */ enum WeaponEquipClass { - WeaponClass_Uncategorized, // Not categorized! Find one! - WeaponClass_AssaultRifle, // Assault Rifles (M4, M16, AKM, etc.) - WeaponClass_MarksmanRifle, // Marksman Rifles (scoped rifles) - WeaponClass_SubmachineGun, // Submachine Guns (MP5, G36C, Uzi, etc.) - WeaponClass_Shotgun, // Shotguns (M4, Nova, M870, BSG) - WeaponClass_LightMachineGun, // Light Machine Guns (M249 SAW) - WeaponClass_MachinePistol, // Machine Pistols; SMGs that don't have a stock (MP5K, TEC-9) - WeaponClass_Pistol, // Pistols (Desert Eagle, M1911, Glock, ... but not tasers!) - WeaponClass_LessLethal, // Less-lethal shotguns, tasers, and pepperball - WeaponClass_GrenadeLauncher, // Grenade Launchers (ARWEN 37, HK69) - WeaponClass_NoCategory, // No category (No Weapon) + WeaponClass_Uncategorized, // Not categorized! Find one! + WeaponClass_AssaultRifle, // Assault Rifles (M4, M16, AKM, etc.) + WeaponClass_MarksmanRifle, // Marksman Rifles (scoped rifles) + WeaponClass_SubmachineGun, // Submachine Guns (MP5, G36C, Uzi, etc.) + WeaponClass_Shotgun, // Shotguns (M4, Nova, M870, BSG) + WeaponClass_LightMachineGun, // Light Machine Guns (M249 SAW) + WeaponClass_MachinePistol, // Machine Pistols; SMGs that don't have a stock (MP5K, TEC-9) + WeaponClass_Pistol, // Pistols (Desert Eagle, M1911, Glock, ... but not tasers!) + WeaponClass_LessLethal, // Less-lethal shotguns, tasers, and pepperball + WeaponClass_GrenadeLauncher, // Grenade Launchers (ARWEN 37, HK69) + WeaponClass_NoCategory, // No category (No Weapon) }; /* @@ -37,36 +37,36 @@ enum WeaponEquipClass */ enum WeaponAimAnimationType { - WeaponAnimAim_Handgun, - WeaponAnimAim_SubmachineGun, - WeaponAnimAim_MachineGun, - WeaponAnimAim_Shotgun, - WeaponAnimAim_Grenade, - WeaponAnimAim_TacticalAid, - WeaponAnimAim_TacticalAidUse, - WeaponAnimAim_PepperSpray, - WeaponAnimAim_M4, - WeaponAnimAim_UMP, - WeaponAnimAim_P90, - WeaponAnimAim_Optiwand, - WeaponAnimAim_Paintball, - WeaponAnimAim_Cuffed + WeaponAnimAim_Handgun, + WeaponAnimAim_SubmachineGun, + WeaponAnimAim_MachineGun, + WeaponAnimAim_Shotgun, + WeaponAnimAim_Grenade, + WeaponAnimAim_TacticalAid, + WeaponAnimAim_TacticalAidUse, + WeaponAnimAim_PepperSpray, + WeaponAnimAim_M4, + WeaponAnimAim_UMP, + WeaponAnimAim_P90, + WeaponAnimAim_Optiwand, + WeaponAnimAim_Paintball, + WeaponAnimAim_Cuffed }; enum WeaponLowReadyAnimationType { - WeaponAnimLowReady_Handgun, - WeaponAnimLowReady_SubmachineGun, - WeaponAnimLowReady_MachineGun, - WeaponAnimLowReady_Shotgun, - WeaponAnimLowReady_Grenade, - WeaponAnimLowReady_TacticalAid, - WeaponAnimLowReady_PepperSpray, - WeaponAnimLowReady_M4, - WeaponAnimLowReady_UMP, - WeaponAnimLowReady_P90, - WeaponAnimLowReady_Optiwand, - WeaponAnimLowReady_Paintball + WeaponAnimLowReady_Handgun, + WeaponAnimLowReady_SubmachineGun, + WeaponAnimLowReady_MachineGun, + WeaponAnimLowReady_Shotgun, + WeaponAnimLowReady_Grenade, + WeaponAnimLowReady_TacticalAid, + WeaponAnimLowReady_PepperSpray, + WeaponAnimLowReady_M4, + WeaponAnimLowReady_UMP, + WeaponAnimLowReady_P90, + WeaponAnimLowReady_Optiwand, + WeaponAnimLowReady_Paintball }; /* @@ -75,18 +75,18 @@ enum WeaponLowReadyAnimationType enum EIdleWeaponStatus { IdleWeaponDoesNotMatter, - IdleWithSAW, - IdleWithMachineGun, + IdleWithSAW, + IdleWithMachineGun, IdleWithG36, IdleWithSubMachineGun, IdleWithUMP, - IdleWithHandgun, + IdleWithHandgun, IdleWithShotgun, IdleWithPaintballGun, IdleWithGrenade, - IdleWithP90, + IdleWithP90, IdleWithAnyWeapon, - IdleWithoutWeapon + IdleWithoutWeapon }; /* @@ -94,11 +94,11 @@ enum EIdleWeaponStatus */ enum EComplianceWeaponAnimation { - Compliance_Machinegun, - Compliance_Shotgun, - Compliance_SubmachineGun, - Compliance_CSBallLauncher, - Compliance_Handgun + Compliance_Machinegun, + Compliance_Shotgun, + Compliance_SubmachineGun, + Compliance_CSBallLauncher, + Compliance_Handgun }; /* @@ -107,8 +107,8 @@ enum EComplianceWeaponAnimation */ struct WeaponVariant { - var localized string VariantName; - var class VariantClass; + var localized string VariantName; + var class VariantClass; }; var() localized config string ShortName; @@ -159,14 +159,6 @@ var(AdvancedDescription) protected localized config string RateOfFire var(Categorization) public config WeaponEquipClass WeaponCategory "Which category this weapon belongs to in the GUI."; var(Categorization) public config WeaponEquipType AllowedSlots "Which slots this weapon is allowed to be equipped in"; -// New Damage Information -var(Damage) protected config float Vc0 "Muzzle Velocity of the weapon"; -var(Damage) protected config float Vc1 "Diference between muzzle velocity and velocity at 50m ((Muzzle Velocity/Velocity at 50m)*-1)"; -var(Damage) protected config float Vc2 "Last Velocity factor ((Velocity at 50m-(Muzzle Velocity+(Vc1*50m)))/(50m^2))"; -var(Damage) protected config float Dc1 "Proportion between energy at 50m and muzzle velocity (Energy at 50m/(Muzzle Velocity*3.28084))"; -var(Damage) protected config float Dc2 "Last damage factor ((Dc0-(Dc1*Velocity at 50m))/(Velocity at 50m^2))"; -var(Damage) protected config bool bUsesBullets; - // New recoil stuff as of V7 var(Recoil) protected config float AutoRecoilBase; var(Recoil) protected config float AutoRecoilPerShot; @@ -218,146 +210,126 @@ static function string GetShortName() { return default.ShortName; } // increasingly severe the longer that we hold down the trigger. simulated function float GetAutoRecoilMagnitude() { - local float RecoilModifier; - local float RecoilBase; - local PlayerController PlayerController; - local Pawn PawnOwner; - - PawnOwner = Pawn(Owner); - - PlayerController = PlayerController(PawnOwner.Controller); - if(PlayerController != None && PlayerController.WantsZoom) - { - RecoilBase = ZoomedAutoRecoilPerShot; - } - else - { - RecoilBase = AutoRecoilPerShot; - } - - RecoilModifier = 1.0f; - if(PawnOwner.GetNumberOfArmsInjured() == 2) - { - RecoilModifier = ArmInjuryDoubleRecoilModifier; - } - else if(PawnOwner.GetNumberOfArmsInjured() == 1) - { - RecoilModifier = ArmInjurySingleRecoilModifier; - } - - return RecoilBase * RecoilModifier; + local float RecoilModifier; + local float RecoilBase; + local PlayerController PlayerController; + local Pawn PawnOwner; + + PawnOwner = Pawn(Owner); + + PlayerController = PlayerController(PawnOwner.Controller); + if(PlayerController != None && PlayerController.WantsZoom) + { + RecoilBase = ZoomedAutoRecoilPerShot; + } + else + { + RecoilBase = AutoRecoilPerShot; + } + + RecoilModifier = 1.0f; + if(PawnOwner.GetNumberOfArmsInjured() == 2) + { + RecoilModifier = ArmInjuryDoubleRecoilModifier; + } + else if(PawnOwner.GetNumberOfArmsInjured() == 1) + { + RecoilModifier = ArmInjurySingleRecoilModifier; + } + + return RecoilBase * RecoilModifier; } // Get the amount of recoil from an individual bullet, // taking the current firing mode into account. simulated function float GetPerBurstRecoilMagnitude() { - local float RecoilModifier; - local float RecoilBase; - local Pawn PawnOwner; - local PlayerController PlayerController; - - PawnOwner = Pawn(Owner); - PlayerController = PlayerController(PawnOwner.Controller); - if(PlayerController != None && PlayerController.WantsZoom) - { - if(CurrentFireMode == FireMode_Burst) - { - RecoilBase = ZoomedBurstRecoilBase; - } - else if(CurrentFireMode == FireMode_Auto) - { - RecoilBase = ZoomedAutoRecoilBase; - } - else - { - RecoilBase = ZoomedSemiRecoilBase; - } - } - else - { - if(CurrentFireMode == FireMode_Burst) - { - RecoilBase = BurstRecoilBase; - } - else if(CurrentFireMode == FireMode_Auto) - { - RecoilBase = AutoRecoilBase; - } - else - { - RecoilBase = SemiRecoilBase; - } - } - - RecoilModifier = 1.0f; - if(PawnOwner.GetNumberOfArmsInjured() == 2) - { - RecoilModifier = ArmInjuryDoubleRecoilModifier; - } - else if(PawnOwner.GetNumberOfArmsInjured() == 1) - { - RecoilModifier = ArmInjurySingleRecoilModifier; - } - - return RecoilBase * RecoilModifier; + local float RecoilModifier; + local float RecoilBase; + local Pawn PawnOwner; + local PlayerController PlayerController; + + PawnOwner = Pawn(Owner); + PlayerController = PlayerController(PawnOwner.Controller); + if(PlayerController != None && PlayerController.WantsZoom) + { + if(CurrentFireMode == FireMode_Burst) + { + RecoilBase = ZoomedBurstRecoilBase; + } + else if(CurrentFireMode == FireMode_Auto) + { + RecoilBase = ZoomedAutoRecoilBase; + } + else + { + RecoilBase = ZoomedSemiRecoilBase; + } + } + else + { + if(CurrentFireMode == FireMode_Burst) + { + RecoilBase = BurstRecoilBase; + } + else if(CurrentFireMode == FireMode_Auto) + { + RecoilBase = AutoRecoilBase; + } + else + { + RecoilBase = SemiRecoilBase; + } + } + + RecoilModifier = 1.0f; + if(PawnOwner.GetNumberOfArmsInjured() == 2) + { + RecoilModifier = ArmInjuryDoubleRecoilModifier; + } + else if(PawnOwner.GetNumberOfArmsInjured() == 1) + { + RecoilModifier = ArmInjurySingleRecoilModifier; + } + + return RecoilBase * RecoilModifier; } simulated function float GetWeight() { - return Weight; + return Weight; } simulated function float GetBulk() { - return Bulk; + return Bulk; } simulated function float GetChoke() { - return Choke; + return Choke; } simulated function float GetVc0() { - return default.MuzzleVelocity / 50.4725; -} - -simulated function float GetVc1() -{ - return Vc1; -} - -simulated function float GetVc2() -{ - return Vc2; -} - -simulated function float GetDc1() -{ - return Dc1; -} - -simulated function float GetDc2() -{ - return Dc2; + return default.MuzzleVelocity / 50.4725; } simulated function bool GetUsesRedDotSight() { - return bUsesRedDotSight; + return bUsesRedDotSight; } simulated function bool ShouldHideCrosshairsInIronsights() { - return !ShowCrosshairInIronsights; + return !ShowCrosshairInIronsights; } simulated function bool ShouldWalkInIronsights() { - return WalkInIronsights; + return WalkInIronsights; } simulated function UpdateAmmoDisplay() { - Ammo.UpdateHUD(); + Ammo.UpdateHUD(); } function bool ShouldIgnoreDisabledZoom() @@ -372,189 +344,157 @@ static function bool IsUsableByPlayer() static function string GetManufacturer() { - return "Manufacturer: "$default.Manufacturer; + return "Manufacturer: "$default.Manufacturer; } static function string GetCaliber() { - return "Caliber: "$default.Caliber; + return "Caliber: "$default.Caliber; } static function string GetCountryOfOrigin() { - return "Country of Origin: "$default.CountryOfOrigin; + return "Country of Origin: "$default.CountryOfOrigin; } static function string GetMagSize() { - if(default.MagazineSize != 0) { - return "Magazine Size: "$string(default.MagazineSize); - } - return "Magazine Size: "$default.MagazineSizeString; + if (default.MagazineSize != 0) { + return "Magazine Size: "$string(default.MagazineSize); + } + return "Magazine Size: "$default.MagazineSizeString; } static function string GetProductionStart() { - return "Started Production: "$default.ProductionStart; + return "Started Production: "$default.ProductionStart; } static function string GetFireModes() { - return "Fire Modes: "$default.FireModes; + return "Fire Modes: "$default.FireModes; } static function string GetMuzzleVelocityString() { - // AK-47 has muzzle velocity (ingame) of 47,404 units and this is confirmed accurate - // In reality it fires at 715 m/s (2,350 ft/s) - // Therefore by multiplying by ~0.015 you can get meters and 0.05 for feet - local int metersPerSecond, feetPerSecond; - local string metersPerSecondStr, feetPerSecondStr; - metersPerSecond = default.MuzzleVelocity / 50.4725; - feetPerSecond = default.MuzzleVelocity / 15.385; - metersPerSecondStr = string(metersPerSecond); - feetPerSecondStr = string(feetPerSecond); - - return "Muzzle Velocity: "$feetPerSecondStr$" ft/s ("$metersPerSecondStr$" m/s)"; + // AK-47 has muzzle velocity (ingame) of 47,404 units and this is confirmed accurate + // In reality it fires at 715 m/s (2,350 ft/s) + // Therefore by multiplying by ~0.015 you can get meters and 0.05 for feet + local int metersPerSecond, feetPerSecond; + local string metersPerSecondStr, feetPerSecondStr; + metersPerSecond = default.MuzzleVelocity / 50.4725; + feetPerSecond = default.MuzzleVelocity / 15.385; + metersPerSecondStr = string(metersPerSecond); + feetPerSecondStr = string(feetPerSecond); + + return "Muzzle Velocity: "$feetPerSecondStr$" ft/s ("$metersPerSecondStr$" m/s)"; } static function string GetRateOfFire() { - return "Rate of Fire: "$default.RateOfFire; + return "Rate of Fire: "$default.RateOfFire; } static function string GetTotalAmmoString() { - return "Maximum Ammo: "$default.TotalAmmoString; + return "Maximum Ammo: "$default.TotalAmmoString; } simulated function BallisticFire(vector StartTrace, vector EndTrace) { local vector HitLocation, HitNormal, ExitLocation, ExitNormal; local actor Victim; - local Material HitMaterial, ExitMaterial; //material on object that was hit - local float Momentum; - local float Distance; - local float ActualVelocity; - local float VelocityRatio; - local float Velocity; - local float KillEnergy; - local int BulletType; - local ESkeletalRegion HitRegion; - - Momentum = MuzzleVelocity * Ammo.Mass; - BulletType = Ammo.GetBulletType(); - Distance = (VSize(HitLocation - StartTrace)) / 50.4725; - Velocity = ((GetVc0()) + ((GetVc1()) * Distance)+((GetVc2()) * (Distance * Distance))); - KillEnergy = ((GetDc1()) * Velocity)+((GetDc2()) * (Velocity * Velocity)); - - Ammo.BallisticsLog("BallisticFire(): Weapon "$name - $", shot by "$Owner.name - $", has MuzzleVelocity="$MuzzleVelocity - $", Ammo "$Ammo.name - $", Class "$BulletType - $" has Mass="$Ammo.Mass - $". Initial Momentum is "$Momentum - $". Velocity is "$Velocity - $". Kill Energy is "$KillEnergy - $". Target is at "$Distance - $"m."); - - foreach TraceActors( - class'Actor', - Victim, - HitLocation, - HitNormal, - HitMaterial, - EndTrace, - StartTrace, - /*optional extent*/, - true, //bSkeletalBoxTest - HitRegion, - true, //bGetMaterial - true, //bFindExitLocation - ExitLocation, - ExitNormal, - ExitMaterial ) - { -// Ammo.BallisticsLog("IMPACT: Momentum before drag: "$Momentum); -// Momentum -= Ammo.GetDrag() * VSize(HitLocation - StartTrace); -// Ammo.BallisticsLog("IMPACT: Momentum after drag: "$Momentum); - - Ammo.BallisticsLog("IMPACT: KillEnergy before calculating penetration: "$KillEnergy); - ActualVelocity = Momentum / Ammo.Mass; - VelocityRatio = ActualVelocity / MuzzleVelocity; - KillEnergy *= VelocityRatio; - Ammo.BallisticsLog("IMPACT: KillEnergy before calculating penetration: "$KillEnergy); - - if(Momentum < 0.0) { - Ammo.BallisticsLog("Momentum went < 0. Not impacting with anything (LOST BULLET)"); - break; - } - - //handle each ballistic impact until the bullet runs out of momentum and does not penetrate - if (Ammo.CanRicochet(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, Momentum, 0)) { - // Do a ricochet - DoBulletRicochet(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, Momentum, KillEnergy, BulletType, 0); - break; - } - else if (!HandleBallisticImpact(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, HitRegion, Momentum, KillEnergy, BulletType, ExitLocation, ExitNormal, ExitMaterial)) - break; - } + local Material HitMaterial, ExitMaterial; //material on object that was hit + local float Momentum; + local float Distance; + local ESkeletalRegion HitRegion; + + Momentum = MuzzleVelocity * Ammo.Mass; + Distance = (VSize(HitLocation - StartTrace)) / 50.4725; + + Ammo.BallisticsLog("BallisticFire(): Weapon "$name + $", shot by "$Owner.name + $", has MuzzleVelocity="$MuzzleVelocity + $", Ammo "$Ammo.name + $" has Mass="$Ammo.Mass + $". Initial Momentum is "$Momentum + $". Target is at "$Distance + $"m."); + + foreach TraceActors( + class'Actor', + Victim, + HitLocation, + HitNormal, + HitMaterial, + EndTrace, + StartTrace, + /*optional extent*/, + true, //bSkeletalBoxTest + HitRegion, + true, //bGetMaterial + true, //bFindExitLocation + ExitLocation, + ExitNormal, + ExitMaterial ) + { + + if(Momentum < 0.0) { + Ammo.BallisticsLog("Momentum went < 0. Not impacting with anything (LOST BULLET)"); + break; + } + + //handle each ballistic impact until the bullet runs out of momentum and does not penetrate + if (Ammo.CanRicochet(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, Momentum, 0)) { + // Do a ricochet + DoBulletRicochet(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, Momentum, 0); + break; + } + else if (!HandleBallisticImpact(Victim, HitLocation, HitNormal, Normal(HitLocation - StartTrace), HitMaterial, HitRegion, Momentum, ExitLocation, ExitNormal, ExitMaterial)) + break; + } } simulated function bool HandleBallisticImpact( - Actor Victim, - vector HitLocation, - vector HitNormal, - vector NormalizedBulletDirection, - Material HitMaterial, - ESkeletalRegion HitRegion, - out float Momentum, - out float KillEnergy, - out int BulletType, - vector ExitLocation, - vector ExitNormal, - Material ExitMaterial - ) + Actor Victim, + vector HitLocation, + vector HitNormal, + vector NormalizedBulletDirection, + Material HitMaterial, + ESkeletalRegion HitRegion, + out float Momentum, + vector ExitLocation, + vector ExitNormal, + Material ExitMaterial + ) { - local float MomentumToPenetrateVictim; - local float MomentumLostToVictim; - local vector MomentumVector; - local bool PenetratesVictim; - local int Damage; - local float KillChance; + local float MomentumToPenetrateVictim; + local float MomentumLostToVictim; + local vector MomentumVector; + local bool PenetratesVictim; + local int Damage; + local float KillChance; local float RandomChance; - local float ActualVelocity; - local float VelocityRatio; - local float OriginalKillEnergy; - local float StartingKillEnergy; - local SkeletalRegionInformation SkeletalRegionInformation; - local ProtectiveEquipment Protection; - local int ArmorLevel; - local int BulletLevel; - local float WoundChance; - local float DamageModifier, ExternalDamageModifier; - local float LimbInjuryAimErrorPenalty; - local IHaveSkeletalRegions SkelVictim; - local Pawn PawnVictim; + local SkeletalRegionInformation SkeletalRegionInformation; + local ProtectiveEquipment Protection; + local float WoundChance; + local float DamageModifier, ExternalDamageModifier; + local float LimbInjuryAimErrorPenalty; + local IHaveSkeletalRegions SkelVictim; + local Pawn PawnVictim; local PlayerController OwnerPC; - BulletType = Ammo.GetBulletType(); - ArmorLevel = Protection.GetProtectionType(); - BulletLevel = Ammo.GetPenetrationType(); - - // You shouldn't be able to hit hidden actors that block zero-extent - // traces (i.e., projectors, blocking volumes). However, the 'Victim' - // when you hit BSP is LevelInfo, which is hidden, so we have to - // handle that as a special case. - if ((Victim.bHidden || Victim.DrawType == DT_None) && !(Victim.IsA('LevelInfo'))) - { - Ammo.BallisticsLog("BallisticFire: Skipping bHidden=true Victim "$Victim.Name$" of class "$Victim.class.name); - return true; //penetrates, no damage or momentum lost - } - - if (Victim.IsA('SwatDoor') || Victim.Owner.IsA('SwatDoor')) //Handle this case on its own, because we dont wanna trigger the skeletal hit, we do that in the shotgun code - { //We also still wanna draw the decals + // You shouldn't be able to hit hidden actors that block zero-extent + // traces (i.e., projectors, blocking volumes). However, the 'Victim' + // when you hit BSP is LevelInfo, which is hidden, so we have to + // handle that as a special case. + if ((Victim.bHidden || Victim.DrawType == DT_None) && !(Victim.IsA('LevelInfo'))) + { + Ammo.BallisticsLog("BallisticFire: Skipping bHidden=true Victim "$Victim.Name$" of class "$Victim.class.name); + return true; //penetrates, no damage or momentum lost + } + + if (Victim.IsA('SwatDoor') || Victim.Owner.IsA('SwatDoor')) //Handle this case on its own, because we dont wanna trigger the skeletal hit, we do that in the shotgun code + { //We also still wanna draw the decals return HandleDoorImpact(Victim, HitLocation, HitNormal, HitMaterial, ExitLocation, ExitNormal, ExitMaterial); } @@ -562,813 +502,389 @@ simulated function bool HandleBallisticImpact( if (Owner.IsA('SwatOfficer') && (Victim.IsA('SwatOfficer') || (Victim.IsA('SwatPlayer') && !Pawn(Owner).IsAttackingPlayer()))) { - Ammo.BallisticsLog("BallisticFire: Skipping Victim "$Victim.Name$" of class "$Victim.class.name$" because officers shouldn't hit other friendly officers/players"); + Ammo.BallisticsLog("BallisticFire: Skipping Victim "$Victim.Name$" of class "$Victim.class.name$" because officers shouldn't hit other friendly officers/players"); return false; //friendly fire... blocked, no effects } - // Some dynamic actors are not rendered due to the player's - // detail settings being too low. In this case they should not block - // bullets, to keep the visual experience consistent. + // Some dynamic actors are not rendered due to the player's + // detail settings being too low. In this case they should not block + // bullets, to keep the visual experience consistent. if( (Victim.bHighDetail && Level.DetailMode == DM_Low) - || (Victim.bSuperHighDetail && Level.DetailMode != DM_SuperHigh)) - { - Ammo.BallisticsLog("BallisticFire: Skipping Victim "$Victim.Name$" of class "$Victim.class.name$ - " because Level.DetailMode="$GetEnum(EDetailMode, Level.DetailMode)$ - " and Victim.bHighDetail="$Victim.bHighDetail$ - " and Victim.bSuperHighDetail="$Victim.bSuperHighDetail); - return true; //penetrates, no damage or momentum lost - } - - //play effects at the point of impact - Ammo.SetLocation(HitLocation); - Ammo.SetRotation(rotator(HitNormal)); - - // Normal TraceActors() collection of material doesn't work quite right for - // skeletal meshes, so we call this helper function to get the material manually. - if (Victim.DrawType == DT_Mesh) - { - HitMaterial = Victim.GetCurrentMaterial(0); // get skin at first index - ExitMaterial = HitMaterial; - - //if the Victim has skeletal regions, do some more work - if (HitRegion != REGION_None && Victim.IsA('IHaveSkeletalRegions')) - { - //if the Victim is protected at the impacted region then handle an impact with ProtectiveEquipment - - if (Victim.IsA('ICanUseProtectiveEquipment')) - { - SkeletalRegionInformation = ICanUseProtectiveEquipment(Victim).GetSkeletalRegionInformation(HitRegion); - Protection = ICanUseProtectiveEquipment(Victim).GetSkeletalRegionProtection(HitRegion); - - if (Protection != None) - { - Ammo.TriggerEffectEvent('BulletHit', Protection, HitMaterial); - if (!HandleProtectiveEquipmentBallisticImpact( - Victim, - Protection, - HitRegion, - HitLocation, - HitNormal, - NormalizedBulletDirection, - Momentum, - KillEnergy, - BulletType, - ArmorLevel, - BulletLevel)) - return false; //blocked by ProtectiveEquipment - } - } - } - } - - if (HitMaterial == None) // weird situation, should trigger FX but not block the bullet (or should it?) - { - Ammo.BallisticsLog("[WARNING!!] BallisticFire: Trace hit Victim "$Victim$" of class "$Victim.class.name$", HitMaterial is None, treating as if no momentum required to penetrate."); - MomentumLostToVictim = 0; - } - else - if (Victim.class.name == 'LevelInfo' || Ammo.RoundsNeverPenetrate) - { - MomentumToPenetrateVictim = Momentum; - MomentumLostToVictim = Momentum; - } - else - { - MomentumToPenetrateVictim = Victim.GetMomentumToPenetrate(HitLocation, HitNormal, HitMaterial); - MomentumLostToVictim = FMin(Momentum, MomentumToPenetrateVictim); - } - - //the bullet will penetrate the victim unles it loses all of its momentum to the victim - PenetratesVictim = (MomentumLostToVictim < Momentum); - - //calculate damage imparted to victim - Damage = MomentumLostToVictim * Level.GetRepo().MomentumToDamageConversionFactor; - - //calculate momentum vector imparted to victim - MomentumVector = NormalizedBulletDirection * MomentumLostToVictim; - if (PenetratesVictim) - MomentumVector *= Level.getRepo().MomentumImpartedOnPenetrationFraction; - - //consider adding internal damage - if (!PenetratesVictim) - Damage += Ammo.InternalDamage; - - //apply any external damage modifiers (maintained by the Repo) - ExternalDamageModifier = Level.GetRepo().GetExternalDamageModifier( Owner, Victim ); - Damage = int( float(Damage) * ExternalDamageModifier ); + || (Victim.bSuperHighDetail && Level.DetailMode != DM_SuperHigh)) + { + Ammo.BallisticsLog("BallisticFire: Skipping Victim "$Victim.Name$" of class "$Victim.class.name$ + " because Level.DetailMode="$GetEnum(EDetailMode, Level.DetailMode)$ + " and Victim.bHighDetail="$Victim.bHighDetail$ + " and Victim.bSuperHighDetail="$Victim.bSuperHighDetail); + return true; //penetrates, no damage or momentum lost + } - // damage pawns - PawnVictim = Pawn(Victim); - if (Damage <= 0 && SkeletalRegionInformation != None && PawnVictim != None) + //play effects at the point of impact + Ammo.SetLocation(HitLocation); + Ammo.SetRotation(rotator(HitNormal)); + + // Normal TraceActors() collection of material doesn't work quite right for + // skeletal meshes, so we call this helper function to get the material manually. + if (Victim.DrawType == DT_Mesh) { - Damage = 0; - } - if(SkeletalRegionInformation != None && PawnVictim != None && bUsesBullets) - { + HitMaterial = Victim.GetCurrentMaterial(0); // get skin at first index + ExitMaterial = HitMaterial; - // dbeswick: stats - OwnerPC = PlayerController(Pawn(Owner).Controller); - if (OwnerPC != None) + //if the Victim has skeletal regions, do some more work + if (HitRegion != REGION_None && Victim.IsA('IHaveSkeletalRegions')) { - OwnerPC.Stats.Hit(class.Name, PlayerController(PawnVictim.Controller)); - } + //if the Victim is protected at the impacted region then handle an impact with ProtectiveEquipment - // Give chances based on the part hit - if (HitRegion == REGION_Head) - WoundChance = 1; - - if (HitRegion == REGION_Torso) + if (Victim.IsA('ICanUseProtectiveEquipment')) { - switch(BulletType) + SkeletalRegionInformation = ICanUseProtectiveEquipment(Victim).GetSkeletalRegionInformation(HitRegion); + Protection = ICanUseProtectiveEquipment(Victim).GetSkeletalRegionProtection(HitRegion); + + if (Protection != None) { - case 1: - WoundChance = 280; - break; - case 2: - WoundChance = 140; - break; - case 3: - WoundChance = 120; - break; - case 4: - WoundChance = 100; - break; - case 5: - WoundChance = 195; - break; - case 6: - WoundChance = 125; - break; - case 7: - WoundChance = 100; - break; - case 8: - WoundChance = 70; - break; - case 9: - WoundChance = 300; - break; - case 10: - WoundChance = 120; - break; - case 11: - WoundChance = 90; - break; - case 12: - WoundChance = 65; - break; - case 13: - WoundChance = 150; - break; - case 14: - WoundChance = 70; - break; - case 15: - WoundChance = 60; - break; - case 16: - WoundChance = 50; - break; - case 17: - WoundChance = 715; - break; - case 18: - WoundChance = 375; - break; - case 19: - WoundChance = 330; - break; - case 20: - WoundChance = 250; - break; - case 21: - WoundChance = 100; - break; - case 22: - WoundChance = 60; - break; - case 23: - WoundChance = 50; - break; - case 24: - WoundChance = 45; - break; - case 25: - WoundChance = 620; - break; - case 26: - WoundChance = 220; - break; - case 27: - WoundChance = 180; - break; - case 28: - WoundChance = 155; - break; - case 29: - WoundChance = 845; - break; - case 30: - WoundChance = 400; - break; - case 31: - WoundChance = 350; - break; - case 32: - WoundChance = 300; - break; - case 33: - WoundChance = 850; - break; - case 34: - WoundChance = 300; - break; - case 35: - WoundChance = 245; - break; - case 36: - WoundChance = 200; - break; - case 37: - WoundChance = 650; - break; - case 38: - WoundChance = 330; - break; - case 39: - WoundChance = 245; - break; - case 40: - WoundChance = 200; - break; - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - WoundChance = 100; - break; - default: - WoundChance = 100; + Ammo.TriggerEffectEvent('BulletHit', Protection, HitMaterial); + if (!HandleProtectiveEquipmentBallisticImpact( + Victim, + Protection, + HitRegion, + HitLocation, + HitNormal, + NormalizedBulletDirection, + Momentum)) + { + return false; //blocked by ProtectiveEquipment + } } } + } + } - if ((HitRegion == REGION_LeftArm || HitRegion == REGION_RightArm)) - WoundChance = 1350; - if ((HitRegion == REGION_LeftLeg || HitRegion == REGION_RightLeg)) - WoundChance = 600; + if (HitMaterial == None) // weird situation, should trigger FX but not block the bullet (or should it?) + { + Ammo.BallisticsLog("[WARNING!!] BallisticFire: Trace hit Victim "$Victim$" of class "$Victim.class.name$", HitMaterial is None, treating as if no momentum required to penetrate."); + MomentumLostToVictim = 0; + } + else + if (Victim.class.name == 'LevelInfo' || Ammo.RoundsNeverPenetrate) + { + MomentumToPenetrateVictim = Momentum; + MomentumLostToVictim = Momentum; + } + else + { + MomentumToPenetrateVictim = Victim.GetMomentumToPenetrate(HitLocation, HitNormal, HitMaterial); + MomentumLostToVictim = FMin(Momentum, MomentumToPenetrateVictim); + } - //Reset damage First - Damage = 0; + //the bullet will penetrate the victim unles it loses all of its momentum to the victim + PenetratesVictim = (MomentumLostToVictim < Momentum); - OriginalKillEnergy = KillEnergy; + //calculate damage imparted to victim + Damage = MomentumLostToVictim * Level.GetRepo().MomentumToDamageConversionFactor; - log( "Initiating damage system" ); - do - { - KillChance = 1 - (WoundChance / KillEnergy); - RandomChance = 1.0 - FRand(); - log( "The KillEnergy is " $ KillEnergy ); - log( "The KillChance is " $ KillChance ); - log( "The RandomChance is " $ RandomChance ); - if (KillChance <= 0.10) - { - KillChance = 0.10; - } - if (RandomChance < KillChance) - { - Damage += 15; - log( "Victim is wounded. Adding 15 damage points. Actual Damage points are " $ Damage ); - } - else - { - Damage += 5; - log( "Victim is not wounded. Adding 5 damage point. Actual Damage points are " $ Damage ); - } - KillEnergy = KillEnergy - WoundChance; - } - until( KillEnergy <= 0 || RandomChance > KillChance || Damage > 150); - log( "Stopping, RandomChance is higher than kill chance"); - log( "We need to restore the kill energy"); - log("IMPACT: KillEnergy before calculating penetration: "$OriginalKillEnergy); - StartingKillEnergy = OriginalKillEnergy; - ActualVelocity = (Momentum - MomentumLostToVictim) / Ammo.Mass; - VelocityRatio = ActualVelocity / MuzzleVelocity; - OriginalKillEnergy *= VelocityRatio; - KillEnergy = OriginalKillEnergy; - if (KillEnergy <= 0) - { - KillEnergy = 0; - } - log("IMPACT: KillEnergy after calculating penetration: "$KillEnergy); - log( "KillEnergy now is " $ KillEnergy ); - if (StartingKillEnergy <= 0) - { - Damage = 0; - log( "This was pointless because Originally our Kill Energy was 0 or less." ); - } - log( "Final damage is " $ Damage ); - } - if( Damage > 0 && SkeletalRegionInformation != None && PawnVictim != None) - { + //calculate momentum vector imparted to victim + MomentumVector = NormalizedBulletDirection * MomentumLostToVictim; + if (PenetratesVictim) + MomentumVector *= Level.getRepo().MomentumImpartedOnPenetrationFraction; + + //consider adding internal damage + if (!PenetratesVictim) + Damage += Ammo.InternalDamage; + + //apply any external damage modifiers (maintained by the Repo) + ExternalDamageModifier = Level.GetRepo().GetExternalDamageModifier( Owner, Victim ); + Damage = int( float(Damage) * ExternalDamageModifier ); + + // damage pawns + PawnVictim = Pawn(Victim); + if (Damage <= 0 && SkeletalRegionInformation != None && PawnVictim != None) + { + Damage = 0; + } + else + if( Damage > 0 && SkeletalRegionInformation != None && PawnVictim != None) + { // dbeswick: stats OwnerPC = PlayerController(Pawn(Owner).Controller); if (OwnerPC != None) { OwnerPC.Stats.Hit(class.Name, PlayerController(PawnVictim.Controller)); } - if(!bUsesBullets) - { DamageModifier = RandRange(SkeletalRegionInformation.DamageModifier.Min, SkeletalRegionInformation.DamageModifier.Max); - // Give the weapon the chance to override arm specific damage... - if ( OverrideArmDamageModifier != 0 && (HitRegion == REGION_LeftArm || HitRegion == REGION_RightArm) ) - DamageModifier = OverrideArmDamageModifier; - Damage *= DamageModifier; - } + // Give the weapon the chance to override arm specific damage... + if ( OverrideArmDamageModifier != 0 && (HitRegion == REGION_LeftArm || HitRegion == REGION_RightArm) ) + DamageModifier = OverrideArmDamageModifier; + Damage *= DamageModifier; - LimbInjuryAimErrorPenalty = RandRange(SkeletalRegionInformation.AimErrorPenalty.Min, SkeletalRegionInformation.AimErrorPenalty.Max); - PawnVictim.AccumulatedLimbInjury += LimbInjuryAimErrorPenalty; - } + LimbInjuryAimErrorPenalty = RandRange(SkeletalRegionInformation.AimErrorPenalty.Min, SkeletalRegionInformation.AimErrorPenalty.Max); + PawnVictim.AccumulatedLimbInjury += LimbInjuryAimErrorPenalty; + } #if IG_EFFECTS - //don't play hit effects on the sky - if (HitMaterial == None || HitMaterial.MaterialVisualType != MVT_Sky) - { - if (Damage <= 0) - Ammo.AddContextForNextEffectEvent('NoDamage'); - Ammo.TriggerEffectEvent('BulletHit', Victim, HitMaterial); - } + //don't play hit effects on the sky + if (HitMaterial == None || HitMaterial.MaterialVisualType != MVT_Sky) + { + if (Damage <= 0) + Ammo.AddContextForNextEffectEvent('NoDamage'); + Ammo.TriggerEffectEvent('BulletHit', Victim, HitMaterial); + } #endif // IG_EFFECTS - Ammo.BallisticsLog(" -> Remaining Momentum is "$Momentum$". Bullet hit Victim "$Victim.name); - - if (HitMaterial != None) - Ammo.BallisticsLog(" ... HitMaterial = "$HitMaterial); - else - Ammo.BallisticsLog(" ... HitMaterial = None"); - - Ammo.BallisticsLog(" ... MomentumToPenetrateVictim is "$MomentumToPenetrateVictim$", so the bullet will lose "$MomentumLostToVictim$" momentum to the Victim."); - - if ( HitRegion != REGION_None && Victim.IsA( 'IHaveSkeletalRegions' ) ) - { - Ammo.BallisticsLog(" ... Victim has SkeletalRegions. "$GetEnum(ESkeletalRegion, HitRegion)$" was hit."); - if (Protection != None) - Ammo.BallisticsLog(" ... (Region is protected by "$Protection.class.name$".)"); - if ( OverrideArmDamageModifier != 0 && (HitRegion == REGION_LeftArm || HitRegion == REGION_RightArm) ) - { - Ammo.BallisticsLog(" ... DamageModifier from the skeletal region was overriden for this arm hit, the OverrideArmDamageModifier is: " - $OverrideArmDamageModifier); - } - else - { - Ammo.BallisticsLog(" ... DamageModifier from the skeletal region is on the Range (Min="$SkeletalRegionInformation.DamageModifier.Min - $", Max="$SkeletalRegionInformation.DamageModifier.Max - $"), Selected "$DamageModifier - $"."); - } - Ammo.BallisticsLog(" ... ExternalDamageModifier = "$ExternalDamageModifier - $"."); - Ammo.BallisticsLog(" ... AimErrorPenalty in on Range (Min="$SkeletalRegionInformation.AimErrorPenalty.Min - $", Max="$SkeletalRegionInformation.AimErrorPenalty.Max - $"), Selected "$LimbInjuryAimErrorPenalty - $"."); - - if (PenetratesVictim) - Ammo.BallisticsLog(" ... Victim was penetrated: Damage = MomentumLostToVictim * MomentumToDamageConversionFactor * DamageModifier * ExternalDamageModifier = "$MomentumLostToVictim - $" * "$Level.GetRepo().MomentumToDamageConversionFactor - $" * "$DamageModifier - $" * "$ExternalDamageModifier - $" = "$Damage); - else - Ammo.BallisticsLog(" ... Bullet was buried in Victim: Damage = ((MomentumLostToVictim * MomentumToDamageConversionFactor) + InternalDamage) * DamageModifier * ExternalDamageModifier = (("$MomentumLostToVictim - $" * "$Level.GetRepo().MomentumToDamageConversionFactor - $") + "$Ammo.InternalDamage - $") * "$DamageModifier - $" * "$ExternalDamageModifier - $" = "$Damage); - } - else - { - if (PenetratesVictim) - Ammo.BallisticsLog(" ... Victim was penetrated: Damage = MomentumLostToVictim * MomentumToDamageConversionFactor = "$MomentumLostToVictim - $" * "$Level.GetRepo().MomentumToDamageConversionFactor - $" = "$Damage); - else - Ammo.BallisticsLog(" ... Bullet was buried in Victim: Damage = (MomentumLostToVictim * MomentumToDamageConversionFactor) + InternalDamage = ("$MomentumLostToVictim - $" * "$Level.GetRepo().MomentumToDamageConversionFactor - $") + "$Ammo.InternalDamage - $" = "$Damage); - } - - // If it's something with skeletal regions, do notification - // We check this using a separate variable to avoid accessed nones - // every time bsp or a static mesh is hit - SkelVictim = IHaveSkeletalRegions(Victim); - if (SkelVictim != None) - SkelVictim.OnSkeletalRegionHit(HitRegion, HitLocation, HitNormal, Damage, GetDamageType(), Owner); - - DealDamage(Victim, Damage, Pawn(Owner), HitLocation, MomentumVector, GetDamageType()); - - Ammo.BallisticsLog(" ... Bullet will impart to victim the momentum it lost to the victim: "$VSize(MomentumVector)$" in direction "$Normal(MomentumVector)); - - Victim.TakeHitImpulse(HitLocation, MomentumVector, GetDamageType()); - - //the bullet has lost momentum to its victim - Momentum -= MomentumLostToVictim; + Ammo.BallisticsLog(" -> Remaining Momentum is "$Momentum$". Bullet hit Victim "$Victim.name); + + if (HitMaterial != None) + Ammo.BallisticsLog(" ... HitMaterial = "$HitMaterial); + else + Ammo.BallisticsLog(" ... HitMaterial = None"); + + Ammo.BallisticsLog(" ... MomentumToPenetrateVictim is "$MomentumToPenetrateVictim$", so the bullet will lose "$MomentumLostToVictim$" momentum to the Victim."); + + if ( HitRegion != REGION_None && Victim.IsA( 'IHaveSkeletalRegions' ) ) + { + Ammo.BallisticsLog(" ... Victim has SkeletalRegions. "$GetEnum(ESkeletalRegion, HitRegion)$" was hit."); + if (Protection != None) + Ammo.BallisticsLog(" ... (Region is protected by "$Protection.class.name$".)"); + if ( OverrideArmDamageModifier != 0 && (HitRegion == REGION_LeftArm || HitRegion == REGION_RightArm) ) + { + Ammo.BallisticsLog(" ... DamageModifier from the skeletal region was overriden for this arm hit, the OverrideArmDamageModifier is: " + $OverrideArmDamageModifier); + } + else + { + Ammo.BallisticsLog(" ... DamageModifier from the skeletal region is on the Range (Min="$SkeletalRegionInformation.DamageModifier.Min + $", Max="$SkeletalRegionInformation.DamageModifier.Max + $"), Selected "$DamageModifier + $"."); + } + Ammo.BallisticsLog(" ... ExternalDamageModifier = "$ExternalDamageModifier + $"."); + Ammo.BallisticsLog(" ... AimErrorPenalty in on Range (Min="$SkeletalRegionInformation.AimErrorPenalty.Min + $", Max="$SkeletalRegionInformation.AimErrorPenalty.Max + $"), Selected "$LimbInjuryAimErrorPenalty + $"."); + + if (PenetratesVictim) + Ammo.BallisticsLog(" ... Victim was penetrated: Damage = MomentumLostToVictim * MomentumToDamageConversionFactor * DamageModifier * ExternalDamageModifier = "$MomentumLostToVictim + $" * "$Level.GetRepo().MomentumToDamageConversionFactor + $" * "$DamageModifier + $" * "$ExternalDamageModifier + $" = "$Damage); + else + Ammo.BallisticsLog(" ... Bullet was buried in Victim: Damage = ((MomentumLostToVictim * MomentumToDamageConversionFactor) + InternalDamage) * DamageModifier * ExternalDamageModifier = (("$MomentumLostToVictim + $" * "$Level.GetRepo().MomentumToDamageConversionFactor + $") + "$Ammo.InternalDamage + $") * "$DamageModifier + $" * "$ExternalDamageModifier + $" = "$Damage); + } + else + { + if (PenetratesVictim) + Ammo.BallisticsLog(" ... Victim was penetrated: Damage = MomentumLostToVictim * MomentumToDamageConversionFactor = "$MomentumLostToVictim + $" * "$Level.GetRepo().MomentumToDamageConversionFactor + $" = "$Damage); + else + Ammo.BallisticsLog(" ... Bullet was buried in Victim: Damage = (MomentumLostToVictim * MomentumToDamageConversionFactor) + InternalDamage = ("$MomentumLostToVictim + $" * "$Level.GetRepo().MomentumToDamageConversionFactor + $") + "$Ammo.InternalDamage + $" = "$Damage); + } + + // If it's something with skeletal regions, do notification + // We check this using a separate variable to avoid accessed nones + // every time bsp or a static mesh is hit + SkelVictim = IHaveSkeletalRegions(Victim); + if (SkelVictim != None) + SkelVictim.OnSkeletalRegionHit(HitRegion, HitLocation, HitNormal, Damage, GetDamageType(), Owner); + + DealDamage(Victim, Damage, Pawn(Owner), HitLocation, MomentumVector, GetDamageType()); + + Ammo.BallisticsLog(" ... Bullet will impart to victim the momentum it lost to the victim: "$VSize(MomentumVector)$" in direction "$Normal(MomentumVector)); + + Victim.TakeHitImpulse(HitLocation, MomentumVector, GetDamageType()); + + //the bullet has lost momentum to its victim + Momentum -= MomentumLostToVictim; #if IG_EFFECTS - if (PenetratesVictim) - { - Ammo.SetLocation( ExitLocation ); - Ammo.SetRotation( rotator(ExitNormal) ); + if (PenetratesVictim) + { + Ammo.SetLocation( ExitLocation ); + Ammo.SetRotation( rotator(ExitNormal) ); - Ammo.TriggerEffectEvent('BulletExited', Victim, ExitMaterial); - } + Ammo.TriggerEffectEvent('BulletExited', Victim, ExitMaterial); + } - if ( ShouldSpawnBloodForVictim( PawnVictim, Damage ) ) - SpawnBloodEffects( Ammo, ExitLocation, Damage, NormalizedBulletDirection ); + if ( ShouldSpawnBloodForVictim( PawnVictim, Damage ) ) + SpawnBloodEffects( Ammo, ExitLocation, Damage, NormalizedBulletDirection ); #endif // IG_EFFECTS - return PenetratesVictim; + + return PenetratesVictim; } //returns true iff the bullet penetrates the ProtectiveEquipment simulated function bool HandleProtectiveEquipmentBallisticImpact( - Actor Victim, - ProtectiveEquipment Protection, - ESkeletalRegion HitRegion, - vector HitLocation, - vector HitNormal, - vector NormalizedBulletDirection, - out float Momentum, - out float KillEnergy, - out int BulletType, - int ArmorLevel, - int BulletLevel - ) + Actor Victim, + ProtectiveEquipment Protection, + ESkeletalRegion HitRegion, + vector HitLocation, + vector HitNormal, + vector NormalizedBulletDirection, + out float Momentum) { - local bool PenetratesProtection; - local vector MomentumVector; - local int Damage; - local float ActualVelocity; - local float VelocityRatio; - local float OriginalKillEnergy; - local float StartingKillEnergy; - local float KillChance; + local bool PenetratesProtection; + local vector MomentumVector; + local int Damage; + local int ArmorLevel; + local int BulletLevel; + local float KillChance; local float RandomChance; - local float WoundChance; - local float MomentumLostToProtection; - local Object.Range DamageModifierRange; - local float DamageModifier, ExternalDamageModifier; + local float WoundChance; + local float MomentumLostToProtection; + local Object.Range DamageModifierRange; + local float DamageModifier, ExternalDamageModifier; - ArmorLevel = Protection.GetProtectionType(); - BulletLevel = Ammo.GetPenetrationType(); + ArmorLevel = Protection.GetProtectionType(); + BulletLevel = Ammo.GetPenetrationType(); - //the bullet will penetrate the protection unles it loses all of its momentum to the protection + //the bullet will penetrate the protection unles it loses all of its momentum to the protection + //PenetratesProtection = (Protection.GetMtP() < Momentum); + //Now it will penetrate if the bullet is designed to penetrate - // PenetratesProtection = (Protection.GetMtP() < Momentum); - PenetratesProtection = (BulletLevel >= ArmorLevel); + PenetratesProtection = (BulletLevel >= ArmorLevel); - //determine DamageModifierRange - if (PenetratesProtection) - DamageModifierRange = Protection.PenetratedDamageFactor; - else - DamageModifierRange = Protection.BlockedDamageFactor; + //determine DamageModifierRange + if (PenetratesProtection) + DamageModifierRange = Protection.PenetratedDamageFactor; + else + DamageModifierRange = Protection.BlockedDamageFactor; - //calculate damage imparted to victim + //calculate damage imparted to victim - MomentumLostToProtection = FMin(Momentum, Protection.GetMtP()); - Damage = MomentumLostToProtection * Level.GetRepo().MomentumToDamageConversionFactor; - - if(Damage > 0 && bUsesBullets) - { - if (HitRegion == REGION_Head) - { - if (BulletLevel >= ArmorLevel) - WoundChance = 1; - else - WoundChance = 400; - } - if (HitRegion == REGION_Torso) - { - if (BulletLevel >= ArmorLevel) - { - switch(BulletType) - { - case 1: - WoundChance = 280; - break; - case 2: - WoundChance = 140; - break; - case 3: - WoundChance = 120; - break; - case 4: - WoundChance = 100; - break; - case 5: - WoundChance = 195; - break; - case 6: - WoundChance = 125; - break; - case 7: - WoundChance = 100; - break; - case 8: - WoundChance = 70; - break; - case 9: - WoundChance = 300; - break; - case 10: - WoundChance = 120; - break; - case 11: - WoundChance = 90; - break; - case 12: - WoundChance = 65; - break; - case 13: - WoundChance = 150; - break; - case 14: - WoundChance = 70; - break; - case 15: - WoundChance = 60; - break; - case 16: - WoundChance = 50; - break; - case 17: - WoundChance = 715; - break; - case 18: - WoundChance = 375; - break; - case 19: - WoundChance = 330; - break; - case 20: - WoundChance = 250; - break; - case 21: - WoundChance = 100; - break; - case 22: - WoundChance = 60; - break; - case 23: - WoundChance = 50; - break; - case 24: - WoundChance = 45; - break; - case 25: - WoundChance = 620; - break; - case 26: - WoundChance = 220; - break; - case 27: - WoundChance = 180; - break; - case 28: - WoundChance = 155; - break; - case 29: - WoundChance = 845; - break; - case 30: - WoundChance = 400; - break; - case 31: - WoundChance = 350; - break; - case 32: - WoundChance = 300; - break; - case 33: - WoundChance = 850; - break; - case 34: - WoundChance = 300; - break; - case 35: - WoundChance = 245; - break; - case 36: - WoundChance = 200; - break; - case 37: - WoundChance = 650; - break; - case 38: - WoundChance = 330; - break; - case 39: - WoundChance = 245; - break; - case 40: - WoundChance = 200; - break; - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - WoundChance = 100; - break; - default: - WoundChance = 100; - } - } - else if (ArmorLevel >= 7) - { - WoundChance = 1750; - } - else - { - WoundChance = 1200; - } - } - //Reset damage First - Damage = 0; - OriginalKillEnergy = KillEnergy; - - log( "Initiating damage system" ); - do - { - KillChance = 1 - (WoundChance / KillEnergy); - RandomChance = 1.0 - FRand(); - log( "The KillEnergy is " $ KillEnergy ); - log( "The KillChance is " $ KillChance ); - log( "The RandomChance is " $ RandomChance ); - if (KillChance <= 0.10) - { - KillChance = 0.10; - } - if (RandomChance < KillChance) - { - Damage += 10; - log( "Victim is wounded. Adding 10 damage points. Actual Damage points are " $ Damage ); - } - else - { - Damage += 4; - log( "Victim is not wounded. Adding 4 damage point. Actual Damage points are " $ Damage ); - } - KillEnergy = KillEnergy - WoundChance; - } - until( KillEnergy <= 0 || RandomChance > KillChance || Damage > 150); - - log( "Stopping, RandomChance is higher than kill chance"); - log( "We need to restore the kill energy"); - log("IMPACT: KillEnergy before calculating penetration: "$OriginalKillEnergy); - KillEnergy = OriginalKillEnergy - WoundChance; - if (KillEnergy <= 0) - { - KillEnergy = 0; - } - log("IMPACT: KillEnergy after calculating penetration: "$KillEnergy); - log( "KillEnergy now is " $ KillEnergy ); - if (StartingKillEnergy <= 0) - { - Damage = 0; - log( "This was pointless because Originally our Kill Energy was 0 or less." ); - } - log( "Final damage is " $ Damage ); - } + MomentumLostToProtection = FMin(Momentum, Protection.GetMtP()); + Damage = MomentumLostToProtection * Level.GetRepo().MomentumToDamageConversionFactor; - if(!bUsesBullets) - { - DamageModifier = RandRange(DamageModifierRange.Min, DamageModifierRange.Max); - Damage *= DamageModifier; - } + DamageModifier = RandRange(DamageModifierRange.Min, DamageModifierRange.Max); + Damage *= DamageModifier; - //apply any external damage modifiers (maintained by the Repo) - ExternalDamageModifier = Level.GetRepo().GetExternalDamageModifier( Owner, Victim ); - Damage = int( float(Damage) * ExternalDamageModifier ); + //apply any external damage modifiers (maintained by the Repo) + ExternalDamageModifier = Level.GetRepo().GetExternalDamageModifier( Owner, Victim ); + Damage = int( float(Damage) * ExternalDamageModifier ); - //calculate momentum vector imparted to victim - MomentumVector = NormalizedBulletDirection * Protection.GetMtP(); - if (PenetratesProtection) - MomentumVector *= Level.getRepo().MomentumImpartedOnPenetrationFraction; + //calculate momentum vector imparted to victim + MomentumVector = NormalizedBulletDirection * Protection.GetMtP(); + if (PenetratesProtection) + MomentumVector *= Level.getRepo().MomentumImpartedOnPenetrationFraction; - Ammo.BallisticsLog(" -> Remaining Momentum is "$Momentum$"."); - Ammo.BallisticsLog(" -> Remaining KillEnergy is "$KillEnergy$"."); - Ammo.BallisticsLog(" ... Bullet hit "$Protection.class.name$" ProtectiveEquipment on Victim "$Victim.name); - Ammo.BallisticsLog(" ... Protection.MomentumToPenetrate is "$Protection.GetMtP()$"."); - Ammo.BallisticsLog(" ... Protection.ArmorLevel is "$ArmorLevel$"."); - Ammo.BallisticsLog(" ... Ammo.BulletLevel is "$BulletLevel$"."); + Ammo.BallisticsLog(" -> Remaining Momentum is "$Momentum$"."); + Ammo.BallisticsLog(" ... Bullet hit "$Protection.class.name$" ProtectiveEquipment on Victim "$Victim.name); + Ammo.BallisticsLog(" ... Protection.MomentumToPenetrate is "$Protection.GetMtP()$"."); + Ammo.BallisticsLog(" ... Protection.ArmorLevel is "$ArmorLevel$"."); + Ammo.BallisticsLog(" ... Ammo.BulletLevel is "$BulletLevel$"."); - if (PenetratesProtection) - Ammo.BallisticsLog(" ... The ProtectiveEquipment was penetrated. Using PenetratedDamageFactor."); - else - Ammo.BallisticsLog(" ... Bullet was buried in the ProtectiveEquipment Using BlockedDamageFactor."); + if (PenetratesProtection) + Ammo.BallisticsLog(" ... The ProtectiveEquipment was penetrated. Using PenetratedDamageFactor."); + else + Ammo.BallisticsLog(" ... Bullet was buried in the ProtectiveEquipment Using BlockedDamageFactor."); - Ammo.BallisticsLog(" ... DamageModifier is on the Range (Min="$DamageModifierRange.Min$", Max="$DamageModifierRange.Max$"), selected "$DamageModifier$"."); - Ammo.BallisticsLog(" ... ExternalDamageModifier = "$ExternalDamageModifier$"."); + Ammo.BallisticsLog(" ... DamageModifier is on the Range (Min="$DamageModifierRange.Min$", Max="$DamageModifierRange.Max$"), selected "$DamageModifier$"."); + Ammo.BallisticsLog(" ... ExternalDamageModifier = "$ExternalDamageModifier$"."); - Ammo.BallisticsLog(" ... Damage = MomentumLostToProtection * MomentumToDamageConversionFactor * DamageModifier * ExternalDamageModifier = "$MomentumLostToProtection - $" * "$Level.GetRepo().MomentumToDamageConversionFactor - $" * "$DamageModifier - $" * "$ExternalDamageModifier - $" = "$Damage); + Ammo.BallisticsLog(" ... Damage = MomentumLostToProtection * MomentumToDamageConversionFactor * DamageModifier * ExternalDamageModifier = "$MomentumLostToProtection + $" * "$Level.GetRepo().MomentumToDamageConversionFactor + $" * "$DamageModifier + $" * "$ExternalDamageModifier + $" = "$Damage); - IHaveSkeletalRegions(Victim).OnSkeletalRegionHit(HitRegion, HitLocation, HitNormal, Damage, GetDamageType(), Owner); + IHaveSkeletalRegions(Victim).OnSkeletalRegionHit(HitRegion, HitLocation, HitNormal, Damage, GetDamageType(), Owner); - DealDamage(Victim, Damage, Pawn(Owner), HitLocation, MomentumVector, GetDamageType()); + DealDamage(Victim, Damage, Pawn(Owner), HitLocation, MomentumVector, GetDamageType()); - //the bullet has lost momentum to its target - Momentum -= Protection.GetMtP(); + //the bullet has lost momentum to its target + Momentum -= Protection.GetMtP(); - if(Ammo.CanShredArmor()) { - Protection.OnProtectedRegionHit(); - } + if (Ammo.CanShredArmor()) { + Protection.OnProtectedRegionHit(); + } - return PenetratesProtection; + return PenetratesProtection; } simulated function bool HandleDoorImpact( - Actor Victim, - vector HitLocation, - vector HitNormal, - Material HitMaterial, - vector ExitLocation, - vector ExitNormal, - Material ExitMaterial - ) + Actor Victim, + vector HitLocation, + vector HitNormal, + Material HitMaterial, + vector ExitLocation, + vector ExitNormal, + Material ExitMaterial + ) { Ammo.SetLocation(HitLocation); Ammo.SetRotation(rotator(HitNormal)); Ammo.TriggerEffectEvent('BulletHit', None, HitMaterial); Ammo.SetLocation( ExitLocation ); - Ammo.SetRotation( rotator(ExitNormal) ); - Ammo.TriggerEffectEvent('BulletExited', Victim, ExitMaterial); + Ammo.SetRotation( rotator(ExitNormal) ); + Ammo.TriggerEffectEvent('BulletExited', Victim, ExitMaterial); return bPenetratesDoors; } static function WeaponEquipClass GetEquipClass() { - return default.WeaponCategory; + return default.WeaponCategory; } static function WeaponEquipType GetEquipType() { - return default.AllowedSlots; + return default.AllowedSlots; } function WeaponAimAnimationType GetAimAnimation() { - return AimAnimation; + return AimAnimation; } function WeaponLowReadyAnimationType GetLowReadyAnimation() { - return LowReadyAnimation; + return LowReadyAnimation; } function bool ValidIdleCategory(EIdleWeaponStatus DesiredStatus) { - local int i; - - for(i = 0; i < IdleWeaponCategory.Length; i++) - { - if(IdleWeaponCategory[i] == DesiredStatus) - { - return true; - } - } - return false; // This isn't a valid idle category for this weapon + local int i; + + for(i = 0; i < IdleWeaponCategory.Length; i++) + { + if(IdleWeaponCategory[i] == DesiredStatus) + { + return true; + } + } + return false; // This isn't a valid idle category for this weapon } simulated function vector GetDefaultLocationOffset() { - return DefaultLocationOffset; + return DefaultLocationOffset; } simulated function Rotator GetDefaultRotationOffset() { - return DefaultRotationOffset; + return DefaultRotationOffset; } simulated function vector GetIronsightsLocationOffset() { - return IronSightLocationOffset; + return IronSightLocationOffset; } simulated function Rotator GetIronsightsRotationOffset() { - return IronSightRotationOffset; + return IronSightRotationOffset; } simulated function float GetViewInertia() @@ -1395,11 +911,11 @@ simulated function SetIronSightAnimationProgress(float value) simulated function vector GetHandsOffsetLastFrame() { - return HandsOffsetLastFrame; + return HandsOffsetLastFrame; } simulated function SetHandsOffsetLastFrame(vector value) { - HandsOffsetLastFrame = value; + HandsOffsetLastFrame = value; } simulated function float GetBaseAimError() @@ -1433,32 +949,32 @@ function int GetFlashlightTextureIndex() // Sticky selection: if this item is equipped, then we switch to a grenade, then use a grenade, it switches to this item simulated function bool HasStickySelection() { - return true; + return true; } simulated function EquippedHook() { - local Pawn OwnerPawn; - local PlayerController OwnerController; - - Super.EquippedHook(); - - OwnerPawn = Pawn(Owner); - if(OwnerPawn != None && HasStickySelection()) - { - OwnerController = PlayerController(OwnerPawn.Controller); - if(OwnerController != None) - { - if(GetPocket() == Pocket.Pocket_SecondaryWeapon) - { - OwnerController.bSecondaryWeaponLast = true; - } - else - { - OwnerController.bSecondaryWeaponLast = false; - } - } - } + local Pawn OwnerPawn; + local PlayerController OwnerController; + + Super.EquippedHook(); + + OwnerPawn = Pawn(Owner); + if(OwnerPawn != None && HasStickySelection()) + { + OwnerController = PlayerController(OwnerPawn.Controller); + if(OwnerController != None) + { + if(GetPocket() == Pocket.Pocket_SecondaryWeapon) + { + OwnerController.bSecondaryWeaponLast = true; + } + else + { + OwnerController.bSecondaryWeaponLast = false; + } + } + } } @@ -1519,83 +1035,83 @@ function UnRegisterInterestedGrenadeThrowing(IInterestedGrenadeThrowing Client) simulated function MutateFPHandheldEquipmentModel(HandheldEquipmentModel Model) { - local int i; - - Super.MutateFPHandheldEquipmentModel(Model); - - if (FPSkins.Length > 0) - { - - for(i=0; i 0) + { + + for(i=0; i 0) - { - - for(i=0; i 0) + { + + for(i=0; i