Smarter Healers & Supports
Posted: Thu Jul 09, 2015 4:17 pm
So, you want to make a monster that can heal or buff any allies within a radius? Not a problem; there are a number of ways to do this.
...But what if you want it to check to see if there are allies for it to heal or buff, before entering those states, and to avoid going into them if there's nothing around for it to heal or buff? Now things get a little harder.
Here is a method for a monster to check around it for potential "targets" to heal or buff, without using ACS, and without exhaustive and extensive editing of all your other monsters. This tutorial expects that you have some expertise with DECORATE; I'd rate it somewhere between beginner and intermediate difficulty.
This method relies on the fact that any action functions exectued by a CustomInventory actor in its Pickup state are treated as though the actor picking them up is the one executing them, rather than the pickup. Not only does this mean we don't have to do tons of edits to all the monsters, it comes in handy with some tweaks you may want to do when using the method in your mod.
So, let's start with the monster we want to have the healing ability:The first thing the monster does is give an item called HealingWizardAlliesCheck to any living monsters within a 512 mapunit radius. Don't worry about the line checking for the 'HealingWizardAlliesTrue' item; we'll come back to that. Now, let's look at the code for the 'HealingWizardAlliesCheck' item:Any monster that recieves the above item will immediately give another item, called 'HealingWizardAlliesCheckBack' to, again, any living monsters within a 512 mapunit radius. Now, let's look at the code for this second CustomInventory actor:Things are a little more complicated now. You'll notice that the first thing this actor does is use the [wiki]CheckClass[/wiki] function in an expression used by [wiki]A_JumpIf[/wiki]. Remember above when I said that action functions executed in a CustomInventory actor's Pickup state are actually executed by that actor picking them up? It may sound counter-intuitive, but the monster picking up this item will now check its own class, and if the monster happens to be our HealingWizard (as a result of us using the AAPTR_DEFAULT actor pointer which is 'check self'), it will then jump to a new state where it gives yet another item, whose code need not be so complicated, at least for our example:The only purpose of the above item is so that the HealingWizard 'knows' there was at least one monster in the vicinity at the time in question.
Now, let's check back with our HealingWizard.You'll notice that there's quite a few tics between when it checks for allies, and when it actually executes the healing action. You'll probably want to do another check for allies in the area just to be sure, but for simplicity's sake, I haven't included that here.
And... that's that! There's a lot of flexibility to this method, so put your own spin on it! For example, you could have the monster check for different amounts of the item it gets (HealingWizardAlliesTrue in our example) to determine the strength of its healing ability; if there aren't many monsters in the area, the healer could jump to a state where the healing effect is stronger. Or it could check for multiples of that item to set the priority with which it uses the heal ability. Or, how about checking to see if there are any allies that need healing badly, and prioritizing the healing ability then? You could do something like this:Or what if you need the healer to ignore certain monsters, like if they're allied with the player? Just do something like this:
...But what if you want it to check to see if there are allies for it to heal or buff, before entering those states, and to avoid going into them if there's nothing around for it to heal or buff? Now things get a little harder.
Here is a method for a monster to check around it for potential "targets" to heal or buff, without using ACS, and without exhaustive and extensive editing of all your other monsters. This tutorial expects that you have some expertise with DECORATE; I'd rate it somewhere between beginner and intermediate difficulty.
This method relies on the fact that any action functions exectued by a CustomInventory actor in its Pickup state are treated as though the actor picking them up is the one executing them, rather than the pickup. Not only does this mean we don't have to do tons of edits to all the monsters, it comes in handy with some tweaks you may want to do when using the method in your mod.
So, let's start with the monster we want to have the healing ability:
Code: Select all
ACTOR HealingWizard : Wizard
{
States
{
RadiusHeal:
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheck",512,RGF_MONSTERS,5)
WZRD A 4 A_Chase
TNT1 A 0 A_JumpIfInventory("HealingWizardAlliesTrue",1,"AlliesFound")
Goto See
}
}
Code: Select all
ACTOR HealingWizardAlliesCheck : CustomInventory
{
+ALWAYSPICKUP
States
{
Pickup:
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheckBack",512,RGF_MONSTERS,5)
Stop
}
}
Code: Select all
ACTOR HealingWizardAlliesCheckBack : CustomInventory
{
+ALWAYSPICKUP
States
{
Pickup:
TNT1 A 0 A_JumpIf(CheckClass("HealingWizard",AAPTR_DEFAULT),"PickupWizard")
Stop
PickupHealerGolem:
TNT1 A 0 A_GiveInventory("HDRLAHealerGolemAlliesTrue")
Stop
}
}
Code: Select all
ACTOR HealingWizardAlliesTrue : Inventory{+ALWAYSPICKUP}
Now, let's check back with our HealingWizard.
Code: Select all
ACTOR HealingWizard : Wizard
{
States
{
RadiusHeal:
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheck",512,RGF_MONSTERS,5)
WZRD A 4 A_Chase
TNT1 A 0 A_JumpIfInventory("HealingWizardAlliesTrue",1,"AlliesFound")
Goto See
AlliesFound:
WZRD CCCCCC 4 A_FaceTarget
WZRD D 12 A_RadiusGive("HealingWizardHealth",512,RGF_MONSTERS,5)
TNT1 A 0 A_TakeInventory("HealingWizardAlliesCheck")
TNT1 A 0 A_TakeInventory("HealingWizardAlliesCheckBack")
TNT1 A 0 A_TakeInventory("HealingWizardAlliesTrue")
Goto See
}
}
ACTOR HealingWizardHealth : CustomInventory
{
+ALWAYSPICKUP
States
{
Pickup:
TNT1 A 0 A_SetHealth(health+random(1,2))
Stop
}
}
And... that's that! There's a lot of flexibility to this method, so put your own spin on it! For example, you could have the monster check for different amounts of the item it gets (HealingWizardAlliesTrue in our example) to determine the strength of its healing ability; if there aren't many monsters in the area, the healer could jump to a state where the healing effect is stronger. Or it could check for multiples of that item to set the priority with which it uses the heal ability. Or, how about checking to see if there are any allies that need healing badly, and prioritizing the healing ability then? You could do something like this:
Code: Select all
ACTOR HealingWizardAlliesCheck : CustomInventory
{
+ALWAYSPICKUP
States
{
Pickup:
TNT1 A 0 A_JumpIfHealthLower(40,"Critical")
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheckBack",512,RGF_MONSTERS,5)
Stop
Critical:
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheckBackCritical",512,RGF_MONSTERS,5)
Stop
}
}
Code: Select all
ACTOR HealingWizardAlliesCheck : CustomInventory
{
+ALWAYSPICKUP
States
{
Pickup:
TNT1 A 0 A_JumpIf(CheckClass("DoomPlayerRoboBuddy",AAPTR_DEFAULT),"PickupFail")
TNT1 A 0 A_RadiusGive("HealingWizardAlliesCheckBack",512,RGF_MONSTERS,5)
Stop
PickupFail:
Stop
}
}