Amineri Posted April 29, 2014 Share Posted April 29, 2014 Having picked up a lot of tricks in the last few months, I finally have revisited this topic and was able to mod in variable explosive damage depending on distance from the blast center. Once I knew where to put the code, this actually turned out to be a pretty simply change, only requiring insertion of new code in a single function, XComUnitPawn.TakeDirectDamage. TakeDirectDamage is called for each unit that takes AoE damage from XComUnitPawn.TakeSplashDamage. The new code looks like : if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) { if(XComProjectile(Dmg.DamageCauser) != none) { actualDamage.DamageAmount = int(0.50 + (float(Dmg.DamageAmount) * (1.0 - FMin(1.0, (0.50 * VSize(Dmg.DamageCauser.Location - Location)) / XComProjectile(Dmg.DamageCauser).DamageRadius)))); } } actualDamage.DamageAmount = kSelf.OnTakeDamage(actualDamage.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser); The above code is only applied to projectiles dealing explosive damage (including of type XComDamageType_NeedleExplosion, which is a child of XComDamageType_Explosion). The above equation scales the damage down to 50% of regular damage at the edge of the blast, with 100% damage at the center, scaling down linearly. Fractional damage is rounded instead of truncated, so a 3 base damage blast will still deal 2 damage at the edge, and a 5 damage blast will deal 3 at the edge. The Dmg and actualDamage variables are UnrealEngine natively defined structure, defined in Engine.upk, in Actor.DamageEvent : struct native DamageEvent { var int DamageAmount; var Actor EventInstigator; var Vector HitLocation; var Vector Momentum; var class<DamageType> DamageType; var TraceHitInfo HitInfo; var Actor DamageCauser; var bool bRadialDamage; var float Radius; var bool bIsHit; var array<Actor> IgnoredActors; var Actor Target; var bool bDamagesUnits; var bool bCausesSurroundingAreaDamage; var bool bDebug; var Box FilterBox; var Actor kShot; } The key part here is that DamageEvent contains both the EventInstigator (the unit that originated the projectile) and the DamageCauser (the projectile itself). Both members are of type Actor, but Actor is a parent class of both XGUnit and XComProjectile, which is why they have to be cast to the correct type. Below is the UPKmodder file which implements the mod : MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk FUNCTION=TakeDirectDamage@XComUnitPawn RESIZE=110 // enable absorbed damage pop-ups // make explosive damage scale down with distance from blast center [BEFORE_HEX] [HEADER] 17 06 00 00 2F 04 00 00 [/HEADER] [code] //if(!XGUnit(GetGameUnit()).CanTakeDamage()) 07 30 00 81 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 0A 00 C7 C6 00 00 00 1B B7 11 00 00 00 00 00 00 16 16 //return 04 0B //kDamageDealer = XGUnit(Dmg.EventInstigator) 0F 00 D9 3D 00 00 2E 3F CE 00 00 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 //kSelf = XGUnit(GetGameUnit()) 0F 00 D8 3D 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 //if((kSelf.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') 07 E5 00 82 82 19 00 D8 3D 00 00 0A 00 27 C5 00 00 00 2D 01 27 C5 00 00 18 15 00 72 00 D9 3D 00 00 00 D8 3D 00 00 16 16 18 28 00 72 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 D4 52 00 00 16 16 //return 04 0B //bWasAlive = kSelf.GetUnitHP() > 0 14 2D 00 D5 3D 00 00 97 19 00 D8 3D 00 00 0A 00 D5 3A 00 00 00 1B 01 3C 00 00 00 00 00 00 16 25 16 //bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible() 14 2D 00 D4 3D 00 00 82 19 00 D8 3D 00 00 0A 00 24 3A 00 00 00 2D 01 24 3A 00 00 18 0D 00 81 1B 90 46 00 00 00 00 00 00 16 16 16 //actualDamage = Dmg 0F 00 D7 3D 00 00 00 DA 3D 00 00 //if((Dmg.EventInstigator != none) && kDamageDealer != none) 07 E2 01 82 77 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 2A 16 18 0D 00 77 00 D9 3D 00 00 2A 16 16 //enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam() 14 2D 00 D6 3D 00 00 9B 38 3A 19 00 D9 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 38 3A 19 00 D8 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 16 //actualDamage.DamageAmount = kSelf.OnTakeDamage(Dmg.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 19 00 D8 3D 00 00 9F 00 09 CA 00 00 00 1B 4C 62 00 00 00 00 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 00 D9 3D 00 00 35 9C F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 9B F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 16 //if(actualDamage.DamageAmount > 0) 07 E8 02 97 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 25 16 //super(Actor).TakeDirectDamage(actualDamage) 1C 10 FC FF FF 00 D7 3D 00 00 16 //if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) 07 90 03 82 77 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 2A 16 18 37 00 77 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 2A 16 16 //kSelf.m_kBehavior.m_kPod.OnTakeDamage() 19 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 0A 00 00 00 00 00 00 1B 4C 62 00 00 00 00 00 00 16 //if(!kSelf.IsAlive() && bWasAlive) 07 93 05 82 81 19 00 D8 3D 00 00 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 16 18 0B 00 2D 00 D5 3D 00 00 16 //DamageEvent_CauseOfDeath = Dmg 0F 01 8B 3B 00 00 00 DA 3D 00 00 //if(kDamageDealer != none) 07 90 05 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 19 00 D9 3D 00 00 3B 00 00 00 00 00 00 1B 3F 68 00 00 00 00 00 00 00 D8 3D 00 00 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 16 //if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) 07 01 05 82 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 24 00 9A 19 00 D8 3D 00 00 0A 00 41 3B 00 00 00 1B F4 37 00 00 00 00 00 00 16 2C 15 16 16 18 20 00 19 00 D8 3D 00 00 0A 00 0A C5 00 00 00 2D 01 0A C5 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 40 16 //if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) 07 90 05 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 0B 00 2D 00 D4 3D 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 4E 16 //else 06 14 06 //if(GetGameUnit().IsAlive()) 07 14 06 19 1B 06 39 00 00 00 00 00 00 16 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 //if(kDamageDealer != none) 07 F7 05 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordWounding(XGUnit(GetGameUnit())) 19 00 D9 3D 00 00 1D 00 00 00 00 00 00 1B 47 68 00 00 00 00 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 16 //ApplyShredderRocket(Dmg, enemyOfUnitHit) 1B 8A 04 00 00 00 00 00 00 00 DA 3D 00 00 2D 00 D6 3D 00 00 16 //return 04 0B //EOS 53 [/CODE] [/BEFORE_HEX] [AFTER_HEX] [HEADER] 9B 07 00 00 3F 05 00 00 [/HEADER] [code] //if(!XGUnit(GetGameUnit()).CanTakeDamage()) 07 30 00 81 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 0A 00 C7 C6 00 00 00 1B B7 11 00 00 00 00 00 00 16 16 //return 04 0B //kDamageDealer = XGUnit(Dmg.EventInstigator) 0F 00 D9 3D 00 00 2E 3F CE 00 00 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 //kSelf = XGUnit(GetGameUnit()) 0F 00 D8 3D 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 //if((kSelf.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') 07 E5 00 82 82 19 00 D8 3D 00 00 0A 00 27 C5 00 00 00 2D 01 27 C5 00 00 18 15 00 72 00 D9 3D 00 00 00 D8 3D 00 00 16 16 18 28 00 72 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 D4 52 00 00 16 16 //return 04 0B //bWasAlive = kSelf.GetUnitHP() > 0 14 2D 00 D5 3D 00 00 97 19 00 D8 3D 00 00 0A 00 D5 3A 00 00 00 1B 01 3C 00 00 00 00 00 00 16 25 16 //bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible() 14 2D 00 D4 3D 00 00 82 19 00 D8 3D 00 00 0A 00 24 3A 00 00 00 2D 01 24 3A 00 00 18 0D 00 81 1B 90 46 00 00 00 00 00 00 16 16 16 //actualDamage = Dmg 0F 00 D7 3D 00 00 00 DA 3D 00 00 //if((Dmg.EventInstigator != none) && kDamageDealer != none) 07 E2 01 82 77 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 2A 16 18 0D 00 77 00 D9 3D 00 00 2A 16 16 //enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam() 14 2D 00 D6 3D 00 00 9B 38 3A 19 00 D9 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 38 3A 19 00 D8 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 16 //if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 07 0D 03 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 //if(XComProjectile(Dmg.DamageCauser) != none) 07 0D 03 77 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 E0 53 00 00 2A 16 //actualDamage.DamageAmount = int(0.5 + float(Dmg.DamageAmount) * (1.0 - FMin(1.0, 0.5 * (VSize(Dmg.DamageCauser.Location - Location) / XComProjectile(Dmg.DamageCauser).DamageRadius)))) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 38 44 AE 1E 00 00 00 3F AB 38 3F 35 02 FA FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 AF 1E 00 00 80 3F F4 1E 00 00 80 3F AC AB 1E 00 00 00 3F E1 D8 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF 01 94 F8 FF FF 16 16 16 19 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 E0 53 00 00 09 00 C2 FC FF FF 00 01 C2 FC FF FF 16 16 16 16 16 //actualDamage.DamageAmount = kSelf.OnTakeDamage(actualDamage.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 19 00 D8 3D 00 00 9F 00 09 CA 00 00 00 1B 4C 62 00 00 00 00 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 00 D9 3D 00 00 35 9C F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 9B F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 16 //if(XGUnit(GetGameUnit()) != null) 07 29 04 77 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 2A 16 //XGUnit(GetGameUnit()).SetTimer(0.5, false, 'DebugTreads') 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 13 00 00 00 00 00 00 61 18 1E 00 00 00 3F 28 21 7E 17 00 00 00 00 00 00 4A 16 //if(actualDamage.DamageAmount > 0) 07 5E 04 97 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 25 16 //super(Actor).TakeDirectDamage(actualDamage) 1C 10 FC FF FF 00 D7 3D 00 00 16 //if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) 07 06 05 82 77 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 2A 16 18 37 00 77 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 2A 16 16 //kSelf.m_kBehavior.m_kPod.OnTakeDamage() 19 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 0A 00 00 00 00 00 00 1B 4C 62 00 00 00 00 00 00 16 //if(!kSelf.IsAlive() && bWasAlive) 07 09 07 82 81 19 00 D8 3D 00 00 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 16 18 0B 00 2D 00 D5 3D 00 00 16 //DamageEvent_CauseOfDeath = Dmg 0F 01 8B 3B 00 00 00 DA 3D 00 00 //if(kDamageDealer != none) 07 06 07 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 19 00 D9 3D 00 00 3B 00 00 00 00 00 00 1B 3F 68 00 00 00 00 00 00 00 D8 3D 00 00 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 16 //if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) 07 77 06 82 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 24 00 9A 19 00 D8 3D 00 00 0A 00 41 3B 00 00 00 1B F4 37 00 00 00 00 00 00 16 2C 15 16 16 18 20 00 19 00 D8 3D 00 00 0A 00 0A C5 00 00 00 2D 01 0A C5 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 40 16 //if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) 07 06 07 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 0B 00 2D 00 D4 3D 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 4E 16 //else 06 8A 07 //if(GetGameUnit().IsAlive()) 07 8A 07 19 1B 06 39 00 00 00 00 00 00 16 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 //if(kDamageDealer != none) 07 6D 07 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordWounding(XGUnit(GetGameUnit())) 19 00 D9 3D 00 00 1D 00 00 00 00 00 00 1B 47 68 00 00 00 00 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 16 //ApplyShredderRocket(Dmg, enemyOfUnitHit) 1B 8A 04 00 00 00 00 00 00 00 DA 3D 00 00 2D 00 D6 3D 00 00 16 //return 04 0B //null ops 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B //EOS 53 [/CODE] [/AFTER_HEX] Unfortunately this has a second effect code for Long War, which is enabling HTML tag pop-ups for absorbed damage : //if(XGUnit(GetGameUnit()) != null) 07 29 04 77 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 2A 16 //XGUnit(GetGameUnit()).SetTimer(0.5, false, 'DebugTreads') 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 13 00 00 00 00 00 00 61 18 1E 00 00 00 3F 28 21 7E 17 00 00 00 00 00 00 4A 16 The above code will probably cause crashes if installed into vanilla code. To implement the absorbed damage pop-ups for Long War required rewriting XGUnit.AbsorbDamage (to save the last absorbed damage amount) and XGUnit.DebugTreads into a helper to invoke the Messager to create the pop-up. This code should be removed (requiring adjustment of the jump offsets) if creating a patch for vanilla Enemy Within. Link to comment Share on other sites More sharing options...
wghost81 Posted April 29, 2014 Share Posted April 29, 2014 (edited) I've converted your mod to PatchUPK format, but I have a question before I post it here. XComProjectile(Dmg.DamageCauser) is used in two places and in both it casts XComFracLevelActor.TakeDirectDamage.Dmg instead of XComUnitPawn.TakeDirectDamage.Dmg. Is it intentional? In all other places XComUnitPawn.TakeDirectDamage.Dmg is used, which is an input parameter of XComUnitPawn.TakeDirectDamage function. Both EventInstigator and DamageCauser are members of XComUnitPawn.TakeDirectDamage.Dmg, as I understand it, and XComFracLevelActor.TakeDirectDamage.Dmg is actually a different object, which isn't accessible from this function by regular Unreal Script means. Edited April 29, 2014 by wghost81 Link to comment Share on other sites More sharing options...
Amineri Posted April 29, 2014 Author Share Posted April 29, 2014 Nice catch, thank you very much :) There were indeed two references to XComFracLevelActor.TakeDirectDamage.Dmg which I hadn't fixed after copying the reference code from that function. The crazy thing is that it appeared to all work properly in my test case, which could have led to some maddeningly-inconsistent bugs. Here's my updated UPKmodder file with the references corrected, in case anyone is interested : MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk FUNCTION=TakeDirectDamage@XComUnitPawn RESIZE=110 // enable absorbed damage pop-ups // make explosive damage scale down with distance from blast center [BEFORE_HEX] [HEADER] 17 06 00 00 2F 04 00 00 [/HEADER] [CODE] //if(!XGUnit(GetGameUnit()).CanTakeDamage()) 07 30 00 81 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 0A 00 C7 C6 00 00 00 1B B7 11 00 00 00 00 00 00 16 16 //return 04 0B //kDamageDealer = XGUnit(Dmg.EventInstigator) 0F 00 D9 3D 00 00 2E 3F CE 00 00 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 //kSelf = XGUnit(GetGameUnit()) 0F 00 D8 3D 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 //if((kSelf.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') 07 E5 00 82 82 19 00 D8 3D 00 00 0A 00 27 C5 00 00 00 2D 01 27 C5 00 00 18 15 00 72 00 D9 3D 00 00 00 D8 3D 00 00 16 16 18 28 00 72 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 D4 52 00 00 16 16 //return 04 0B //bWasAlive = kSelf.GetUnitHP() > 0 14 2D 00 D5 3D 00 00 97 19 00 D8 3D 00 00 0A 00 D5 3A 00 00 00 1B 01 3C 00 00 00 00 00 00 16 25 16 //bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible() 14 2D 00 D4 3D 00 00 82 19 00 D8 3D 00 00 0A 00 24 3A 00 00 00 2D 01 24 3A 00 00 18 0D 00 81 1B 90 46 00 00 00 00 00 00 16 16 16 //actualDamage = Dmg 0F 00 D7 3D 00 00 00 DA 3D 00 00 //if((Dmg.EventInstigator != none) && kDamageDealer != none) 07 E2 01 82 77 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 2A 16 18 0D 00 77 00 D9 3D 00 00 2A 16 16 //enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam() 14 2D 00 D6 3D 00 00 9B 38 3A 19 00 D9 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 38 3A 19 00 D8 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 16 //actualDamage.DamageAmount = kSelf.OnTakeDamage(Dmg.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 19 00 D8 3D 00 00 9F 00 09 CA 00 00 00 1B 4C 62 00 00 00 00 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 00 D9 3D 00 00 35 9C F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 9B F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 16 //if(actualDamage.DamageAmount > 0) 07 E8 02 97 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 25 16 //super(Actor).TakeDirectDamage(actualDamage) 1C 10 FC FF FF 00 D7 3D 00 00 16 //if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) 07 90 03 82 77 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 2A 16 18 37 00 77 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 2A 16 16 //kSelf.m_kBehavior.m_kPod.OnTakeDamage() 19 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 0A 00 00 00 00 00 00 1B 4C 62 00 00 00 00 00 00 16 //if(!kSelf.IsAlive() && bWasAlive) 07 93 05 82 81 19 00 D8 3D 00 00 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 16 18 0B 00 2D 00 D5 3D 00 00 16 //DamageEvent_CauseOfDeath = Dmg 0F 01 8B 3B 00 00 00 DA 3D 00 00 //if(kDamageDealer != none) 07 90 05 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 19 00 D9 3D 00 00 3B 00 00 00 00 00 00 1B 3F 68 00 00 00 00 00 00 00 D8 3D 00 00 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 16 //if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) 07 01 05 82 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 24 00 9A 19 00 D8 3D 00 00 0A 00 41 3B 00 00 00 1B F4 37 00 00 00 00 00 00 16 2C 15 16 16 18 20 00 19 00 D8 3D 00 00 0A 00 0A C5 00 00 00 2D 01 0A C5 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 40 16 //if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) 07 90 05 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 0B 00 2D 00 D4 3D 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 4E 16 //else 06 14 06 //if(GetGameUnit().IsAlive()) 07 14 06 19 1B 06 39 00 00 00 00 00 00 16 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 //if(kDamageDealer != none) 07 F7 05 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordWounding(XGUnit(GetGameUnit())) 19 00 D9 3D 00 00 1D 00 00 00 00 00 00 1B 47 68 00 00 00 00 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 16 //ApplyShredderRocket(Dmg, enemyOfUnitHit) 1B 8A 04 00 00 00 00 00 00 00 DA 3D 00 00 2D 00 D6 3D 00 00 16 //return 04 0B //EOS 53 [/CODE] [/BEFORE_HEX] [AFTER_HEX] [HEADER] 9B 07 00 00 3F 05 00 00 [/HEADER] [CODE] //if(!XGUnit(GetGameUnit()).CanTakeDamage()) 07 30 00 81 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 0A 00 C7 C6 00 00 00 1B B7 11 00 00 00 00 00 00 16 16 //return 04 0B //kDamageDealer = XGUnit(Dmg.EventInstigator) 0F 00 D9 3D 00 00 2E 3F CE 00 00 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 //kSelf = XGUnit(GetGameUnit()) 0F 00 D8 3D 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 //if((kSelf.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') 07 E5 00 82 82 19 00 D8 3D 00 00 0A 00 27 C5 00 00 00 2D 01 27 C5 00 00 18 15 00 72 00 D9 3D 00 00 00 D8 3D 00 00 16 16 18 28 00 72 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 D4 52 00 00 16 16 //return 04 0B //bWasAlive = kSelf.GetUnitHP() > 0 14 2D 00 D5 3D 00 00 97 19 00 D8 3D 00 00 0A 00 D5 3A 00 00 00 1B 01 3C 00 00 00 00 00 00 16 25 16 //bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible() 14 2D 00 D4 3D 00 00 82 19 00 D8 3D 00 00 0A 00 24 3A 00 00 00 2D 01 24 3A 00 00 18 0D 00 81 1B 90 46 00 00 00 00 00 00 16 16 16 //actualDamage = Dmg 0F 00 D7 3D 00 00 00 DA 3D 00 00 //if((Dmg.EventInstigator != none) && kDamageDealer != none) 07 E2 01 82 77 35 B1 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 2A 16 18 0D 00 77 00 D9 3D 00 00 2A 16 16 //enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam() 14 2D 00 D6 3D 00 00 9B 38 3A 19 00 D9 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 38 3A 19 00 D8 3D 00 00 0A 00 3E C8 00 00 00 1B C6 3B 00 00 00 00 00 00 16 16 //if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 07 0D 03 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 //if(XComProjectile(Dmg.DamageCauser) != none) 07 0D 03 77 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 2A 16 //actualDamage.DamageAmount = int(0.5 + float(Dmg.DamageAmount) * (1.0 - FMin(1.0, 0.5 * (VSize(Dmg.DamageCauser.Location - Location) / XComProjectile(Dmg.DamageCauser).DamageRadius)))) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 38 44 AE 1E 00 00 00 3F AB 38 3F 35 02 FA FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 AF 1E 00 00 80 3F F4 1E 00 00 80 3F AC AB 1E 00 00 00 3F E1 D8 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF 01 94 F8 FF FF 16 16 16 19 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 09 00 C2 FC FF FF 00 01 C2 FC FF FF 16 16 16 16 16 //actualDamage.DamageAmount = kSelf.OnTakeDamage(actualDamage.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser) 0F 35 02 FA FF FF 13 F9 FF FF 00 01 00 D7 3D 00 00 19 00 D8 3D 00 00 9F 00 09 CA 00 00 00 1B 4C 62 00 00 00 00 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 00 D9 3D 00 00 35 9C F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 9B F8 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 16 //if(XGUnit(GetGameUnit()) != null) 07 29 04 77 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 2A 16 //XGUnit(GetGameUnit()).SetTimer(0.5, false, 'DebugTreads') 19 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 13 00 00 00 00 00 00 61 18 1E 00 00 00 3F 28 21 7E 17 00 00 00 00 00 00 4A 16 //if(actualDamage.DamageAmount > 0) 07 5E 04 97 35 02 FA FF FF 13 F9 FF FF 00 00 00 D7 3D 00 00 25 16 //super(Actor).TakeDirectDamage(actualDamage) 1C 10 FC FF FF 00 D7 3D 00 00 16 //if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) 07 06 05 82 77 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 2A 16 18 37 00 77 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 2A 16 16 //kSelf.m_kBehavior.m_kPod.OnTakeDamage() 19 19 19 00 D8 3D 00 00 09 00 16 3A 00 00 00 01 16 3A 00 00 09 00 A9 9C 00 00 00 01 A9 9C 00 00 0A 00 00 00 00 00 00 1B 4C 62 00 00 00 00 00 00 16 //if(!kSelf.IsAlive() && bWasAlive) 07 09 07 82 81 19 00 D8 3D 00 00 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 16 18 0B 00 2D 00 D5 3D 00 00 16 //DamageEvent_CauseOfDeath = Dmg 0F 01 8B 3B 00 00 00 DA 3D 00 00 //if(kDamageDealer != none) 07 06 07 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 19 00 D9 3D 00 00 3B 00 00 00 00 00 00 1B 3F 68 00 00 00 00 00 00 00 D8 3D 00 00 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 00 DA 3D 00 00 20 CA 52 00 00 16 16 //if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) 07 77 06 82 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 24 00 9A 19 00 D8 3D 00 00 0A 00 41 3B 00 00 00 1B F4 37 00 00 00 00 00 00 16 2C 15 16 16 18 20 00 19 00 D8 3D 00 00 0A 00 0A C5 00 00 00 2D 01 0A C5 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 40 16 //if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) 07 06 07 82 19 00 D9 3D 00 00 0A 00 A8 37 00 00 00 1B 96 45 00 00 00 00 00 00 16 18 0B 00 2D 00 D4 3D 00 00 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78) 19 2E C0 46 00 00 19 2E 2B FE FF FF 12 20 35 FE FF FF 0A 00 91 F9 FF FF 00 1C D4 FB FF FF 16 09 00 8D F9 FF FF 00 01 8D F9 FF FF 0C 00 00 00 00 00 00 1B 02 7B 00 00 00 00 00 00 24 4E 16 //else 06 8A 07 //if(GetGameUnit().IsAlive()) 07 8A 07 19 1B 06 39 00 00 00 00 00 00 16 0A 00 FC 37 00 00 00 1B 59 44 00 00 00 00 00 00 16 //if(kDamageDealer != none) 07 6D 07 77 00 D9 3D 00 00 2A 16 //kDamageDealer.RecordWounding(XGUnit(GetGameUnit())) 19 00 D9 3D 00 00 1D 00 00 00 00 00 00 1B 47 68 00 00 00 00 00 00 2E 3F CE 00 00 1B 06 39 00 00 00 00 00 00 16 16 //ApplyShredderRocket(Dmg, enemyOfUnitHit) 1B 8A 04 00 00 00 00 00 00 00 DA 3D 00 00 2D 00 D6 3D 00 00 16 //return 04 0B //null ops 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B //EOS 53 [/CODE] [/AFTER_HEX] As a follow on project, following some discussion in the Long War beta forum, I might create a separate module that would scale the environmental damage for explosives based on distance from blast as well. Link to comment Share on other sites More sharing options...
wghost81 Posted April 29, 2014 Share Posted April 29, 2014 Here's PatcherGUI version without absorbed damage pop-ups, written in pseudo-code. UPK_FILE=XComGame.upk OBJECT=XComUnitPawn.TakeDirectDamage:AUTO // make explosive damage scale down with distance from blast center [REPLACEMENT_CODE] //if(!XGUnit(GetGameUnit()).CanTakeDamage()) 07 [@label1] 81 19 2E <Class.XGUnit> 1B <GetGameUnit> 16 0A 00 <XGUnit.CanTakeDamage.ReturnValue> 00 1B <CanTakeDamage> 16 16 //return 04 0B [#label1] //kDamageDealer = XGUnit(Dmg.EventInstigator) 0F 00 <.kDamageDealer> 2E <Class.XGUnit> 35 <Engine.Actor.DamageEvent.EventInstigator> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> //kSelf = XGUnit(GetGameUnit()) 0F 00 <.kSelf> 2E <Class.XGUnit> 1B <GetGameUnit> 16 //if((kSelfXGUnit.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') 07 [@label2] 82 82 19 00 <.kSelf> 0A 00 <XGUnit.m_bIsDoingBullRush> 00 2D 01 <XGUnit.m_bIsDoingBullRush> 18 15 00 72 00 <.kDamageDealer> 00 <.kSelf> 16 16 18 28 00 72 35 <Engine.Actor.DamageEvent.DamageType> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 20 <Class.XComDamageType_Melee> 16 16 //return 04 0B [#label2] //bWasAlive = kSelf.GetUnitHP() > 0 14 2D 00 <.bWasAlive> 97 19 00 <.kSelf> 0A 00 <XGUnitNativeBase.GetUnitHP.ReturnValue> 00 1B <GetUnitHP> 16 25 16 //bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible() 14 2D 00 <.bWasVisibleOnlyWithBioelectricSkin> 82 19 00 <.kSelf> 0A 00 <XGUnitNativeBase.m_bEnableBioElectricParticles> 00 2D 01 <XGUnitNativeBase.m_bEnableBioElectricParticles> 18 0D 00 81 1B <IsVisible> 16 16 16 //actualDamage = Dmg 0F 00 <.actualDamage> 00 <.Dmg> //if((Dmg.EventInstigator != none) && kDamageDealer != none) 07 [@label3] 82 77 35 <Engine.Actor.DamageEvent.EventInstigator> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 2A 16 18 0D 00 77 00 <.kDamageDealer> 2A 16 16 //enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam() 14 2D 00 <.enemyOfUnitHit> 9B 38 3A 19 00 <.kDamageDealer> 0A 00 <XGUnit.GetTeam.ReturnValue> 00 1B <GetTeam> 16 38 3A 19 00 <.kSelf> 0A 00 <XGUnit.GetTeam.ReturnValue> 00 1B <GetTeam> 16 16 [#label3] //if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 07 [@label4] 61 02 35 <Engine.Actor.DamageEvent.DamageType> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 20 <Class.XComDamageType_Explosion> 16 //if(XComProjectile(Dmg.DamageCauser) != none) 07 [@label4] 77 2E <Class.XComProjectile> 35 <Engine.Actor.DamageEvent.DamageCauser> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 2A 16 //actualDamage.DamageAmount = int(0.5 + float(Dmg.DamageAmount) * (1.0 - FMin(1.0, 0.5 * (VSize(Dmg.DamageCauser.Location - Location) / XComProjectile(Dmg.DamageCauser).DamageRadius)))) 0F 35 <Engine.Actor.DamageEvent.DamageAmount> <Engine.Actor.DamageEvent> 00 01 00 <.actualDamage> 38 44 AE 1E 00 00 00 3F AB 38 3F 35 <Engine.Actor.DamageEvent.DamageAmount> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> AF 1E 00 00 80 3F F4 1E 00 00 80 3F AC AB 1E 00 00 00 3F E1 D8 19 35 <Engine.Actor.DamageEvent.DamageCauser> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 09 00 <Engine.Actor.Location> 00 01 <Engine.Actor.Location> 01 <Engine.Actor.Location> 16 16 16 19 2E <Class.XComProjectile> 35 <Engine.Actor.DamageEvent.DamageCauser> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 09 00 <Engine.Projectile.DamageRadius> 00 01 <Engine.Projectile.DamageRadius> 16 16 16 16 16 [#label4] //actualDamage.DamageAmount = kSelf.OnTakeDamage(actualDamage.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser) 0F 35 <Engine.Actor.DamageEvent.DamageAmount> <Engine.Actor.DamageEvent> 00 01 00 <.actualDamage> 19 00 <.kSelf> 9F 00 <XGUnit.OnTakeDamage.ReturnValue> 00 1B <OnTakeDamage> 35 <Engine.Actor.DamageEvent.DamageAmount> <Engine.Actor.DamageEvent> 00 00 00 <.actualDamage> 35 <Engine.Actor.DamageEvent.DamageType> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 00 <.kDamageDealer> 35 <Engine.Actor.DamageEvent.HitLocation> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 35 <Engine.Actor.DamageEvent.Momentum> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 35 <Engine.Actor.DamageEvent.DamageCauser> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 16 //if(actualDamage.DamageAmount > 0) 07 [@label5] 97 35 <Engine.Actor.DamageEvent.DamageAmount> <Engine.Actor.DamageEvent> 00 00 00 <.actualDamage> 25 16 //super(Actor).TakeDirectDamage(actualDamage) 1C <Engine.Actor.TakeDirectDamage> 00 <.actualDamage> 16 [#label5] //if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) 07 [@label6] 82 77 19 00 <.kSelf> 09 00 <XGUnitNativeBase.m_kBehavior> 00 01 <XGUnitNativeBase.m_kBehavior> 2A 16 18 37 00 77 19 19 00 <.kSelf> 09 00 <XGUnitNativeBase.m_kBehavior> 00 01 <XGUnitNativeBase.m_kBehavior> 09 00 <XGAIBehavior.m_kPod> 00 01 <XGAIBehavior.m_kPod> 2A 16 16 //kSelf.m_kBehavior.m_kPod.OnTakeDamage() 19 19 19 00 <.kSelf> 09 00 <XGUnitNativeBase.m_kBehavior> 00 01 <XGUnitNativeBase.m_kBehavior> 09 00 <XGAIBehavior.m_kPod> 00 01 <XGAIBehavior.m_kPod> 0A 00 <NullRef> 00 1B <OnTakeDamage> 16 [#label6] //if(!kSelf.IsAlive() && bWasAlive) 07 [@label7] 82 81 19 00 <.kSelf> 0A 00 <XGUnitNativeBase.IsAlive.ReturnValue> 00 1B <IsAlive> 16 16 18 0B 00 2D 00 <.bWasAlive> 16 //DamageEvent_CauseOfDeath = Dmg 0F 01 <XComUnitPawnNativeBase.DamageEvent_CauseOfDeath> 00 <.Dmg> //if(kDamageDealer != none) 07 [@label8] 77 00 <.kDamageDealer> 2A 16 //kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 19 00 <.kDamageDealer> 3B 00 <NullRef> 00 1B <RecordKill> 00 <.kSelf> 61 02 35 <Engine.Actor.DamageEvent.DamageType> <Engine.Actor.DamageEvent> 00 00 00 <.Dmg> 20 <Class.XComDamageType_Explosion> 16 16 //if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) 07 [@label9] 82 82 19 00 <.kDamageDealer> 0A 00 <XGUnitNativeBase.IsMine.ReturnValue> 00 1B <IsMine> 16 18 24 00 9A 19 00 <.kSelf> 0A 00 <XGUnitNativeBase.GetCharType.ReturnValue> 00 1B <GetCharType> 16 2C 15 16 16 18 20 00 19 00 <.kSelf> 0A 00 <XGUnit.m_bHadShieldThisTurn> 00 2D 01 <XGUnit.m_bHadShieldThisTurn> 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64) 19 2E <Class.XComOnlineEventMgr> 19 2E <Engine.GameEngine> 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 09 00 <Engine.GameEngine.OnlineEventManager> 00 01 <Engine.GameEngine.OnlineEventManager> 0C 00 <NullRef> 00 1B <UnlockAchievement> 24 40 16 [#label9] //if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) 07 [@label8] 82 19 00 <.kDamageDealer> 0A 00 <XGUnitNativeBase.IsMine.ReturnValue> 00 1B <IsMine> 16 18 0B 00 2D 00 <.bWasVisibleOnlyWithBioelectricSkin> 16 //XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78) 19 2E <Class.XComOnlineEventMgr> 19 2E <Engine.GameEngine> 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 09 00 <Engine.GameEngine.OnlineEventManager> 00 01 <Engine.GameEngine.OnlineEventManager> 0C 00 <NullRef> 00 1B <UnlockAchievement> 24 4E 16 [#label8] //else 06 [@label10] [#label7] //if(GetGameUnit().IsAlive()) 07 [@label10] 19 1B <GetGameUnit> 16 0A 00 <XGUnitNativeBase.IsAlive.ReturnValue> 00 1B <IsAlive> 16 //if(kDamageDealer != none) 07 [@label11] 77 00 <.kDamageDealer> 2A 16 //kDamageDealer.RecordWounding(XGUnit(GetGameUnit())) 19 00 <.kDamageDealer> 1D 00 <NullRef> 00 1B <RecordWounding> 2E <Class.XGUnit> 1B <GetGameUnit> 16 16 [#label11] //ApplyShredderRocket(Dmg, enemyOfUnitHit) 1B <ApplyShredderRocket> 00 <.Dmg> 2D 00 <.enemyOfUnitHit> 16 [#label10] //return 04 0B //EOS 53 I don't have time, to test it in game, but the code it produces seems to be right: simulated event TakeDirectDamage(const DamageEvent Dmg) { local XGUnit kDamageDealer, kSelf; local DamageEvent actualDamage; local bool enemyOfUnitHit, bWasAlive, bWasVisibleOnlyWithBioelectricSkin; // End:0x30 if(!XGUnit(GetGameUnit()).CanTakeDamage()) { return; } kDamageDealer = XGUnit(Dmg.EventInstigator); kSelf = XGUnit(GetGameUnit()); // End:0xE5 if((kSelf.m_bIsDoingBullRush && kDamageDealer == kSelf) && Dmg.DamageType == class'XComDamageType_Melee') { return; } bWasAlive = kSelf.GetUnitHP() > 0; bWasVisibleOnlyWithBioelectricSkin = kSelf.m_bEnableBioElectricParticles && !IsVisible(); actualDamage = Dmg; // End:0x1E2 if((Dmg.EventInstigator != none) && kDamageDealer != none) { enemyOfUnitHit = kDamageDealer.GetTeam() != kSelf.GetTeam(); } // End:0x30D if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) { // End:0x30D if(XComProjectile(Dmg.DamageCauser) != none) { actualDamage.DamageAmount = int(0.50 + (float(Dmg.DamageAmount) * (1.0 - FMin(1.0, (0.50 * VSize(Dmg.DamageCauser.Location - Location)) / XComProjectile(Dmg.DamageCauser).DamageRadius)))); } } actualDamage.DamageAmount = kSelf.OnTakeDamage(actualDamage.DamageAmount, Dmg.DamageType, kDamageDealer, Dmg.HitLocation, Dmg.Momentum, Dmg.DamageCauser); // End:0x413 if(actualDamage.DamageAmount > 0) { super(Actor).TakeDirectDamage(actualDamage); } // End:0x4BB if((kSelf.m_kBehavior != none) && kSelf.m_kBehavior.m_kPod != none) { kSelf.m_kBehavior.m_kPod.OnTakeDamage(); } // End:0x6BE if(!kSelf.IsAlive() && bWasAlive) { DamageEvent_CauseOfDeath = Dmg; // End:0x6BB if(kDamageDealer != none) { kDamageDealer.RecordKill(kSelf, ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')); // End:0x62C if((kDamageDealer.IsMine() && kSelf.GetCharType() == 21) && kSelf.m_bHadShieldThisTurn) { XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(64); } // End:0x6BB if(kDamageDealer.IsMine() && bWasVisibleOnlyWithBioelectricSkin) { XComOnlineEventMgr(GameEngine(class'Engine'.static.GetEngine()).OnlineEventManager).UnlockAchievement(78); } } } // End:0x73F else { // End:0x73F if(GetGameUnit().IsAlive()) { // End:0x722 if(kDamageDealer != none) { kDamageDealer.RecordWounding(XGUnit(GetGameUnit())); } ApplyShredderRocket(Dmg, enemyOfUnitHit); } } //return; } Link to comment Share on other sites More sharing options...
Amineri Posted April 29, 2014 Author Share Posted April 29, 2014 I've coded up the second part to the mod that scales environmental damage down based on distance from the explosion center. This only applies to explosive-type effects, not flamethrower, fires, plasma, KSM body flying, etc. At the same time I also added a +/- 25% randomization to the environmental damage, applied separately to each XComDestructibleActor component. The code is added to XComDestructibleActor.ApplyDamageToMe, just after the environmental damage is retrieved but before it is saved/applied : if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) { if(XComProjectile(Dmg.DamageCauser) != none) { DamageAmount = int(0.50 + (float(DamageAmount) * (1.0 - FMin(1.0, (0.50 * VSize(Dmg.DamageCauser.Location - Location)) / XComProjectile(Dmg.DamageCauser).DamageRadius)))); } } if(DamageAmount > 0) { DamageAmount *= (0.750 + (0.50 * FRand())); } I've gone through and I'm pretty sure all of the Dmg references are to XComDestructibleActor.ApplyDamageToMe.Dmg. The full UPKmodder file is here: MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk FUNCTION=ApplyDamageToMe@XComDestructibleActor RESIZE=100 //reduce environmental damage based on distance from explosion center //randomize environmental damage on per-actor basis +/- 25% of base [BEFORE_HEX] [HEADER] 42 06 00 00 4E 04 00 00 [/HEADER] [CODE] //bFragile = (Toughness != none) && Toughness.bFragile 14 2D 00 D8 4A 00 00 82 77 01 9C 4A 00 00 2A 16 18 20 00 19 01 9C 4A 00 00 0A 00 98 54 00 00 00 2D 01 98 54 00 00 16 //bInvincible = (Toughness != none) && Toughness.bInvincible 14 2D 00 D7 4A 00 00 82 77 01 9C 4A 00 00 2A 16 18 20 00 19 01 9C 4A 00 00 0A 00 97 54 00 00 00 2D 01 97 54 00 00 16 //bSuccumbsToDamage = bInvincible && Toughness.bSuccumbsToDamage 14 2D 00 D6 4A 00 00 82 2D 00 D7 4A 00 00 18 20 00 19 01 9C 4A 00 00 0A 00 96 54 00 00 00 2D 01 96 54 00 00 16 //if((((Health <= 0) && IsInState('_Destroyed')) || bInvincible && !bSuccumbsToDamage) || !bFragile && !Dmg.DamageType.default.bCausesFracture) 07 3C 01 84 84 82 98 01 B3 4A 00 00 25 16 18 0E 00 61 19 21 7F 00 00 00 00 00 00 00 4A 16 16 18 1C 00 82 2D 00 D7 4A 00 00 18 0D 00 81 2D 00 D6 4A 00 00 16 16 16 18 46 00 82 81 2D 00 D8 4A 00 00 16 18 35 00 81 12 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0A 00 85 FF FF FF 00 2D 02 85 FF FF FF 16 16 16 //return 04 0B //if(bSuccumbsToDamage && Dmg.DamageType != Toughness.SuccumbsToDamageClass) 07 8C 01 82 2D 00 D6 4A 00 00 18 3D 00 77 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 19 01 9C 4A 00 00 09 00 94 54 00 00 00 01 94 54 00 00 16 16 //return 04 0B //bFragile = bFragile && !Dmg.DamageType.default.bCausesFracture 14 2D 00 D8 4A 00 00 82 2D 00 D8 4A 00 00 18 35 00 81 12 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0A 00 85 FF FF FF 00 2D 02 85 FF FF FF 16 16 //DamageAmount = Dmg.DamageAmount 0F 00 D5 4A 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 //if((Dmg.DamageCauser != none) && Dmg.DamageCauser.IsA('XComProjectile')) 07 B1 02 82 77 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 2A 16 18 34 00 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0B 00 CB FF FF FF 00 C5 21 32 81 00 00 00 00 00 00 16 16 //Proj = XComProjectile(Dmg.DamageCauser) 0F 00 D9 4A 00 00 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 //DamageAmount = Proj.WorldDamage 0F 00 D5 4A 00 00 19 00 D9 4A 00 00 09 00 D4 75 00 00 00 01 D4 75 00 00 //LastDamage = Dmg 0F 01 99 4A 00 00 48 DA 4A 00 00 //LastDamage.DamageAmount = DamageAmount 0F 35 02 FA FF FF 13 F9 FF FF 00 01 01 99 4A 00 00 00 D5 4A 00 00 //Health -= DamageAmount A2 01 B3 4A 00 00 00 D5 4A 00 00 16 //if(((Health <= 0) && !IsInState('_Destroyed')) && !bFragile) 07 6C 04 82 82 98 01 B3 4A 00 00 25 16 18 10 00 81 61 19 21 7F 00 00 00 00 00 00 00 4A 16 16 16 18 0D 00 81 2D 00 D8 4A 00 00 16 16 //GetComponentsBoundingBox(Bounds) 1C 4A FC FF FF 00 D4 4A 00 00 16 //BoundsExtents = Bounds.Max - Bounds.Min 0F 00 D3 4A 00 00 D8 35 A8 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 35 A7 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 16 //if(VSize(BoundsExtents) > 0.0) 07 1A 04 B1 E1 00 D3 4A 00 00 16 1E 00 00 00 00 16 //class'XComWorldData'.static.GetWorldData().PotentialFireColumns.AddItem((Bounds.Max + Bounds.Min) / 2.0) 55 19 12 20 2A 0C 00 00 0A 00 C8 D2 00 00 00 1B 47 3C 00 00 00 00 00 00 16 09 00 00 0D 00 00 00 01 00 0D 00 00 42 00 D6 D7 35 A8 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 35 A7 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 16 1E 00 00 00 40 16 16 //else 06 5B 04 //class'XComWorldData'.static.GetWorldData().PotentialFireColumns.AddItem(Location) 55 19 12 20 2A 0C 00 00 0A 00 C8 D2 00 00 00 1B 47 3C 00 00 00 00 00 00 16 09 00 00 0D 00 00 00 01 00 0D 00 00 0A 00 01 94 F8 FF FF 16 //GotoState('_Destroyed') 71 21 7F 00 00 00 00 00 00 00 4A 4A 4A 16 //else 06 3F 06 //if(((float(Health) <= (float(TotalHealth) * 0.750)) && !IsInState('_Damaged')) || bFragile) 07 3F 06 84 82 B2 38 3F 01 B3 4A 00 00 AB 38 3F 01 9A 4A 00 00 1E 00 00 40 3F 16 16 18 10 00 81 61 19 21 7A 00 00 00 00 00 00 00 4A 16 16 16 18 0B 00 2D 00 D8 4A 00 00 16 //if(((Dmg.DamageCauser == none) || !Dmg.DamageCauser.IsA('XComProjectile')) || XComProjectile(Dmg.DamageCauser).WeaponType != 97) 07 31 06 84 84 72 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 2A 16 18 36 00 81 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0B 00 CB FF FF FF 00 C5 21 32 81 00 00 00 00 00 00 16 16 16 18 43 00 9B 38 3A 19 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 09 00 BB 75 00 00 00 01 BB 75 00 00 38 3A 24 61 16 16 //if(((!Toughness.bFragile && !Toughness.bInvincible) && HasRadialDamage()) && XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.IsA('XGBattle_SP')) 07 31 06 82 82 82 81 19 01 9C 4A 00 00 0A 00 98 54 00 00 00 2D 01 98 54 00 00 16 18 22 00 81 19 01 9C 4A 00 00 0A 00 97 54 00 00 00 2D 01 97 54 00 00 16 16 18 0B 00 1B 92 3D 00 00 00 00 00 00 16 16 18 6A 00 19 19 2E E4 32 00 00 19 12 20 35 FE FF FF 0A 00 92 F9 FF FF 00 1C D5 FB FF FF 16 09 00 50 F9 FF FF 00 01 50 F9 FF FF 09 00 F0 32 00 00 00 01 F0 32 00 00 0B 00 CB FF FF FF 00 C5 21 55 82 00 00 00 00 00 00 16 16 //bDoCameraPan = true 14 2D 01 A8 4A 00 00 27 //SpeakWarning() 1B 73 73 00 00 00 00 00 00 16 //GotoState('_Damaged') 71 21 7A 00 00 00 00 00 00 00 4A 4A 4A 16 //return 04 0B //EOS 53 [/CODE] [/BEFORE_HEX] [AFTER_HEX] [HEADER] A2 07 00 00 4E 05 00 00 [/HEADER] [CODE] //bFragile = (Toughness != none) && Toughness.bFragile 14 2D 00 D8 4A 00 00 82 77 01 9C 4A 00 00 2A 16 18 20 00 19 01 9C 4A 00 00 0A 00 98 54 00 00 00 2D 01 98 54 00 00 16 //bInvincible = (Toughness != none) && Toughness.bInvincible 14 2D 00 D7 4A 00 00 82 77 01 9C 4A 00 00 2A 16 18 20 00 19 01 9C 4A 00 00 0A 00 97 54 00 00 00 2D 01 97 54 00 00 16 //bSuccumbsToDamage = bInvincible && Toughness.bSuccumbsToDamage 14 2D 00 D6 4A 00 00 82 2D 00 D7 4A 00 00 18 20 00 19 01 9C 4A 00 00 0A 00 96 54 00 00 00 2D 01 96 54 00 00 16 //if((((Health <= 0) && IsInState('_Destroyed')) || bInvincible && !bSuccumbsToDamage) || !bFragile && !Dmg.DamageType.default.bCausesFracture) 07 3C 01 84 84 82 98 01 B3 4A 00 00 25 16 18 0E 00 61 19 21 7F 00 00 00 00 00 00 00 4A 16 16 18 1C 00 82 2D 00 D7 4A 00 00 18 0D 00 81 2D 00 D6 4A 00 00 16 16 16 18 46 00 82 81 2D 00 D8 4A 00 00 16 18 35 00 81 12 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0A 00 85 FF FF FF 00 2D 02 85 FF FF FF 16 16 16 //return 04 0B //if(bSuccumbsToDamage && Dmg.DamageType != Toughness.SuccumbsToDamageClass) 07 8C 01 82 2D 00 D6 4A 00 00 18 3D 00 77 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 19 01 9C 4A 00 00 09 00 94 54 00 00 00 01 94 54 00 00 16 16 //return 04 0B //bFragile = bFragile && !Dmg.DamageType.default.bCausesFracture 14 2D 00 D8 4A 00 00 82 2D 00 D8 4A 00 00 18 35 00 81 12 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0A 00 85 FF FF FF 00 2D 02 85 FF FF FF 16 16 //DamageAmount = Dmg.DamageAmount 0F 00 D5 4A 00 00 35 02 FA FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 //if((Dmg.DamageCauser != none) && Dmg.DamageCauser.IsA('XComProjectile')) 07 B1 02 82 77 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 2A 16 18 34 00 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0B 00 CB FF FF FF 00 C5 21 32 81 00 00 00 00 00 00 16 16 //Proj = XComProjectile(Dmg.DamageCauser) 0F 00 D9 4A 00 00 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 //DamageAmount = Proj.WorldDamage 0F 00 D5 4A 00 00 19 00 D9 4A 00 00 09 00 D4 75 00 00 00 01 D4 75 00 00 //if(ClassIsChildOf(Dmg.DamageType, class'XComDamageType_Explosion')) 07 B6 03 61 02 35 63 FD FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 20 CA 52 00 00 16 //if(XComProjectile(Dmg.DamageCauser) != none) 07 B6 03 77 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 2A 16 //DamageAmount = int(0.5 + float(DamageAmount) * (1.0 - FMin(1.0, 0.5 * (VSize(Dmg.DamageCauser.Location - Location) / XComProjectile(Dmg.DamageCauser).DamageRadius)))) 0F 00 D5 4A 00 00 38 44 AE 1E 00 00 00 3F AB 38 3F 00 D5 4A 00 00 AF 1E 00 00 80 3F F4 1E 00 00 80 3F AC AB 1E 00 00 00 3F E1 D8 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF 01 94 F8 FF FF 16 16 16 19 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 09 00 C2 FC FF FF 00 01 C2 FC FF FF 16 16 16 16 16 //if(DamageAmount > 0) 07 E0 03 97 00 D5 4A 00 00 25 16 //DamageAmount *= 0.75 + (0.5 * FRand()) // randomize environmental damage +/- 25% 9F 00 D5 4A 00 00 AE 1E 00 00 40 3F AB 1E 00 00 00 3F C3 16 16 16 16 //LastDamage = Dmg 0F 01 99 4A 00 00 48 DA 4A 00 00 //LastDamage.DamageAmount = DamageAmount 0F 35 02 FA FF FF 13 F9 FF FF 00 01 01 99 4A 00 00 00 D5 4A 00 00 //Health -= DamageAmount A2 01 B3 4A 00 00 00 D5 4A 00 00 16 //if(((Health <= 0) && !IsInState('_Destroyed')) && !bFragile) 07 9B 05 82 82 98 01 B3 4A 00 00 25 16 18 10 00 81 61 19 21 7F 00 00 00 00 00 00 00 4A 16 16 16 18 0D 00 81 2D 00 D8 4A 00 00 16 16 //GetComponentsBoundingBox(Bounds) 1C 4A FC FF FF 00 D4 4A 00 00 16 //BoundsExtents = Bounds.Max - Bounds.Min 0F 00 D3 4A 00 00 D8 35 A8 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 35 A7 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 16 //if(VSize(BoundsExtents) > 0.0) 07 49 05 B1 E1 00 D3 4A 00 00 16 1E 00 00 00 00 16 //class'XComWorldData'.static.GetWorldData().PotentialFireColumns.AddItem((Bounds.Max + Bounds.Min) / 2.0) 55 19 12 20 2A 0C 00 00 0A 00 C8 D2 00 00 00 1B 47 3C 00 00 00 00 00 00 16 09 00 00 0D 00 00 00 01 00 0D 00 00 42 00 D6 D7 35 A8 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 35 A7 F8 FF FF 27 F9 FF FF 00 00 00 D4 4A 00 00 16 1E 00 00 00 40 16 16 //else 06 8A 05 //class'XComWorldData'.static.GetWorldData().PotentialFireColumns.AddItem(Location) 55 19 12 20 2A 0C 00 00 0A 00 C8 D2 00 00 00 1B 47 3C 00 00 00 00 00 00 16 09 00 00 0D 00 00 00 01 00 0D 00 00 0A 00 01 94 F8 FF FF 16 //GotoState('_Destroyed') 71 21 7F 00 00 00 00 00 00 00 4A 4A 4A 16 //else 06 6E 07 //if(((float(Health) <= (float(TotalHealth) * 0.750)) && !IsInState('_Damaged')) || bFragile) 07 6E 07 84 82 B2 38 3F 01 B3 4A 00 00 AB 38 3F 01 9A 4A 00 00 1E 00 00 40 3F 16 16 18 10 00 81 61 19 21 7A 00 00 00 00 00 00 00 4A 16 16 16 18 0B 00 2D 00 D8 4A 00 00 16 //if(((Dmg.DamageCauser == none) || !Dmg.DamageCauser.IsA('XComProjectile')) || XComProjectile(Dmg.DamageCauser).WeaponType != 97) 07 60 07 84 84 72 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 2A 16 18 36 00 81 19 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 0B 00 CB FF FF FF 00 C5 21 32 81 00 00 00 00 00 00 16 16 16 18 43 00 9B 38 3A 19 2E A9 76 00 00 35 B2 F9 FF FF 13 F9 FF FF 00 00 48 DA 4A 00 00 09 00 BB 75 00 00 00 01 BB 75 00 00 38 3A 24 61 16 16 //if(((!Toughness.bFragile && !Toughness.bInvincible) && HasRadialDamage()) && XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.IsA('XGBattle_SP')) 07 60 07 82 82 82 81 19 01 9C 4A 00 00 0A 00 98 54 00 00 00 2D 01 98 54 00 00 16 18 22 00 81 19 01 9C 4A 00 00 0A 00 97 54 00 00 00 2D 01 97 54 00 00 16 16 18 0B 00 1B 92 3D 00 00 00 00 00 00 16 16 18 6A 00 19 19 2E E4 32 00 00 19 12 20 35 FE FF FF 0A 00 92 F9 FF FF 00 1C D5 FB FF FF 16 09 00 50 F9 FF FF 00 01 50 F9 FF FF 09 00 F0 32 00 00 00 01 F0 32 00 00 0B 00 CB FF FF FF 00 C5 21 55 82 00 00 00 00 00 00 16 16 //bDoCameraPan = true 14 2D 01 A8 4A 00 00 27 //SpeakWarning() 1B 73 73 00 00 00 00 00 00 16 //GotoState('_Damaged') 71 21 7A 00 00 00 00 00 00 00 4A 4A 4A 16 //return 04 0B //null ops 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B //EOS 53 [/CODE] [/AFTER_HEX] ----------------- I also created a second little optional mod for this that applies an 8x scaling factor to difficulty-based alien bonus damage (by default it simply adds the bonus damage). This is applied in XGTacticalGameCore.CalcEnvironmentalDamage : iDamage = m_arrWeapons[iWeapon].iEnvironmentDamage + (8 * aCurrentStats[12]); For vanilla environmental damage values this isn't necessary, since all plasma weapons have 125 environmental damage, enough to destroy any DestructibleActor except a car (which has 250 toughness). However if the environmental damage numbers in the DGC.ini are modded down this may be of interest (we've done this in Long War). The full UPKmodder file : MODFILEVERSION=4 UPKFILE=XComGame.upk GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk FUNCTION=CalcEnvironmentalDamage@XGTacticalGameCore // apply scaling to bonus damage for environmental damage [BEFORE_HEX] [HEADER] 86 00 00 00 5E 00 00 00 [/HEADER] [CODE] //bCritical = false 49 02 00 28 15 //bHasHeightBonus = false 49 02 00 28 15 //fDistanceToTarget = 0.0 49 06 00 1E 00 00 00 00 15 //bUseFlankBonus = false 49 02 00 28 15 //iDamage = m_arrWeapons[iWeapon].iEnvironmentDamage + aCurrentStats[12] 0F 00 42 86 00 00 92 35 26 0F 00 00 2C 0F 00 00 00 00 10 00 4B 86 00 00 01 1B 12 00 00 1A 2C 0C 48 48 86 00 00 16 //if(iAbility == 34) 07 71 00 9A 00 4A 86 00 00 2C 22 16 //iDamage = 0 0F 00 42 86 00 00 25 //return iDamage 04 00 42 86 00 00 //return ReturnValue 04 3A 43 86 00 00 //EOS 53 [/CODE] [/BEFORE_HEX] [AFTER_HEX] [HEADER] 82 00 00 00 5E 00 00 00 [/HEADER] [CODE] //bCritical = false 49 02 00 28 15 //bHasHeightBonus = false 49 02 00 28 15 //fDistanceToTarget = 0.0 49 06 00 1E 00 00 00 00 15 //bUseFlankBonus = false 49 02 00 28 15 //iDamage = m_arrWeapons[iWeapon].iEnvironmentDamage + (8 * aCurrentStats[12]) 0F 00 42 86 00 00 92 35 26 0F 00 00 2C 0F 00 00 00 00 10 00 4B 86 00 00 01 1B 12 00 00 90 2C 08 1A 2C 0C 48 48 86 00 00 16 16 //if(iAbility == 34) 07 75 00 9A 00 4A 86 00 00 2C 22 16 //iDamage = 0 0F 00 42 86 00 00 25 //return iDamage 04 00 42 86 00 00 //null ops 0B 0B //EOS 53 [/CODE] [/AFTER_HEX] Link to comment Share on other sites More sharing options...
Recommended Posts