Page 1 of 2

Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 4:08 am
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.)

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 4:15 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 4:26 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 7:15 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 7:41 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 7:42 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 7:57 am
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

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 8:03 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 8:11 am
by Caligari87
Ah whoops. Didn't realize that Used() didn't repeat.

8-)

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 8:46 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 9:03 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 9:31 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 9:35 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 10:04 am
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.

Re: Intentionally making a Pickup Delay

Posted: Fri Mar 16, 2018 10:17 am
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 :)