[ACS] Accurate input scripts?

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
User avatar
TDRR
Posts: 830
Joined: Sun Mar 11, 2018 4:15 pm
Location: Venezuela

[ACS] Accurate input scripts?

Post by TDRR »

So like most of you know ACS has a way to check which key is pressed, but i don't completely know how to use it.

I'm currently using this method:

Code: Select all

Script "P1InputShield" (void)
{
 int activateshield;
 while (TRUE)
 {
   activateshield = GetPlayerInput(-1, INPUT_BUTTONS);
if (activateshield & BT_RELOAD)
{
   GiveActorInventory(1, "Input_Shield", 1);
   delay(4); //3 frame buffer
   TakeActorInventory(1, "Input_Shield", 10);
}
   delay(1);
 }
}
Unfortunately as you might expect this is rather clunky and doesn't work well for holding an input. The wiki page mentions that by comparing INPUT_BUTTONS with INPUT_OLDBUTTONS i would be able to know exactly when a key is pressed or released.

Ideally i want to have the item be given when the button is pressed and taken when the button gets released. (also yes i know i have to change the way that i'm giving the item because it won't work online so don't question that)
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
Contact:

Re: [ACS] Accurate input scripts?

Post by Matt »

This ought to work:

Code: Select all

Script "P1InputShield" (void)
{
 int activateshield;
 while (TRUE)
 {
   activateshield = GetPlayerInput(-1, MODINPUT_BUTTONS);
if (activateshield & BT_RELOAD)
{
   GiveActorInventory(1, "Input_Shield", 1);
}
else if (GetPlayerInput(-1, MODINPUT_OLDBUTTONS) & BT_RELOAD)
{
   TakeActorInventory(1, "Input_Shield", 10);
}
   delay(1);
 }
} 
Changing to MODINPUT instead of INPUT because:
The MODINPUT_* series check the values after they have been processed by the game engine. These may be different if, for example, the player is fully or partially frozen (Movement inputs will be nulled) or is using a weapon such as the chainsaw which alters the player's input to include forward movement.
User avatar
TDRR
Posts: 830
Joined: Sun Mar 11, 2018 4:15 pm
Location: Venezuela

Re: [ACS] Accurate input scripts?

Post by TDRR »

Matt wrote:Changing to MODINPUT instead of INPUT because:
The MODINPUT_* series check the values after they have been processed by the game engine. These may be different if, for example, the player is fully or partially frozen (Movement inputs will be nulled) or is using a weapon such as the chainsaw which alters the player's input to include forward movement.
That's the exact opposite of what i want. I'm using it for two things: Controlling a character for a Smash Bros. clone while the player is frozen just so it can't do anything to break it. And the second is for vehicles, which obviously needs to have the player frozen because else the car could strafe which is pretty ridiculous.

Anyways, thanks! But i have another question, if i added a loop that say, increased a value every tic the key is pressed, how would i make it stop when it's not pressed anymore? To my understanding loops start from the beginning of the loop, not the beginning of the script so it would get permanently stuck.
gramps
Posts: 300
Joined: Thu Oct 18, 2018 2:16 pm

Re: [ACS] Accurate input scripts?

Post by gramps »

I think the delay(1) acts a bit like "yield" would act in a coroutine, allowing other scripts a chance to execute, doesn't it?
User avatar
TDRR
Posts: 830
Joined: Sun Mar 11, 2018 4:15 pm
Location: Venezuela

Re: [ACS] Accurate input scripts?

Post by TDRR »

gramps wrote:I think the delay(1) acts a bit like "yield" would act in a coroutine, allowing other scripts a chance to execute, doesn't it?
Nope, at least not in the way i want to do. You see, normally these scripts are ran either with ENTER or executed with ACS_NamedExecuteAlways which allows them to always run alongside other scripts.

I thought about just using "restart" after adding 1 to a counter so it goes back to the beginning of the script, checks for the keybind and adds 1 again to the counter until the key is released.
User avatar
Matt
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
Contact:

Re: [ACS] Accurate input scripts?

Post by Matt »

It would help to indent properly so you can see the structure of where a block ends or begins.

My own preference is to avoid while structures entirely, have a single script go through all the necessary checks, and have only a single delay call at the very end before the script restarts.

Code: Select all

int activateshield[32];
Script "P1InputShield" (void)
{
    if (GetPlayerInput(-1, INPUT_BUTTONS) & BT_RELOAD)
    {
        GiveActorInventory(1, "Input_Shield", 1);
        activateshield[PlayerNumber()]++;
    }
    else
    {
        activateshield[PlayerNumber()]-=10;
        if (activateshield[PlayerNumber()]<0) activateshield[PlayerNumber()]=0;

        if (GetPlayerInput(-1, INPUT_OLDBUTTONS) & BT_RELOAD)
        {
            TakeActorInventory(1, "Input_Shield", 10);
        }
    }
    delay(1);
    restart;
} 
User avatar
TDRR
Posts: 830
Joined: Sun Mar 11, 2018 4:15 pm
Location: Venezuela

Re: [ACS] Accurate input scripts?

Post by TDRR »

Matt wrote:It would help to indent properly so you can see the structure of where a block ends or begins.

My own preference is to avoid while structures entirely, have a single script go through all the necessary checks, and have only a single delay call at the very end before the script restarts.

Code: Select all

int activateshield[32];
Script "P1InputShield" (void)
{
    if (GetPlayerInput(-1, INPUT_BUTTONS) & BT_RELOAD)
    {
        GiveActorInventory(1, "Input_Shield", 1);
        activateshield[PlayerNumber()]++;
    }
    else
    {
        activateshield[PlayerNumber()]-=10;
        if (activateshield[PlayerNumber()]<0) activateshield[PlayerNumber()]=0;

        if (GetPlayerInput(-1, INPUT_OLDBUTTONS) & BT_RELOAD)
        {
            TakeActorInventory(1, "Input_Shield", 10);
        }
    }
    delay(1);
    restart;
}
No way, thanks Matt! This pretty much solves all my questions in one go, will be useful for lots of things!
Post Reply

Return to “Scripting”