Getting the damage/hit value
Just going through the Combat stuff
Is it possible to retrieve the exact amount of damage being done either by Dink or by an enemy sprite in a strike?
I found The Prophet's post on this, but it doesn't account for the fact that the initial strength of attack varies/is random as per the DinkC Reference
Step 1. When Dink or a monster hits the other, a number of hitpoints is randomly selected from the upper half of its strength range. In DinkC terms, you might write it like this:
Perhaps something clever can be done with sp_custom here - I still haven't got my head around this stuff, looking through magicman's persistent loot scripts... I tried to set sp_nohit() to 1 in these custom procedures so that the smashing sound of the barrel doesn't repeat all the time which I was getting in my dmod, and happens in the Persistent Loot dmod as well, but it had no effect.
Is it possible to retrieve the exact amount of damage being done either by Dink or by an enemy sprite in a strike?
I found The Prophet's post on this, but it doesn't account for the fact that the initial strength of attack varies/is random as per the DinkC Reference
Step 1. When Dink or a monster hits the other, a number of hitpoints is randomly selected from the upper half of its strength range. In DinkC terms, you might write it like this:
int &hit_work = sp_strength(enemySprite, -1); int &hits = math_mod(&hit_work, 2); &hit_work / 2; int &add_remainder = &hit_work; &add_remainder += &hits; &hits = random(&add_remainder, &hit_work); &hits += 1;
Perhaps something clever can be done with sp_custom here - I still haven't got my head around this stuff, looking through magicman's persistent loot scripts... I tried to set sp_nohit() to 1 in these custom procedures so that the smashing sound of the barrel doesn't repeat all the time which I was getting in my dmod, and happens in the Persistent Loot dmod as well, but it had no effect.
Yeh that DinkC example does indeed mirror the same result as the internal damage code.
As for getting the exact damage done to a sprite, I'm not sure, I've never tried, are you trying to retrieve the raw amount of damage done before defense is taken into account or just the end result of damage done after calc. I can't think of a way off the top of my head aside from setting all actual damage to 0 on hit and just calling an external that handles that same damage calculation so it yields the same result but you have the number available to you. I did that with missile damage in Charlie for other reasons.
As for that repeating barrel hit sound... I'm not entirely sure what that's in relation to, but that sounds like something that should be solvable. Could you link me a script or more info and I'll test?
Edit: nvm I just noticed you said it happens in persistent loot. I'll test when I get home.
As for getting the exact damage done to a sprite, I'm not sure, I've never tried, are you trying to retrieve the raw amount of damage done before defense is taken into account or just the end result of damage done after calc. I can't think of a way off the top of my head aside from setting all actual damage to 0 on hit and just calling an external that handles that same damage calculation so it yields the same result but you have the number available to you. I did that with missile damage in Charlie for other reasons.
As for that repeating barrel hit sound... I'm not entirely sure what that's in relation to, but that sounds like something that should be solvable. Could you link me a script or more info and I'll test?
Edit: nvm I just noticed you said it happens in persistent loot. I'll test when I get home.
I after a couple of things... but the first is making sure one enemy can't hurt another, only Dink. The other is, I forgot... but it'll come back to me one day.
It should be possible to check the enemy_sprite var in the sprite's hit(). Otherwise, the raw damage calculation is thrown away by the engine, and the post-def damage parameter in sprites is not accessible through scripting.
@SimonK
Okay, here's a script I made that will accomplish everything you need, you can apply this to individual enemies just by adding 1 external call in the HIT procedure and a couple sp_custom lines in the MAIN procedure, so you don't have to go messing about with a bunch of scripts in the Dmod. It took a bit of fine tuning and testing, and comparing everything against the source code, but it will mimick an attack exactly as the internal engine does it, calculating the damage, generating the blood and also generating the floating damage number text sprite. Since I had to disable the sp_hitpoints and manage hitpoints manually through a sp_custom value I also had to manually handle the death as well, which is fine, it's all contained in the 1 external call. It's easy to implement and use, as below.
EDIT: I updated the below script to remove something from it I used to debug it(forgot to remove before uploading) so if you grabbed it before this edit, re-download it.
First add apply.c to your story folder.
Please note this script uses no local variables so it won't consume any extra variable slots, but it does use global variables &save_x and &save_y to juggle variables. If you don't have those declared, declare them or search and replace them with your own global juggle variables.
Then do the below 4 simple steps to use it in an enemy script:
Step 1: Change your enemies sp_hitpoints to 0.
Step 2: Add this line and set the hitpoints value to whatever you wanted the sp_hitpoints to be:
Step 3: Since basewalk and basedeath can't be retrieved and my script needs to access these values, add the sp_custom lines as below but change "value" to the same as the actual sp_base_walk and sp_base_death(these are in addition to sp_base_walk and sp_base_death, don't remove those from your enemy script). You only need to include the sp_custom base death line if your enemy actually has a sp_base_death set.
Step 4: Add this at the START of the HIT procedure, and you can pass values to &arg1-&arg8 and enemies with those brains will not be able to damage the current_sprite.
Example use cases and notes
So if you want your sprite to be immune from damage for brain 9 sprites and brain 11 sprites(missiles) for example, the external call at the start of your hit procedure would be:
the external function will also return the damage/hit value. You can also retrieve the LAST raw damage done to the current_sprite(raw damage is prior to taking defense into account) at any time by retrieving value from sp_custom("dmg_raw", ¤t_sprite, -1);. And you can retrieve the LAST actual damage/hit value done at anytime using sp_custom("dmg_calc", ¤t_sprite, -1);
Important to note: sp_custom strings are case sensitive, use them exactly as they are above. E.g don't do "HP" instead of "hp".
If you pass a missile brain such as fireball as one of the brains to ignore damage from and you find it's still dealing damage, also pass brain 7. Tested with fireball, when my script retrieves the brain of the fireball sprite it's already changed to brain 7 (seq die), so that's what it detects it as.
One additional obscure thing to consider: If your sprite doesn't have a base death and also doesn't have a death sequence in it's basewalk+5 seq slot, unlike the internal engine, my script will not automatically be able to detect these both don't exist, and it won't play the sequence 164 blood explosion default death. If you want sequence 164 to play on death instead of an actual death sequence, then set sp_custom("base_death", ¤t_sprite, 164);
I tested it in DinkHD and YeOldeDink, but if you find any problems/bugs let me know and I can fix it.
Okay, here's a script I made that will accomplish everything you need, you can apply this to individual enemies just by adding 1 external call in the HIT procedure and a couple sp_custom lines in the MAIN procedure, so you don't have to go messing about with a bunch of scripts in the Dmod. It took a bit of fine tuning and testing, and comparing everything against the source code, but it will mimick an attack exactly as the internal engine does it, calculating the damage, generating the blood and also generating the floating damage number text sprite. Since I had to disable the sp_hitpoints and manage hitpoints manually through a sp_custom value I also had to manually handle the death as well, which is fine, it's all contained in the 1 external call. It's easy to implement and use, as below.
EDIT: I updated the below script to remove something from it I used to debug it(forgot to remove before uploading) so if you grabbed it before this edit, re-download it.
First add apply.c to your story folder.
Please note this script uses no local variables so it won't consume any extra variable slots, but it does use global variables &save_x and &save_y to juggle variables. If you don't have those declared, declare them or search and replace them with your own global juggle variables.
Then do the below 4 simple steps to use it in an enemy script:
Step 1: Change your enemies sp_hitpoints to 0.
Step 2: Add this line and set the hitpoints value to whatever you wanted the sp_hitpoints to be:
sp_custom("hp", ¤t_sprite, hitpoints_value_here);
Step 3: Since basewalk and basedeath can't be retrieved and my script needs to access these values, add the sp_custom lines as below but change "value" to the same as the actual sp_base_walk and sp_base_death(these are in addition to sp_base_walk and sp_base_death, don't remove those from your enemy script). You only need to include the sp_custom base death line if your enemy actually has a sp_base_death set.
sp_custom("base_walk", ¤t_sprite, value); sp_custom("base_death", ¤t_sprite, value);
Step 4: Add this at the START of the HIT procedure, and you can pass values to &arg1-&arg8 and enemies with those brains will not be able to damage the current_sprite.
external("apply", "damage");
Example use cases and notes
So if you want your sprite to be immune from damage for brain 9 sprites and brain 11 sprites(missiles) for example, the external call at the start of your hit procedure would be:
external("apply", "damage", 9, 11);
the external function will also return the damage/hit value. You can also retrieve the LAST raw damage done to the current_sprite(raw damage is prior to taking defense into account) at any time by retrieving value from sp_custom("dmg_raw", ¤t_sprite, -1);. And you can retrieve the LAST actual damage/hit value done at anytime using sp_custom("dmg_calc", ¤t_sprite, -1);
//at the start of the HIT procedure external("apply", "damage"); say("I've just been hit for &return damage!", ¤t_sprite);
//Use this anywhere to grab the LAST damge/hit value done to this sprite sp_custom("dmg_calc", ¤t_sprite, -1); say("The last hit I took was for &return damage!", ¤t_sprite);
//Use this anywhere to grab the LAST raw damage done to this sprite sp_custom("dmg_raw", ¤t_sprite, -1); say("Damage value of &return, prior to factoring in my defense", ¤t_sprite);
Important to note: sp_custom strings are case sensitive, use them exactly as they are above. E.g don't do "HP" instead of "hp".
If you pass a missile brain such as fireball as one of the brains to ignore damage from and you find it's still dealing damage, also pass brain 7. Tested with fireball, when my script retrieves the brain of the fireball sprite it's already changed to brain 7 (seq die), so that's what it detects it as.
One additional obscure thing to consider: If your sprite doesn't have a base death and also doesn't have a death sequence in it's basewalk+5 seq slot, unlike the internal engine, my script will not automatically be able to detect these both don't exist, and it won't play the sequence 164 blood explosion default death. If you want sequence 164 to play on death instead of an actual death sequence, then set sp_custom("base_death", ¤t_sprite, 164);
I tested it in DinkHD and YeOldeDink, but if you find any problems/bugs let me know and I can fix it.
Bugger. There's a typo I just found in the previous script that will make it so if no base death is set it won't create the corpse seq base_walk+5. Just fixed it, here's the new apply.c (above link is updated too).
Also forgot to mention in previous post that if for some reason you want to set a custom sp_blood_num and sp_blood_seq on the enemy, sp_blood_num also can't be retrieved by my script, so it needs an additional sp_custom line so my script can retrieve it:
sp_custom("blood_num", ¤t_sprite, value_here);
Not many people use sp_blood_num so it slipped my mind to mention it, even though I did actually include it. sp_blood_seq is fine though, no need for a sp_custom line for that.
Also forgot to mention in previous post that if for some reason you want to set a custom sp_blood_num and sp_blood_seq on the enemy, sp_blood_num also can't be retrieved by my script, so it needs an additional sp_custom line so my script can retrieve it:
sp_custom("blood_num", ¤t_sprite, value_here);
Not many people use sp_blood_num so it slipped my mind to mention it, even though I did actually include it. sp_blood_seq is fine though, no need for a sp_custom line for that.
Thanks, I do use the sp_blood stuff, at least once, but will probably use it more now that the sequence/Sprite image limits have been raised.

Interestingly for me... as I have a custom procedure that gives the opportunity to idle a little more visually better, I need to keep the standard sp_base_walk() in that custom idle procedure, as well as the sp_custom() version, and all works well.
I wrote this custom idle procedure before Yeoldtoast had implemented base_idle for YOD... which I've yet to test. Anyway it kinda got sidelined because I was increasing graphic count as well back then... so I only have one character who is actually animated in his idle position, a blacksmith. Mind you I could now go back and add more stuff, now that the graphics limit has been raised with the latest version of DinkHD.
Something for the full version...
I wrote this custom idle procedure before Yeoldtoast had implemented base_idle for YOD... which I've yet to test. Anyway it kinda got sidelined because I was increasing graphic count as well back then... so I only have one character who is actually animated in his idle position, a blacksmith. Mind you I could now go back and add more stuff, now that the graphics limit has been raised with the latest version of DinkHD.
Something for the full version...
Hmmm, I tried brain 1 and 11 as exceptions, but for some reason it doesn't work for me. Brain 9 does which is great.
EDIT
Okay, now it does work... not sure what I was doing wrong before... Probably just bad scripting on my part...
EDIT
Okay, now it does work... not sure what I was doing wrong before... Probably just bad scripting on my part...

Unfortunately I haven't finished idles for NPC-brained sprites, only diagonal idles for the player. I may add a new separate brain for it like I have done for various other things.