[ZSCRIPT]Ideas for containers

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
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

[ZSCRIPT]Ideas for containers

Post by Sir Robin »

I want to create containers - you know, crates, boxes, barrels, chests, whatever - that when used or destroyed they spew out their contents. That part of the coding I can handle.
What I want to know is how to assign contents to a container. I could hard-code the contents, then have a subclass of the container for each item it might contain. That seems kinda excessive.
I'm thinking one way could be to put the content items outside the map, give them all a specific TID, and the container has that TID as an arg and when it's opened/destroyed it teleports all items with that TID to itself and spews them out.
Another way could be to set the string arg with a CSV of classes of items to be spawned on the container open/destruction event.
So obviously my goal here is to be able to set the container's content from a map editor.
Any ideas on the best way to do that?
I guess this might be similar to how you would give a baddie a key or some other quest item to drop when they die?
Jarewill
 
 
Posts: 1822
Joined: Sun Jul 21, 2019 8:54 am

Re: [ZSCRIPT]Ideas for containers

Post by Jarewill »

Your first idea of using TIDs to tell what a container should drop can be done using an ActorIterator.
For example:

Code: Select all

Class Container : Actor replaces TechLamp{
	bool empty;
	Default{Height 64;}
	States{Spawn: COLU A -1; Stop;}
	Override bool Used(Actor user){
		If(empty||args[0]==0){Return 0;} //If the container is empty or first arg is invalid, return
		ActorIterator i = level.CreateActorIterator(args[0]); //Create an actor iterator with a specified TID
		Actor thing;
		While(thing = i.Next()){
			If(thing){ //If a thing with the TID exists
				thing.SetOrigin(pos,0); //Move it to the container
				thing.vel=(frandom(-4,4),frandom(-4,4),frandom(4,8)); //And set the velocity
			}
		}
		empty=1; //Mark the container as empty
		Return 1;
	}
}
User avatar
AshHouswares
Posts: 145
Joined: Fri Jun 03, 2022 11:31 am
Graphics Processor: Not Listed

Re: [ZSCRIPT]Ideas for containers

Post by AshHouswares »

Personally, I code containers the same way I code monsters. They drop an item of a designated type or value in their decorate / zscript code on destruction.
User avatar
AFADoomer
Posts: 1337
Joined: Tue Jul 15, 2003 4:18 pm

Re: [ZSCRIPT]Ideas for containers

Post by AFADoomer »

If you are using UDMF maps you can use user variables to do this.

Declare a "user_dropitem" (or whatever you want to name it, as long as it starts with 'user_') variable in your Container actor, then use A_DropItem to spawn that class in the Death state.

You can set the value in the editor to the class name that you want to spawn. In Ultimate Doom Builder it's in the thing's 'Custom' tab'.

Code: Select all

Actor Container : Actor
{
	String user_dropitem;

	States
	{
		Death:
			/* other frames */
			 DEAD A 1 A_DropItem(user_dropitem);
			/* more frames */
			Stop;
	}
}
Alternatively, you could hard-code options that you select with one of the actor arguments, then use ZScript to manually spawn them when the actor is used/dies. I did this in Blade of Agony with the supply chests - it's an overly complicated example, but has some comments and might help.
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: [ZSCRIPT]Ideas for containers

Post by Sir Robin »

Wow, thanks everyone for the answers and example code.
Jarewill wrote: Sat Sep 09, 2023 12:46 pm Your first idea of using TIDs to tell what a container should drop can be done using an ActorIterator.
Perfect! I'm playing around with this example. I added this line:

Code: Select all

				if (thing is "inventory") inventory(thing).droptime = 70 + random(0,30);
So that I can see what was in the container before I gobble it up

AshHouswares wrote: Sat Sep 09, 2023 4:45 pm Personally, I code containers the same way I code monsters. They drop an item of a designated type or value in their decorate / zscript code on destruction.
This is what I meant when I said hard-coding, it's what I'm trying to avoid. I'd have to create an actor for each combination of container and contained object.
So for example, Box_HealthBonus, Box_ArmorBonus, Box_Stimpack, Box_BlueKey, Box_RedKey, etc, for each item
Then I have to create Crate_*, Barrel_*, Chest_*, Sack_*, etc for each container type.
Then if I want to have containers with 2 or 3 items, I have to create all those combinations. It's a whole lot of code, a whole lot of dehacked numbers, A whole lot to scroll through when looking to place an item on the map.

AFADoomer wrote: Sat Sep 09, 2023 6:08 pm If you are using UDMF maps you can use user variables to do this.

Alternatively, you could hard-code options that you select with one of the actor arguments, then use ZScript to manually spawn them when the actor is used/dies. I did this in Blade of Agony with the supply chests - it's an overly complicated example, but has some comments and might help.
Oh, yes, I knew there was a way to pass a string. I forgot about user variables, great tip!
I'd make it User_DropItems so I could give it a CSV list of items to pop out (just take in the string and break it up with split())
And thanks fot the link to the BoA container. I like how you use arg[0] to a reference to a predefined loot list or you can give it a custom item.
It's also a good example of how to handle keys, counted items, and attaching scripts. Excellent, thank you.


A question about something I'm noticing: So I put an override Used function on an actor and now it's able to be used. But if the actor is near a wall when it's used the player still makes a grunt noise like he's trying to open a door. How to fix that?

And another question, when scrolling inventory and I press the query key I get something like "CarriedStimpack (x3)" printed to the console. Can I change that output or is it hard-coded?
Jarewill
 
 
Posts: 1822
Joined: Sun Jul 21, 2019 8:54 am

Re: [ZSCRIPT]Ideas for containers

Post by Jarewill »

Sir Robin wrote: Mon Sep 11, 2023 9:03 pm And another question, when scrolling inventory and I press the query key I get something like "CarriedStimpack (x3)" printed to the console. Can I change that output or is it hard-coded?
While I don't know how to fix the first problem, the second problem can be fixed by giving the item a Tag.
Query displays the item's tag, so if you give it Tag "Stimpack"; it will then display as "Stimpack (x3)".
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: [ZSCRIPT]Ideas for containers

Post by Sir Robin »

Good tip, thanks.

But I'm looking for a way to override the text and put my own in there. So for example it could say "Stimpack (x3) - Use this to recover a little health" or "flashlight (x1) with 80% battery remaining"
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: [ZSCRIPT]Ideas for containers

Post by Sir Robin »

Sir Robin wrote: Mon Sep 11, 2023 9:03 pm A question about something I'm noticing: So I put an override Used function on an actor and now it's able to be used. But if the actor is near a wall when it's used the player still makes a grunt noise like he's trying to open a door. How to fix that?
Solution: The Used() method needs to return true when the actor has been successfully used, this will stop the "use tracer" from continuing
Sir Robin wrote: Mon Sep 11, 2023 9:03 pm And another question, when scrolling inventory and I press the query key I get something like "CarriedStimpack (x3)" printed to the console. Can I change that output or is it hard-coded?
Sir Robin wrote: Sat Sep 16, 2023 6:20 am I'm looking for a way to override the text and put my own in there. So for example it could say "Stimpack (x3) - Use this to recover a little health" or "flashlight (x1) with 80% battery remaining"
The "Query Item" feature binds to console command "invquery". There doesn't seem to be anywhere to override this and it can't be aliased. The only way seem to be to create a new query feature and bind it to another key.
User avatar
AFADoomer
Posts: 1337
Joined: Tue Jul 15, 2003 4:18 pm

Re: [ZSCRIPT]Ideas for containers

Post by AFADoomer »

Unfortunately, the 'invquery' console command is hard-coded to print the item's tag/name and amount... I don't think this could be easily changed in any universal way.
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: [ZSCRIPT]Ideas for containers

Post by Sir Robin »

I got it going, thanks to all for the help!

I made it so that you give the container a TID in args and it takes all actors with that TID as its contents. Then if the player USE it ingame, it displays it's contents above. If player backs away, the contents go back into the container, but if player USE again then contents are flung into the world to be picked up.
Spoiler:
User avatar
AFADoomer
Posts: 1337
Joined: Tue Jul 15, 2003 4:18 pm

Re: [ZSCRIPT]Ideas for containers

Post by AFADoomer »

Very nice effect!
User avatar
Dan_The_Noob
Posts: 878
Joined: Tue May 07, 2019 12:24 pm
Graphics Processor: nVidia with Vulkan support

Re: [ZSCRIPT]Ideas for containers

Post by Dan_The_Noob »

a container that is effectively an unmoving monster with the items spawned as a projectile is probably the quickest easiest way.
then just have a loot table/spawner list for items.

Return to “Scripting”