@@ -183,6 +183,88 @@ void PatchPreLaserCollision() {
183183
184184// End of PRE_LASER_COLLISION patches
185185
186+
187+ // ---------- Beginning of MC_(POST_)ENTITY_TAKE_DMG related patches --------------------------------------------------
188+
189+ // Place to temporarily store "extra sources" to pass to the TakeDamage callbacks.
190+ // These refs are keyed by the address of the primary EntityRef created for, and passed to, the TakeDamage call.
191+ // An entry in this map is added right before the TakeDamage call, and removed immediately afterwards,
192+ // allowing access to the extra source for the duration of the TakeDamage call.
193+ // Should not be modified outside of `TakeDamageWithExtraSource`.
194+ static std::unordered_map<uintptr_t , EntityRef> _TakeDamageExtraSources;
195+
196+ // Fetch the extra source for a TakeDamage source, if any exists.
197+ static EntityRef* GetExtraTakeDamageSource (EntityRef* source) {
198+ if (source && _TakeDamageExtraSources.find ((uintptr_t )source) != _TakeDamageExtraSources.end ()) {
199+ EntityRef* extraSource = &_TakeDamageExtraSources[(uintptr_t )source];
200+ if (extraSource && extraSource->_entity != source->_entity ) {
201+ return extraSource;
202+ }
203+ }
204+ return nullptr ;
205+ }
206+
207+ // Call TakeDamage with an "extra source", available via the standard "source" for the TAKE_DMG callbacks.
208+ // Patches are used to overwrite relevant TakeDamage calls with this one that enables the extra source.
209+ bool __stdcall TakeDamageWithExtraSource (Entity* damagedEntity, float damage, uint64_t damageFlags, EntityRef* source, int damageCountdown, Entity* extraSourceEntity) {
210+ _TakeDamageExtraSources[(uintptr_t )source] = EntityRef (extraSourceEntity);
211+ bool result = damagedEntity->TakeDamage (damage, damageFlags, source, damageCountdown);
212+ _TakeDamageExtraSources.erase ((uintptr_t )source);
213+ return result;
214+ }
215+ void PatchLaserDoDamageExtraSourcePushEbx (char * asmDef, int overriddenBytes) {
216+ void * addr = sASMDefinitionHolder ->GetDefinition (asmDef);
217+ printf (" [REPENTOGON] Patching Entity_Laser::DoDamage at %p\n " , addr);
218+ ASMPatch patch;
219+ patch.Push (ASMPatch::Registers::EBX)
220+ .AddBytes (ByteBuffer ().AddAny ((char *)addr, overriddenBytes))
221+ .AddRelativeJump ((char *)addr + overriddenBytes);
222+ sASMPatcher .PatchAt (addr, &patch);
223+ }
224+ void PatchLaserDoDamageExtraSource (char * asmDef, int bytesToCopy) {
225+ void * addr = sASMDefinitionHolder ->GetDefinition (asmDef);
226+ void * exitAddr = sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::LaserDoDamageExit);
227+
228+ printf (" [REPENTOGON] Patching Entity::TakeDamage call in Entity_Laser::DoDamage at %p\n " , addr);
229+
230+ ASMPatch::SavedRegisters savedRegisters ((ASMPatch::SavedRegisters::Registers::GP_REGISTERS_STACKLESS | ASMPatch::SavedRegisters::Registers::XMM_REGISTERS) & ~ASMPatch::SavedRegisters::Registers::EAX, true );
231+ ASMPatch patch;
232+ patch.Pop (ASMPatch::Registers::EAX)
233+ .PreserveRegisters (savedRegisters)
234+ .Push (ASMPatch::Registers::EAX)
235+ .AddBytes (ByteBuffer ().AddAny ((char *)addr, bytesToCopy))
236+ .Push (ASMPatch::Registers::ECX)
237+ .AddInternalCall (TakeDamageWithExtraSource)
238+ .RestoreRegisters (savedRegisters)
239+ .AddRelativeJump (exitAddr);
240+ sASMPatcher .PatchAt (addr, &patch);
241+ }
242+ void PatchTakeDamageWithExtraSource (char * desc, char * asmDef, ASMPatch::Registers extraSourceRegister, char * offsetAsmDef, int bytesToCopy, int addJump) {
243+ void * addr = sASMDefinitionHolder ->GetDefinition (asmDef);
244+
245+ int offset = 0 ;
246+ if (offsetAsmDef) {
247+ offset = *(int *)((char *)sASMDefinitionHolder ->GetDefinition (offsetAsmDef) + 0x2 );
248+ }
249+
250+ printf (" [REPENTOGON] Patching Entity::TakeDamage call for ExtraSource (%s) at %p\n " , desc, addr);
251+
252+ ASMPatch::SavedRegisters savedRegisters ((ASMPatch::SavedRegisters::Registers::GP_REGISTERS_STACKLESS | ASMPatch::SavedRegisters::Registers::XMM_REGISTERS) & ~ASMPatch::SavedRegisters::Registers::EAX, true );
253+ ASMPatch patch;
254+ patch.PreserveRegisters (savedRegisters);
255+ if (offsetAsmDef) {
256+ patch.Push (extraSourceRegister, offset);
257+ } else {
258+ patch.Push (extraSourceRegister);
259+ }
260+ patch.AddBytes (ByteBuffer ().AddAny ((char *)addr, bytesToCopy))
261+ .Push (ASMPatch::Registers::ECX)
262+ .AddInternalCall (TakeDamageWithExtraSource)
263+ .RestoreRegisters (savedRegisters)
264+ .AddRelativeJump ((char *)addr + bytesToCopy + addJump);
265+ sASMPatcher .PatchAt (addr, &patch);
266+ }
267+
186268/* * MC_ENTITY_TAKE_DMG REIMPLEMENTATION * *
187269* This section patches in a new ENTITY_TAKE_DMG callback with table returns for overridding.
188270* A patch is used because ENTITY_TAKE_DMG runs in the middle of the TakeDamage functions,
@@ -192,8 +274,9 @@ void PatchPreLaserCollision() {
192274* We need to patch into both Entity::TakeDamage AND EntityPlayer::TakeDamage.
193275*/
194276bool __stdcall ProcessPreDamageCallback (Entity* entity, float * damage, int * damageHearts, uint64_t * damageFlags, EntityRef* source, int * damageCountdown, const bool isPlayer) {
195- const int callbackid = 11 ;
277+ EntityRef* extraSource = GetExtraTakeDamageSource (source) ;
196278
279+ const int callbackid = 11 ;
197280 if (VanillaCallbackState.test (callbackid)) {
198281 lua_State* L = g_LuaEngine->_state ;
199282 lua::LuaStackProtector protector (L);
@@ -212,7 +295,8 @@ bool __stdcall ProcessPreDamageCallback(Entity* entity, float* damage, int* dama
212295 }
213296 caller.push (*damageFlags)
214297 .push (source, lua::Metatables::ENTITY_REF)
215- .push (*damageCountdown);
298+ .push (*damageCountdown)
299+ .push (extraSource, lua::Metatables::ENTITY_REF);
216300 lua::LuaResults lua_result = caller.call (1 );
217301
218302 if (!lua_result) {
@@ -283,7 +367,6 @@ bool __stdcall ProcessPreDamageCallback(Entity* entity, float* damage, int* dama
283367
284368 return true ;
285369}
286-
287370void InjectPreDamageCallback (void * addr, bool isPlayer) {
288371 printf (" [REPENTOGON] Patching %s::TakeDamage for MC_ENTITY_TAKE_DMG at %p\n " , isPlayer ? " Entity_Player" : " Entity" , addr);
289372
@@ -337,26 +420,18 @@ void InjectPreDamageCallback(void* addr, bool isPlayer) {
337420 sASMPatcher .PatchAt (addr, &patch);
338421}
339422
340- // Patches overtop the existing calls to LuaEngine::Callback::EntityTakeDamage,
341- // within the Entity::TakeDamage and EntityPlayer::TakeDamage functions respectively.
342- void PatchPreEntityTakeDamageCallbacks () {
343- InjectPreDamageCallback (sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PreEntityCallback), false );
344- InjectPreDamageCallback (sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PrePlayerCallback), true );
345- }
346-
347423// Even though I patched overtop the calls to this callback, super kill it for good measure.
348424HOOK_METHOD (LuaEngine, EntityTakeDamage, (Entity* entity, float damage, unsigned long long damageFlags, EntityRef* source, int damageCountdown) -> bool) { return true ; }
349425
350- // End of ENTITY_TAKE_DMG patches
351-
352426/* * MC_POST_ENTITY_TAKE_DMG * *
353427* A hook worked just fine for ""POST_TAKE_DMG"" initially, but now that we support overidding
354428* values via ENTITY_TAKE_DMG (see above) we need the POST_TAKE_DMG callback to actually show
355429* those modified values. That means another patch!!
356430* Like before, we need to patch into both Entity::TakeDamage and EntityPlayer::TakeDamage.
357431*/
358-
359432void __stdcall ProcessPostDamageCallback (Entity* entity, const float damage, const uint64_t damageFlags, EntityRef* source, const int damageCountdown, const bool isPlayer) {
433+ EntityRef* extraSource = GetExtraTakeDamageSource (source);
434+
360435 const int callbackid = 1006 ;
361436 if (CallbackState.test (callbackid - 1000 )) {
362437 if (isPlayer && source->_type == 33 && source->_variant == 4 ) {
@@ -381,10 +456,10 @@ void __stdcall ProcessPostDamageCallback(Entity* entity, const float damage, con
381456 caller.push (damageFlags)
382457 .push (source, lua::Metatables::ENTITY_REF)
383458 .push (damageCountdown)
459+ .push (extraSource, lua::Metatables::ENTITY_REF)
384460 .call (1 );
385461 }
386462};
387-
388463void InjectPostDamageCallback (void * addr, bool isPlayer) {
389464 printf (" [REPENTOGON] Patching %s::TakeDamage for MC_POST_ENTITY_TAKE_DMG at %p\n " , isPlayer ? " Entity_Player" : " Entity" , addr);
390465 const int numOverriddenBytes = (isPlayer ? 10 : 5 );
@@ -426,15 +501,32 @@ void InjectPostDamageCallback(void* addr, bool isPlayer) {
426501 sASMPatcher .PatchAt (addr, &patch);
427502}
428503
429- // These patches overwrite suitably-sized commands near where the respective TakeDamage functions would return.
430- // The overridden bytes are restored by the patch.
431- void PatchPostEntityTakeDamageCallbacks () {
432- // Sig is 6 bytes before where we actually want to patch to avoid bleeding past the end of the function.
504+ void PatchEntityTakeDamageCallbacks () {
505+ // Patches overtop the existing calls to LuaEngine::Callback::EntityTakeDamage,
506+ // within the Entity::TakeDamage and EntityPlayer::TakeDamage functions respectively.
507+ InjectPreDamageCallback (sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PreEntityCallback), false );
508+ InjectPreDamageCallback (sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PrePlayerCallback), true );
509+
510+ // These patches overwrite suitably-sized commands near where the respective TakeDamage functions would return.
511+ // The overridden bytes are restored by the patch.
512+ // First sig is 6 bytes before where we actually want to patch to avoid bleeding past the end of the function.
433513 InjectPostDamageCallback ((char *)sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PostEntityCallback) + 0x6 , false );
434514 InjectPostDamageCallback (sASMDefinitionHolder ->GetDefinition (&AsmDefinitions::TakeDmg_PostPlayerCallback), true );
515+
516+ // Patches over TakeDamage calls to allow providing an ExtraSource.
517+ PatchLaserDoDamageExtraSourcePushEbx (&AsmDefinitions::LaserDoDamagePushEbxA, 0x7 );
518+ PatchLaserDoDamageExtraSourcePushEbx (&AsmDefinitions::LaserDoDamagePushEbxB, 0x8 );
519+ PatchLaserDoDamageExtraSource (&AsmDefinitions::LaserDoDamageA, 0x14 );
520+ PatchLaserDoDamageExtraSource (&AsmDefinitions::LaserDoDamageB, 0xF );
521+ PatchTakeDamageWithExtraSource (" Entity_Laser::do_damage, player" , &AsmDefinitions::LaserDoDamagePlayer, ASMPatch::Registers::EBX, nullptr , 0x11 , 0x3 );
522+ PatchTakeDamageWithExtraSource (" Entity_Knife::update_bone_swing" , &AsmDefinitions::UpdateBoneSwingDamage, ASMPatch::Registers::ESI, nullptr , 0x1A , 0x2 );
523+ PatchTakeDamageWithExtraSource (" Entity_Knife::update_bone_swing, fireplace" , &AsmDefinitions::UpdateBoneSwingDamageFireplace, ASMPatch::Registers::ESI, nullptr , 0x11 , 0x3 );
524+ PatchTakeDamageWithExtraSource (" Entity_Familiar::ai_umbilical_baby" , &AsmDefinitions::GelloDamage, ASMPatch::Registers::EBP, &AsmDefinitions::GelloDamageEbpOffset, 0x1A , 0x2 );
525+ PatchTakeDamageWithExtraSource (" Entity_Familiar::ai_umbilical_baby, fireplace" , &AsmDefinitions::GelloDamageFireplace, ASMPatch::Registers::EBP, &AsmDefinitions::GelloDamageEbpOffset, 0x11 , 0x3 );
526+ PatchTakeDamageWithExtraSource (" Entity_Effect::Update, Brimstone Ball" , &AsmDefinitions::BrimstoneBallDamage, ASMPatch::Registers::EBP, &AsmDefinitions::BrimstoneBallDamageEbpOffset, 0x36 , 0x2 );
435527}
436528
437- // End of POST_ENTITY_TAKE_DMG patches
529+ // ---------- End of MC_(POST_)ENTITY_TAKE_DMG related patches --------------------------------------------------
438530
439531
440532// MC_PRE_PLAYER_USE_BOMB
0 commit comments