How to call ACS_EXECUTE from a class instance in ZSCRIPT

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
peewee_RotA
Posts: 366
Joined: Fri Feb 07, 2014 6:45 am

How to call ACS_EXECUTE from a class instance in ZSCRIPT

Post by peewee_RotA »

Is there a version of ACS_EXECUTE in zscript that is called by a specific actor so they can be the activator?

A lot of ACS Script functions rely on identifying the activator. The ones that do not imply an activator will require a TID. In my case I need to call teleport on a player from Zscript to a teleport destination determined by another ACS script. It has to be a specific player, not all players in coop, and the player doesn't have a tid. I have a pointer to the player actor in zscript, but the related event I am calling it from is on a monster (and its projectile). In this case, a DoSpecialDamage.

What I'd like to do is just call a specific script number set by the args1 property (this is readable as args[0] in zscript) when the monster causes damage. I let the script number be set like this, instead of hardcoded, so the feature is more flexible. This way I can have 2 or more of the same monster that call different scripts on these events.

I know that I can call ACS_EXECUTE from zscript with other monsters I've tested. I also know that the script number in the argument is working. This is the first case where I am using the action Teleport which requires that the activator be the thing that teleports.

So far I've found that ACS_ScriptCall is a function on an actor that properly sets the activator. The problem is that this uses a named function. That means I can't set the script number like normal, requiring it to be hardcoded to a specific string. I'm also unclear if named scripts in ACS have the same limitations as named functions in ACS. Either way, it would be very helpful if I could call scripts in this way by number.

Here's the ZSCRIPT code I have using the ACS_ScriptCall functionality

Code: Select all

const HARDCODED_SCRIPT_NAME = "NamedScriptName";
class TeleMonster : MyBaseMonster
{
    void DoScriptCall(Actor targetActor)
    {
        targetActor.ACS_ScriptCall(HARDCODED_SCRIPT_NAME);
    }

    override int DoSpecialDamage(Actor target, int damage, name damagetype) //Call script from melee damage
    {
        A_PrintBold("Damaged! 111");
        let playerObj = PlayerPawn(target);
        if (damage > 0 && playerObj && playerObj.health > 0)
        {
            A_PrintBold("Damaged!");
            DoScriptCall(playerObj);
        }

        return damage;
    }
}

class TeleProjectile : MyBaseProjectile
{
    Default
    {
        Radius 13;
        Height 8;
        Speed 15;
        Damage 2;
    }

    void DoScriptCall(Actor targetActor)
    {
        targetActor.ACS_ScriptCall(HARDCODED_SCRIPT_NAME);
    }

    override int DoSpecialDamage(Actor target, int damage, name damagetype) // Call script from projectile damage
    {
        let playerObj = PlayerPawn(target);
        if (damage > 0 && playerObj && playerObj.health > 0)
        {
            DoScriptCall(playerObj);
        }

        return damage;
    }
}
Last edited by peewee_RotA on Fri May 13, 2022 9:44 am, edited 2 times in total.
peewee_RotA
Posts: 366
Joined: Fri Feb 07, 2014 6:45 am

Re: How to call ACS_EXECUTE from a class instance in ZSCRIPT

Post by peewee_RotA »

Here's the ZSCRIPT code I use to call ACS_EXCECUTE from monsters when the activator doesn't matter. In this case it activates when the monster is hit.

Code: Select all

const SCRIPT_NUM_DRAGON = 212;
class ScriptDragon : Dragon
{
    Default
    {
        +NOTELEOTHER
    }
    override int TakeSpecialDamage(Actor inflictor, Actor source, int damage, Name damagetype)
    {
        let playerObj = PlayerPawn(source);
        if (damage > 0 && playerObj && playerObj.health > 0)
        {
            int scriptNum = Args[0];
            if (scriptNum == 0)
                scriptNum = SCRIPT_NUM_DRAGON;
            
            ACS_Execute(scriptNum);
        }

        return damage;
    }
}
Post Reply

Return to “Scripting”