Jump to content
The Dark Mod Forums

Help with a Thief-style chest. (Solved)


kingsal
 Share

Recommended Posts

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
Link to comment
Share on other sites

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!

 

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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!

 

 

Link to comment
Share on other sites

Yes, but unlike floats it throws up errors to the likes of "wrong immediate type of boolean data type" when you try to set a value, unlike float. I'm just wondering why it's even a data type, for some sort of parity? We already don't have int.

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

 

 

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

  • 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.

 Share

  • Recent Status Updates

    • freyk

      Some years earlier i created some launchers for TDM. uploaded today some new sourcecode and executables on my github repo.
       
      · 0 replies
    • Epifire

      Say, I know it's been a while since the site got overhauled from the crash. But did we ever figure out if/how to get the recent topics & replies list back? It's not a total deal breaker but it was nice for becoming a thread creeper again...


      · 2 replies
    • Epifire

      Some of you who've been on the TDM discord know I was out of work last Winter, just putting in hrs for the developer portfolio. Currently I've been working a seasonal job to pay the bills and now I'm finally in my last week before I get bumped off. Things will be tight but I'm planning a long off period to make as much content as I can. Big plans in Unreal Engine as well as my most ambitious TDM collab yet! Never been so excited to be a stuck at home to pursue my life's work. With a lotta time and maybe some luck, I'm hoping to get enough art work done that I may start applying around to studios.
      · 4 replies
    • STiFU

      I finally got around to play Prey and I truly loved it. It is an incredible homage to System Shock and Deus Ex. While the gameplay is not en par with those two titles, the game makes up for that with its well written lore and story. The whole "world" just feells so authentic and it features a ton of really god environmental story-telling. Recommended for every immersive sim fan, i.e., everyone on this forum.
      · 2 replies
    • jaxa

      Alder Lake has arrived:
      https://forums.thedarkmod.com/index.php?/topic/18055-2016-cpugpu-news/page/15/&tab=comments#comment-466190
       
      · 0 replies
×
×
  • Create New...