1. The player meets an enemy & engages
2. The enemy takes some damage
3. When the enemy has taken a specified amount of damage (or when its health drops to a specified level, whichever is easier) it is teleported to another location
I want to use ACS to determine when the enemy has taken the necessary damage to teleport it away. I have searched the forums and the wiki, and I've not found the specials necessary for this task.
I'd greatly appreciate any help in this matter.
[For reference, my script currently teleports the enemy after a specified duration, which won't really work if the player can destroy the enemy before that duration ends:
script "Monitor HP then execute code" (int mtid) {
int actorhp = GetActorProperty (mtid, APROP_HEALTH);
if (actorhp <= 100) {
//Do stuff
}
else {restart;}
}
Something like this work?
Re: Triggering Action When Monster Loses x Health
Posted: Wed Aug 31, 2016 9:23 am
by Graf Zahl
That needs at least a delay.
Re: Triggering Action When Monster Loses x Health
Posted: Wed Aug 31, 2016 9:35 am
by D2JK
The health monitoring part shouldn't necessarily need an ACS script; take a look at WoundHealth and Wound-state.
Re: Triggering Action When Monster Loses x Health
Posted: Wed Aug 31, 2016 12:15 pm
by ReX
Gutawer wrote:[
Spoiler:
code]
script "Monitor HP then execute code" (int mtid) {
int actorhp = GetActorProperty (mtid, APROP_HEALTH);
if (actorhp <= 100) {
//Do stuff
}
else {restart;}
}
[/code]
Something like this work?
I'll give it a shot & report back. Graf, I'll make sure I put the delay in there.
D2JK wrote:The health monitoring part shouldn't necessarily need an ACS script; take a look at WoundHealth and Wound-state.
At this point I can't alter the DECORATE definition of that enemy, but thanks for the suggestion.
Re: Triggering Action When Monster Loses x Health
Posted: Wed Aug 31, 2016 2:24 pm
by Gutawer
Woops, completely forgot about the delay, I'm on my phone so I had no way of checking the script will work, lol
Re: Triggering Action When Monster Loses x Health
Posted: Thu Sep 01, 2016 8:58 am
by ReX
ReX wrote:I'll give it a shot & report back. Graf, I'll make sure I put the delay in there.
I implemented the following code, which compiled fine but does not work as intended. Specifically, the enemy does not teleport away when its health drops below the specified level. Any suggestions?
{
int actorhp = GetActorProperty (18, APROP_HEALTH);
if (actorhp <= 6500)
{
TeleportOther (18, 20, 1); //Teleports Gargantua out of Test Lab
}
delay (18);
// else
// {
restart;
// }
}
Re: Triggering Action When Monster Loses x Health
Posted: Thu Sep 01, 2016 9:19 am
by Gez
It's not a problem in the current state because the else stuff is commented out, but that's a very bad place for your delay, it should be in the same block as restart, just before restart.
As for why the script doesn't seem to work; I suggest printing some message to check what's happening. E.g.:
{
int actorhp = GetActorProperty (18, APROP_HEALTH);
PrintBold(s:"Gargantua health: ", i:actorhp);
if (actorhp <= 6500)
{
Log("s:Teleporting");
TeleportOther (18, 20, 1); //Teleports Gargantua out of Test Lab
}
else
{
delay (18);
restart;
}
}
This way you'll get to know how much health the script believes the monster has, and you'll be warned in the log if it attempts to teleport. With these information, you can quickly check for two possible map errors:
#1. Something else is tagged 18 accidentally and the script doesn't look for the health of the actual monster, but for some other map thing with the same TID.
#2. The monster does attempt to teleport, but the teleportation fails for some reason (keep in mind that monsters are normally allowed to telefrag!).
Re: Triggering Action When Monster Loses x Health
Posted: Thu Sep 01, 2016 12:44 pm
by ReX
Gez wrote:As for why the script doesn't seem to work; I suggest printing some message to check what's happening. E.g.:
[example code]
This way you'll get to know how much health the script believes the monster has, and you'll be warned in the log if it attempts to teleport. With these information, you can quickly check for two possible map errors:
#1. Something else is tagged 18 accidentally and the script doesn't look for the health of the actual monster, but for some other map thing with the same TID.
#2. The monster does attempt to teleport, but the teleportation fails for some reason (keep in mind that monsters are normally allowed to telefrag!).
I used the code you suggested, with a couple of modifications, as follows:
{
int actorhp = GetActorProperty (18, APROP_HEALTH);
PrintBold(s:"Gargantua health: ", i:actorhp);
if (actorhp <= 6500)
{
Log(s:"Teleporting");
TeleportOther (18, 20, 1); //Teleports Gargantua out of Test Lab
}
else
{
delay (18);
restart;
}
}
At the start of the battle, the health of the monster is correctly displayed. Thereafter, I am unable to see its health. [I realize I can implement a health status bar, but I'm trying to avoid more features.] The "teleporting" log fails to appear, probably because the script is failing to trying to teleport the enemy. The end result is that the enemy does not teleport, and I'm eventually able to destroy it in that room.
As for your other points, I checked and the Gargantua is the only thing with TID 18. The destination mapspot (TID 20) is at a location with plenty of room for the Gargantua to spawn, and there is no possibility of something blocking the spawning. It's also unique. Moreover, if I use the previous script and have the creature teleport out after a specified duration, the teleporting part of the script works just fine. In fact, I went back to the original script, and the teleporting worked just as intended:
{
int actorhp;
do
{
actorhp = GetActorProperty (18, APROP_HEALTH);
PrintBold(s:"Gargantua health: ", i:actorhp);
delay(18);
} while (actorhp > 6500);
Log(s:"Teleporting");
TeleportOther (18, 20, 1); //Teleports Gargantua out of Test Lab
}
It's a different approach, instead of restarting the script we loop on a condition (using the do while structure; you could use a while instead but in this case I felt that the do while was the more elegant approach as it avoids having to query the monster's health in two different places in the code).
Re: Triggering Action When Monster Loses x Health
Posted: Thu Sep 01, 2016 7:23 pm
by ReX
Gez wrote:Then you can do this instead:
It works! Many thanks.
I have cleaned up the code for in-game use, as follows:
{
int actorhp;
do
{
actorhp = GetActorProperty (18, APROP_HEALTH);
// PrintBold(s:"Gargantua health: ", i:actorhp);
delay(18);
}
while (actorhp > 6500);
// Log(s:"Teleporting");
TeleportOther (18, 20, 1); //Teleports Gargantua out of Test Lab
}
However, I'm trying to understand the logic. (Or perhaps I simply don't understand the syntax.) I imagine this is doing the following:
1. Get the enemy's health
2. Check to see if the enemy's health is > 6500
3. While this is true, loop back to the DO statement (i.e., Step 1)
4. When this is not true, teleport the enemy away
Intuitively, I'd have thought the WHILE statement would have been at the start of the logic. At any rate, it works, so I'm very grateful to you.
Re: Triggering Action When Monster Loses x Health
Posted: Fri Sep 02, 2016 1:49 am
by Gutawer
The do, while loop works exactly the same as the while loop, except the code is executed before the check is done. So what Gez' code does is essentially stalls the teleport until health is under 6500.
Re: Triggering Action When Monster Loses x Health
Posted: Fri Sep 02, 2016 4:54 am
by Gez
ReX wrote:Intuitively, I'd have thought the WHILE statement would have been at the start of the logic. At any rate, it works, so I'm very grateful to you.
Yes, that's what I meant with the difference between "while" and "do while". As Gutawer points out, the "do while" loop makes the check at the end instead of the beginning.
With a while loop, I'd have to do something like this:
And so it makes me get the actor hit points in two different places in the code. It's never a good idea to have to duplicate the same instruction when you can avoid it, because it means that if later for some reason you have to change it, then you have to remember to change all the places that have been duplicated.
Anyway, the logic is just that the script will always eventually teleport in its first running instance (provided the monster's health does decrease over time, of course), and it just waiting until the condition is met. I don't know why the restart didn't work (that might deserve reporting as a bug, honestly) but with a while loop you don't need to restart, so problem solved.
Re: Triggering Action When Monster Loses x Health
Posted: Fri Sep 02, 2016 8:19 am
by ReX
Thanks for the explanation. And, yes, the problem is solved