Intentionally making a Pickup Delay

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!)
User avatar
insightguy
Posts: 1730
Joined: Tue Mar 22, 2011 11:54 pm

Intentionally making a Pickup Delay

Post by insightguy »

from the Zdoom wiki regarding custom inventory wrote:Note that due to this special behavior, the Use and Pickup states will ignore all frame durations and shouldn't be looped, attempts to do to so may result in the sequence being interrupted by the engine; every frame will execute within the same tic.
Well shit, I needed a way to be able to make the player stand in one spot for about 100 tics while holding the use key to be able to "install" the item in question. 1/2 of the problem is fixed, thanks to mikki for that, but the "delay" is what I'm having trouble with.

Is there any solution to this out there that's built in engine rather than me having to make the hackiest hack on a hack to make this work (what I was planning to do is a massive headache and wanted to see if there were easier outs for this.)
User avatar
FFFFRRRR
Posts: 99
Joined: Sat Nov 04, 2017 3:33 am

Re: Intentionally making a Pickup Delay

Post by FFFFRRRR »

You could use ACS with GetPlayerInput and Thing_Stop. I wouldn't consider that "hacky". Keep checking whether you hold "use" or not, and if so, use Thing_Stop to stop the player.
User avatar
insightguy
Posts: 1730
Joined: Tue Mar 22, 2011 11:54 pm

Re: Intentionally making a Pickup Delay

Post by insightguy »

It's not locking the player that i'm worried about.

Here is what I want to happen
  • You see the item
  • You go over to the item
  • You hold the use key
  • A "progress bar" shows up and shows how long I have to hold the use key
  • when the bar is full, the item is "picked up"
I know how to make the progress bar with SBARINFO but I need the logic behind the pickup.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Intentionally making a Pickup Delay

Post by gwHero »

Do you mean to have this done for a specific pickup item? In that case I think this would be doable in ZScript. You can create a pickup class that inherits from Inventory and override the touch in which you do not call super.touch.

Add a tick and count in this tick until 100 is reached; after that call super.touch.
User avatar
insightguy
Posts: 1730
Joined: Tue Mar 22, 2011 11:54 pm

Re: Intentionally making a Pickup Delay

Post by insightguy »

gwHero wrote:Add a tick and count in this tick until 100 is reached; after that call super.touch.
from the Zdoom wiki regarding custom inventory wrote:Note that due to this special behavior, the Use and Pickup states will ignore all frame durations and shouldn't be looped, attempts to do to so may result in the sequence being interrupted by the engine; every frame will execute within the same tic.
This is the problem that makes the 100 tic solution non workable. I already tried the 100 tic delay in the thing and it ignored it. Unless you have a specific other way to do it, it won't work.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Intentionally making a Pickup Delay

Post by gwHero »

Quickly produced some code; was not able to test it but for the delayed pickup this could be something to start with.

Code: Select all

class MD_Pickup : Inventory 
{	

	Default
	{
		+special	
	}

	int nn;
	bool touched;
	Actor toucher;
	
	override void PostBeginPlay()
	{
		nn=0; 
		touched = false;
	}
	override void Tick()
	{
		if (touched) nn++;
		if (nn > 100)  
			Super.touch(_toucher); 
	}
	            
	override void touch(Actor toucher) 
	{
		_toucher = toucher;
		touched = true;
	}

}

Essential is the +special flag.
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: Intentionally making a Pickup Delay

Post by Caligari87 »

I think something like this may be more in line with the intent

Code: Select all

int holdCounter;

override void touch(Actor toucher){ }

override bool used(Actor user)
{
    holdCounter++;
    if(holdCounter >= 100)
    {
        Super.touch(user);
    }
    return true;
}
Of course you'll want to add some extra code to reset the hold counter if the item isn't being actively used
User avatar
insightguy
Posts: 1730
Joined: Tue Mar 22, 2011 11:54 pm

Re: Intentionally making a Pickup Delay

Post by insightguy »

Caligari87 wrote:I think something like this may be more in line with the intent

Code: Select all

int holdCounter;

override void touch(Actor toucher){ }

override bool used(Actor user)
{
    holdCounter++;
    if(holdCounter >= 100)
    {
        Super.touch(user);
    }
    return true;
}
Of course you'll want to add some extra code to reset the hold counter if the item isn't being actively used
Although close to the intention, for future reference, this requires you to mash the button 100 times before the item picks up. Close, but I need to somehow translate this to a button held down rather than mashed.
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: Intentionally making a Pickup Delay

Post by Caligari87 »

Ah whoops. Didn't realize that Used() didn't repeat.

8-)
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Intentionally making a Pickup Delay

Post by gwHero »

That's why I started for the touch override as a start. But that's purely for the delay. For the holding down problem of the use key : this could be checked independently: in player class, decorate/zscript, acs, or zscript with the InputProcess event) setting some global, and checking this global in the touch override.
User avatar
insightguy
Posts: 1730
Joined: Tue Mar 22, 2011 11:54 pm

Re: Intentionally making a Pickup Delay

Post by insightguy »

OK, after going through Caligari87's and gwHero's code, I managed to make something similar with the thing I wanted to make

Code: Select all

class WeaponPickup : CustomInventory
{
	int holdCounter;
	
	override void touch(Actor toucher) 
		{
		}
		
    override bool used(Actor user)
		{
			while (CheckIfCloser(user, 250.0, false))
			{
				holdCounter++;
				if(holdCounter >= 100)
				{
					Super.touch(user);
					return true;
				}
			}
			return true;
		}
}
The problem now is, how do I add a delay to this. The idea being that every time the "while" loop loops, a delay would be added so to make the loop actually be useful.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Intentionally making a Pickup Delay

Post by Arctangent »

There is no such thing as Delay for ZScript.

Instead, the most straightforward method for that kind of thing involves using Tick as your loop; it does, after all, get called every single frame without fail. used makes a good way to start the process, but you'll have to keep track of user and cast it to PlayerPawn down the line so you can access PlayerPawn's player variable, which stores the actual player entity "riding" the PlayerPawn, so you can access the player's cmd variable and finish off the chain by accessing the cmd variable's buttons variable.

Or, to grab a snippet from PlayerPawn's ZScript code:

Code: Select all

...
		let player = self.player;
		let weapon = player.ReadyWeapon;

		if (weapon == NULL)
			return;

		// Check for fire. Some weapons do not auto fire.
		if ((player.WeaponState & WF_WEAPONREADY) && (player.cmd.buttons & BT_ATTACK))
...
Take note of the use of [wiki]GetPlayerInput[/wiki]'s BT_ATTACK constant; the player's cmd variable is what stores their inputs and is also what GetPlayerInput grabs its data from, with its buttons variable being accessed by INPUT_BUTTONS. So &ing cmd.buttons with BT_USE will let you check if the player is holding the use button down after used has already done its job.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Intentionally making a Pickup Delay

Post by gwHero »

You should not ad a while loop, because counting to 100 in this loop is done in a fraction of a millisecond.

That's why I added a Tick; a tick is called by the engine every 1/28 second; there you can do the counting. The counting is done in a private variable. A delay like in ACS is not available.
User avatar
Arctangent
Posts: 1235
Joined: Thu Nov 06, 2014 1:53 pm
Contact:

Re: Intentionally making a Pickup Delay

Post by Arctangent »

gwHero wrote:That's why I added a Tick; a tick is called by the engine every 1/28 second
1/35; the idTech 1 engine's gamesim run at a maximum of 35 FPS, so it ticks every 1/35th of a second, before factoring in situations intense situation where a single tick takes longer than 1/35 seconds to process as the engine only prevents itself from updating the gamesim more often than 35 times a second, rather than also forcing an update if a tick would throw off its metaphorical schedule so to speak.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Intentionally making a Pickup Delay

Post by gwHero »

Arctangent wrote:
gwHero wrote:That's why I added a Tick; a tick is called by the engine every 1/28 second
Ah yes you're right, I was mistaking, it's about 28 ms a tic takes :)
Post Reply

Return to “Scripting”