Jump to content
The Dark Mod Forums

Recommended Posts

Posted (edited)

Hey Guys,

 

I apologize ahead of time, I am a novice at scripting.

 

I am trying to create a thief-style chest; one that when opened, the items are automatically dumped into the player's inventory.

I have pretty hacky prototype. Once the player frobs open the lid (atdm:mover_binarymover_base), it targets a func_callscriptfunction. I have a hacky Stim/response that removes the lid's targets when frobbed. This prevents the player from getting items every time they open the chest. The problem is when I try to lock the lid or attach a froblock, it breaks and nothing happens. The lid doesn't seem to like having other entities bound to it or target it.

 

Any suggestions or help would be awesome?

Thanks a bunch guys.

 

 

EDIT (Solved). Thanks for everyone's help with this.

Here is the .script and .def for anyone who is interested in using this in their FM.

 

Here is the script by SteveL:

#ifndef AUTOLOOT_CHEST
#define AUTOLOOT_CHEST

//Script for autoloot chest by SteveL
// Spawnargs: "random_spawn", "random_chance"
//"random_spawn" = name of inventory item. (example "atdm:ammo_gasarrow")
//"random_chance" = Probability of spawn. (0 to 1)

void autoloot_chest(entity chest, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
    // Fire only if map has been open 3 seconds (avoiding map initialisation) and 
    // only the first time the door/lid is fully opened.
    if ( sys.getTime() > 3 && bOpen && !chest.getBoolKey("already_opened") )
    {
        chest.setKey("already_opened", "1");
        // Search through "random_spawn" spawnargs, and find a matching "random_chance" spawnarg
        string key = chest.getNextKey("random_spawn", "");
        while ( key != "" )
        { 
            float chance = chest.getFloatKey(sys.strReplace(key, "_spawn", "_chance"));
            float r = sys.random(1.0);
            if ( chance > r )
            {
                entity newItem1 = sys.spawn(chest.getKey(key));
                newItem1.addItemToInv($player1);
                sys.wait(1.0);
            }
            key = chest.getNextKey("random_spawn", key);
        }
    }
}	
#endif

And the def file:

Be sure to replace the YOUR FM with your fm's directory.

//++++++++++++++++++++++++Frob Chest++++++++++++++++++++++++++++++
//Auto Loot Chest
//Uses script "autoloot_chest" by SteveL
//Spawnargs: "random_spawn", "random_chance"
//"random_spawn" = Name of inventory item. (example "atdm:ammo_gasarrow")
//"random_chance" = Probability of spawn. (0 to 1)

entityDef frob_chest_lid
{
	//editor stuff
		"inherit"		"atdm:mover_binarymover_base"
		"editor_displayFolder"	"YOUR FM/autoloot_chest/"
		"editor_usage"	        "Auto loot chest. Random_spawn = name of inventory item. (example: atdm:ammo_gasarrow). Random_chance = Probability of spawn. (0 to 1)." 
		"editor_color"		"1.00 0.82 0.29"
		"spawnclass"            "CFrobDoor"
		
	//model
		"model"			"models/darkmod/containers/openable/footlocker_wood_lid.ase"	
		
	//sound
		"snd_open"		"chest_wood_open"
		"snd_close"		"chest_wood_close"
		
	//movement
		"rotate"		"0 0 -80"
		"move_time"             "0.4"
	
	//interaction
		"frobable"              "1"
		"locked"                "0"
		"state_change_callback" "autoloot_chest"
		
}

//Chest Body
entityDef frob_chest
{
	//editor stuff
		"inherit"		"atdm:entity_base"
		"spawnclass"            "idStaticEntity"
		"editor_displayFolder"	"YOUR FM/autoloot_chest/"
		"editor_usage"          "Auto loot chest."
		"editor_color"		"1.00 0.82 0.29"
		
	//model
		"model"                 "models/darkmod/containers/openable/footlocker_wood.ase"
	
	//other stuff
		"solid"                  "1"
}
Edited by kingsal
  • Like 1
Posted

Hello. Your script looks okay, not sure if there's any better arguments to use than just addItemToInv. If you want the items to be added just once, it's as simple as an if loop that closes after 1 frob.

float chestFrobbed = 0;

void function() {

	if (chestFrobbed == 0) {
        entity newItem1 = sys.spawn("atdm:weapon_shortsword");
        newItem1.addItemToInv($player1);
        chestFrobbed = 1;
	sys.waitFrame();
	}
}

It's probably tidier to do it with a boolean, but boolean and entitity data types can't be immediately declared it seems, don't know why.

  • Like 1

My FMs: The King of Diamonds (2016) | Visit my Mapbook thread sometimes! | Read my tutorial on Image-Based Lighting Workflows for TDM!

 

 

Posted

There are no booleans in the scripting language, so you have to use float. Wouldn't it make more sense to use a script object instead a global script to do this? Otherwise you will have to write a separate script function for every chest.

FM's: Builder Roads, Old Habits, Old Habits Rebuild

Mapping and Scripting: Apples and Peaches

Sculptris Models and Tutorials: Obsttortes Models

My wiki articles: Obstipedia

Texture Blending in DR: DR ASE Blend Exporter

Posted

Spooks- I tried your script out and it works really well and is much cleaner. It also works with being locked and having a froblock attached to it. Thanks so much! :D

 

Obs- That would definitely be a more solid solution and friendlier to the mission designer. It would be nice to be able to select the items as spawnargs inside darkradiant.

There is one small advantage to each chest having its own script, you can make edits to its contents without digging around for it in the editor. If for instance, you wanted to quickly balance the items across the entire map.

 

Thanks guys for the help!

  • Like 1
Posted

There is one small advantage to each chest having its own script, you can make edits to its contents without digging around for it in the editor. If for instance, you wanted to quickly balance the items across the entire map.

 

You could probably use the menu function that selects all entities that have the same model as the one you have selected. That'd let you skip between chests in the map easily.

 

The script object version would also let you balance the loot distribution by setting a probability against each item so you could have the same spawnargs on every chest and still keep the loot balanced.

 

e.g.

"random_spawn1" "atdm:weapon_shortsword"

"random_chance1" "20"

 

I don't mind providing the starter script object if you want to try it out. The documentation is a bit brief, both ours and ID's.

  • Like 1
Posted

Steve- If its something you're interested in, that would be awesome. I'd definitely like to try it out! It sounds like a much better long term solution.

 

I do like the TDM style chests with the items being optional to pick up, it feels immersive. However, there are some nice advantages to an item dump chest, you don't have to worry about bsp recompiling if you move it and you can easily balance item distribution.

  • Like 1
Posted

There are no booleans in the scripting language, so you have to use float. Wouldn't it make more sense to use a script object instead a global script to do this? Otherwise you will have to write a separate script function for every chest.

 

Somebody needs to update the Scripting Basics page on the wiki then, the Boolean data type is stated to exist there. At the very least it should be noted booleans and entities can't have their values set outside of a function (i.e. at declaration time when they're global variables).

  • Like 1

My FMs: The King of Diamonds (2016) | Visit my Mapbook thread sometimes! | Read my tutorial on Image-Based Lighting Workflows for TDM!

 

 

Posted

its used to see if a door is open or closed as in (boolean bOpen) it checks that bOpen is true or false if you remove it then doors controlled by scripts will fail to function, and you'll break many maps that use that function.

eg

void sewerhatch1_state(entity mover_lever, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
if (bOpen)
{
$manhole_cover_1a.Open();
}
else
{
$manhole_cover_1a.Close();
}
}

  • Like 1
Posted (edited)

void sewerhatch1_state(entity mover_lever, boolean bOpen, boolean bLocked, boolean bInterrupted)

Ah, that's a "state_change_callback" script.

 

@kingsal You could use one of those more simply than a script object to get the job done with the chest. state_change_callback is a way to call a script when a door is moved or a button is pressed. Unlike most ways to call a script, the script gets told which entity fired it.

 

Chest lids are doors, so you could put your spawnargs on the lid along with "state_change_callback" "autoloot_chest"

 

Then in your map script:

void autoloot_chest(entity chest, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
    // Fire only if map has been open 3 seconds (avoiding map initialisation) and 
    // only the first time the door/lid is fully opened.
    if ( sys.getTime() > 3 && bOpen && !chest.getBoolKey("already_opened") )
    {
        chest.setKey("already_opened", "1");
        // Search through "random_spawn" spawnargs, and find a matching "random_chance" spawnarg
        string key = chest.getNextKey("random_spawn", "");
        while ( key != "" )
        { 
            float chance = chest.getFloatKey(sys.strReplace(key, "_spawn", "_chance"));
            float r = sys.random(1.0);
            if ( chance > r )
            {
                entity newItem1 = sys.spawn(chest.getKey(key));
                newItem1.addItemToInv($player1);
                sys.wait(1.0);
            }
            key = chest.getNextKey("random_spawn", key);
        }
    }
}
The script disables a chest by adding a spawnarg to it in real time. You can use any random_spawnXYZ spawnarg naming scheme as long as there's a matching random_chanceXYZ sparnarg for each. Without the matching spawnarg, the chance will come out at 0 so the item won't ever be added.

 

I tested it with these s/args on a chest lid:

"random_spawn1" "atdm:ammo_firearrow"

"random_spawn2" "atdm:ammo_mossarrow"

"random_spawnA" "atdm:ammo_broadhead"

"random_chanceA" "0.5"

"random_chance1" "0.8"

"random_chance2" "0.5"

"state_change_callback" "autoloot_chest"

 

You can make a new entity def with your preferred settings. Then changing the def will change all matching chest lids that haven't overridden the spawnargs.

 

If you want to stick to your original plan of a separate script for each chest then Spooks' global variable is the quick way as you found, but that method only works with a separate script for each chest, because a script shared between chests wouldn't know which chest had triggered it (and so couldn't disable the right chest).

Edited by SteveL
  • Like 1
Posted

Oh awesome Steve.

 

I am a novice when it comes to scripting, but this is really helpful. If I get a chance today or tomorrow I will plug in your script and give it a shot.

This is fantastic.

 

I can see getting a lot of use out of both scripts for different purposes.

  • Like 1
Posted

Cool. I added a fix to the script above by the way by moving
chest.setKey("already_opened", "1");
to the top of the block, so the player can't trigger the script a second time during the sys.wait()s between multiple items being spawned.

  • Like 1
  • 1 month later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • JackFarmer

      "The Year of the Rat." 
      😄

      Al Stewart must be proud of you!
      Happy testing!
      @MirceaKitsune
      · 1 reply
    • datiswous

      I posted about it before, but I think the default tdm logo video looks outdated. For a (i.m.o.) better looking version, you can download the pk4 attached to this post and plonk it in your tdm root folder. Every mission that starts with the tdm logo then starts with the better looking one. Try for example mission COS1 Pearls and Swine.
      tdm_logo_video.pk4
      · 2 replies
    • JackFarmer

      Kill the bots! (see the "Who is online" bar)
      · 3 replies
    • STiFU

      I finished DOOM - The Dark Ages the other day. It is a decent shooter, but not as great as its predecessors, especially because of the soundtrack.
      · 5 replies
    • JackFarmer

      What do you know about a 40 degree day?
      @demagogue
      · 4 replies
×
×
  • Create New...