Okay, prepare to be educated!
First off, some notes:
- onHealthChange() and onManaChange() events are only called when health and mana are changed, respectively!
- Yes, that means if there is a poff/spark, onHealthChange()/onManaChange() will never be called!
- All parameters MUST be used or it will not work!
- Do not worry about trying to figure out what to put if you can't think of anything, they have default values, just need to use the names alone!
- Be smart, please remember this is called every time when health/mana changes, so don't bloat it up with dirty and messy code.
Here is the creature event function:
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
Here are what the parameters mean:
- creature: the victim, the one whose health is changing
- attacker: the one changing the health, it can be nil (fields, traps, etc)
- primaryDamage: the primary damage
- primaryType: the type of the primary damage
- secondaryDamage: the secondary damage
- secondaryType: the type of the secondary damage
- origin: the type of attack
- ORIGIN_NONE
- ORIGIN_CONDITION
- ORIGIN_SPELL
- ORIGIN_MELEE
- ORIGIN_RANGED
You can find information on our beloved Wiki
What is the difference between primary and secondary?
This is pretty self-explanatory, let's say you have a firesword or an earth-enchanged warhammer.
The primary type will be physical, the secondary type is the elemental one (fire and earth, respectively).
secondaryDamage/
secondaryType is only applied when there is a secondary damage/type, so it's somewhat uncommon.
Let's get into some examples:
In this example, I'm just showing you who the attacker and the creature are.
Remember, the attacker is the one changing the health, the victim is the one whose health is being changed.
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
attacker:sendTextMessage(MESSAGE_EVENT_ORANGE, "Attacker: " .. attacker:getName() .. "\n")
attacker:sendTextMessage(MESSAGE_EVENT_ORANGE, "Victim: " .. creature:getName() .. "\n")
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
Now let's say you want to have a bonus added to your weapon.
So, you can have a plain club and a special club (both same id), except special club has actionid 1000.
The special club will do twice the damage that a plain club will do.
So, when we change someone's health, we need to double the primary damage.
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if attacker:getSlotItem(CONST_SLOT_LEFT):getActionId() == 1000 then
return primaryDamage * 2, primaryType, secondaryDamage, secondaryType
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
As you can see, I multiplied primaryDamage just by doing:
primaryDamage * 2
Plain club:
Special club (actionid 1000):
Let's keep going, right? It's pretty fun!
Let's play around with primary types. We'll have a 50-50 chance of hitting
fire damage or
ice damage.
Pretty simple, just need to set the
primaryType to their respective types when a random number falls in the right spot.
NOTE:
You can see all the primary types here
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if math.random(100) <= 50 then
return primaryDamage, COMBAT_FIREDAMAGE, secondaryDamage, secondaryType
end
return primaryDamage, COMBAT_ICEDAMAGE, secondaryDamage, secondaryType
end
Pretty simple? Let's go deeper, shall we? We'll use a firesword for this example.
We want to modify the types for the firesword. Remember, a firesword is one of those weapons
that have both a primary and secondary damage/type. It attacks with
physical and
fire.
Let's change them, again on 50-50 chance, to
earth and
energy?
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if math.random(100) <= 50 then
return primaryDamage, COMBAT_ENERGYDAMAGE, secondaryDamage, COMBAT_EARTHDAMAGE
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
Note that the
primaryType and
secondaryType inside the if statement are changed to
earth and
energy.
The
fire and
physical damage are defaulted from the firesword. So you don't need to change the
primaryType and
secondaryType in the end (outside the if statement).
Super simple, right? Now, I know this thread is about
critical hits, so let's do that then.
From my understanding of critical hits, each time a player hits someone, there's a chance of dealing X additional damage.
As we've learned up to now, we can multiply damage and we can apply a chance (ofcourse...). So, let's mix the two.
But wait, let's make it more customized. Let's have a
message appear above the creatures head when a critical hit happens. And let's make it even more unique, let's have different messages depending on the type of attack.
In this example, melee attacks will have the message "
SKULLBASH!" and distance attacks will have the message "
HEADSHOT!". Also, they both will deal
10 times the original damage.
Remember, the
origin parameter will tell us what type of attack has occurred. You can see their types above.
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if math.random(100) <= 50 then
if origin == ORIGIN_MELEE then
creature:say("SKULLBASH!", TALKTYPE_MONSTER_SAY)
elseif origin == ORIGIN_RANGED then
creature:say("HEADSHOT!", TALKTYPE_MONSTER_SAY)
end
return primaryDamage * 10, primaryType, secondaryDamage, secondaryType
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
NOTE: I did not include the ORIGIN_RANGED example because it is bugged. No matter what distance weapon you use the server will always respond with ORIGIN_MELEE. I've reported this to
@Dalkon and a fix should be on the way soon.
Last example I have, let's use the ORIGIN_SPELL type. Let's say you have a super ability that absorbs all
spell damages. That means, when someone uses a damage spell on you, it will heal you instead.
Pretty simple, just use COMBAT_HEALING for the
primaryType. COMBAT_HEALING is technically just healing damage, so you don't need to modify
primaryDamage to make it heal, in fact, it doesn't work this way, you have to use COMBAT_HEALING.
Code:
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if origin == ORIGIN_SPELL then
return primaryDamage, COMBAT_HEALING, secondaryDamage, COMBAT_HEALING
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
There's definitely THOUSANDS of different things you can do, all you need to do is have a lot of creativity.