Taking damage
Author(s): benevolusgoatTags:
The MC_ENTITY_TAKE_DMG
callback has a number of useful applications for scenarios involving taking damage, namely as the player.
Callback breakdown⚓︎
MC_ENTITY_TAKE_DMG triggers when an entity takes damage, but before the damage is subtracted from the entity's health. It has 5 parameters, an optional argument, and a return type.
Parameters
ent
(Entity): The entity taking damage.amount
(integer
): If the player took damage, represents how many half-hearts of damage they're taking. If an enemy, it will return afloat
for the exact amount of Hit Points to be subtracted from the enemy.flags
(DamageFlag): A bitflag containing extra information about the how the damage was dealt and how it should be handled.source
(EntityRef): The source of the damage. The entity that dealt the damage can be accessed through itsEntity
variable, but this may returnnil
such as if the damage came from spikes. In these instances, you can check theType
andVariant
variables, whereType
will be0
andVariant
will be theGridEntityType
.countdown
(integer
): Will initiate a "damage countdown" if not already active. Any damage sources that deal damage with theDamageFlag.DAMAGE_COUNTDOWN
flag, such as The Nail, Gamekid, and My Little Unicorn, will not deal damage while the countdown is active.
Optional Argument
The optional argument for this callback is EntityType
. When specified, only entities with the matching type will trigger this callback.
1 |
|
Return type
You can return false
to prevent the damage from from being taken by the entity. Returning any value will stop the remaining callbacks from triggering.
With REPENTOGON, the callback's return functionality has been given an upgrade. You may return a table instead of a boolean and include any of the following fields to modify them:
Damage
: The amount of damage taken.DamageFlags
: The corresponding DamageFlags associated with the damage being taken.DamageCountdown
: The damage countdown set when the damage follows through.
In addition, instead of cancelling the remaining callbacks, it will pass these modified values along to them.
Triggering events upon Isaac taking damage⚓︎
Although this seems relatively simple, doing this incorrectly can make the difference of whether your code activates just once or in excessive amounts in a short period of time.
Non-REPENTOGON⚓︎
The only damage callback available is MC_ENTITY_TAKE_DMG
. Mods may cancel damage inside this callback, cancelling future callbacks for that particular damage instance from running. If the damage goes through, Isaac will typically initiate invincibility frames. If the damage is cancelled, there's nothing stopping the callback from triggering a second time as soon as possible. If your mod were to trigger an event upon taking damage, and a mod that runs after yours cancels the damage, your code would trigger every single frame. As such, it is important to utilize AddPriorityCallback
for situations where no "POST" callback exists.
AddPriorityCallback allows you to specify a CallbackPriority, meaning you can guarantee it will run earlier or later than other callbacks that don't specify one. Using CallbackPriority.LATE
means it will run after most other callbacks, thus can safely be used to trigger events upon taking damage.
1 |
|
REPENTOGON⚓︎
REPENTOGON adds MC_POST_ENTITY_TAKE_DMG
, which has no return types but will only trigger after the damage has gone through fully, skipping the need for AddPriorityCallback.
Modifying damage taken⚓︎
It's common to want to modify the flags of any damage being taken to enemies or players. This process is relatively straightfoward.
Non-REPENTOGON⚓︎
The only way to change information about the damage being dealt is to cancel it and deal damage a second time with Entity:TakeDamage. Note that dealing damage within MC_ENTITY_TAKE_DMG
the callback would typically result in an infinite loop. To avoid this, you can add the DAMAGE_CLONES
damage flag in the TakeDamage
function and then check for it. This DamageFlag is specifically used for avoiding infinite loops.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
REPENTOGON⚓︎
Referring back to the Return type section, you can return a table of values to modify attributes of the damage taken and it'll be passed along to the remaining callbacks.
1 2 3 4 5 6 7 8 9 |
|
Safe/Fake player damage⚓︎
Certain DamageFlags will prevent the player from losing devil or angel deal chance. The game uses this for things such as the curse room door. Detecting these sources can be seen within the flags
parameter. You can also modify the damage taken to use these flags yourself.
DamageFlag.DAMAGE_NO_PENALTIES
will prevent any penalties to the player, such as lowering devil deal chance or resetting Perfection progress. This andDamageFlag.DAMAGE_RED_HEARTS
will prevent rerolls from being trigered on Tainted Eden.DamageFlag.DAMAGE_FAKE
will not decrease Isaac's health, but can still trigger on-damage effects with the amount of damage that would've been taken. This is used by Dull Razor.
You can check, add, and remove bitflags using bitwise operations. You don't have to learn the exact details of how they work in order to utilize them, just remember what they do. The order in which they're positioned matters!
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|