Project Zomboid

Project Zomboid

Not enough ratings
HOW TO CREATE ANNOTATED STASH MAPS (41.6+)
By ringod123
This guide will teach you how to create Stash Map mods. If you have not already then it is worth checking out this guide on how to add lootable maps to the game world using the new procedural distributions system: https://theindiestone.com/forums/index.php?/topic/22577-how-to-create-lootable-maps-for-build-416/
   
Award
Favorite
Favorited
Unfavorite
Part 1
Once your lootable map is in game (or if you are wanting to add more using the ones already in game) you can then go ahead with this tutorial for creating your Stash maps. The first thing that you need to do is create a new folder named "StashDescriptions" in your mods "media\lua\shared" folder, if none of these folders already exist then create them.

Then you will need to create a StashDesc.lua file in the StashDescriptions folder, name it something unique for your mod (e.g bedfordStashDesc.lua). Once you have created the new file, open it and paste the following line in as the first line:

require "StashDescriptions/StashUtil";

Now you can start adding your stash maps, just leave a blank line after the first line you added above. Below are 2 examples each of the different stash types that can be made:

-- guns
local stashMap1 = StashUtil.newStash("BedfordStashMap1", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.spawnOnlyOnZed = true;
stashMap1.daysToSpawn = "10";
stashMap1.zombies = 5
stashMap1.traps = "5";
stashMap1.barricades = 50;
stashMap1.buildingX = 13782;
stashMap1.buildingY = 10524;
stashMap1.spawnTable = "GunCache2";
stashMap1:addContainer("GunBox","floors_interior_tilesandwood_01_62",nil,"bedroom",nil,nil,nil);
stashMap1:addStamp("X",nil,343,281,0,0,0);
stashMap1:addStamp(nil,"Stash_WpMap1_Text1",13266,10178,0,0,0);
stashMap1:addStamp("Circle",nil,13605,10374,0,0,0);
stashMap1:addStamp(nil,"Stash_WpMap1_Text2",13550,10396,0,0,0);
stashMap1:addStamp("Exclamation",nil,13452,10182,1,0,0);
stashMap1:addStamp(nil,"Stash_WpMap1_Text3",13475,10179,1,0,0);

local stashMap1 = StashUtil.newStash("BedfordStashMap2", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13751;
stashMap1.buildingY = 10531;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "GunCache2";
stashMap1:addContainer("GunBox","floors_interior_tilesandwood_01_62",nil,"bedroom",nil,nil,nil);
stashMap1:addContainer("GunBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addStamp("Target",nil,13243,10181,0,0,0);
stashMap1:addStamp("House",nil,13605,10374,0,0,0);
stashMap1:addStamp("Lightning",nil,13452,10182,1,0,0);

-- shotgun
local stashMap1 = StashUtil.newStash("BedfordStashMap3", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13620;
stashMap1.buildingY = 10515;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "ShotgunCache2";
stashMap1:addStamp("Skull",nil,13380,10274,0,0,0);
stashMap1:addStamp("X",nil,13520,10407,0,0,0);
stashMap1:addStamp("Question",nil,13873,10235,1,0,0);

local stashMap1 = StashUtil.newStash("BedfordStashMap4", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13596;
stashMap1.buildingY = 10516;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "ShotgunCache2";
stashMap1:addContainer("ShotgunBox",nil,"Base.Bag_DuffelBag",nil,nil,nil,nil);
stashMap1:addContainer("ShotgunBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addStamp("X",nil,13380,10274,0,0,0);
stashMap1:addStamp("House",nil,13520,10407,0,0,0);
stashMap1:addStamp("Target",nil,13873,10235,1,0,0);

-- tools
local stashMap1 = StashUtil.newStash("BedfordStashMap5", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13090;
stashMap1.buildingY = 10897;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "ToolsCache1";
stashMap1:addStamp("Circle",nil,13372,10366,0,0,0);
stashMap1:addStamp("Exclamation",nil,13650,10325,0,0,0);

local stashMap1 = StashUtil.newStash("BedfordStashMap6", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13112;
stashMap1.buildingY = 10899;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "ToolsCache1";
stashMap1:addContainer("ToolsBox",nil,"Base.Bag_DuffelBagTINT",nil,nil,nil,nil);
stashMap1:addContainer("ToolsBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addStamp("Exclamation",nil,13372,10266,0,0,0);
stashMap1:addStamp("Exclamation",nil,13650,10325,0,0,0);

-- survivor houses
local stashMap1 = StashUtil.newStash("BedfordStashMap7", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13248;
stashMap1.buildingY = 11313;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "SurvivorCache1";
stashMap1:addContainer("GunBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addContainer("ShotgunBox",nil,"Base.Bag_DuffelBagTINT",nil,nil,nil,nil);
stashMap1:addStamp("House",nil,13248,10418,0,0,0);
stashMap1:addStamp("Target",nil,13218,10359,0,0,0);

local stashMap1 = StashUtil.newStash("BedfordStashMap8", "Map", "Base.BedfordMap", "Stash_AnnotedMap");
stashMap1.daysToSpawn = "0";
stashMap1.buildingX = 13242;
stashMap1.buildingY = 11288;
stashMap1.zombies = 2;
stashMap1.barricades = 50;
stashMap1.spawnTable = "SurvivorCache1";
stashMap1:addContainer("ToolsBox",nil,"Base.Bag_DuffelBagTINT",nil,nil,nil,nil);
stashMap1:addContainer("ToolsBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addContainer("GunBox","carpentry_01_16",nil,nil,nil,nil,nil);
stashMap1:addContainer("ShotgunBox",nil,"Base.Bag_DuffelBagTINT",nil,nil,nil,nil);
stashMap1:addStamp("House",nil,13248,10418,0,0,0);
stashMap1:addStamp("X",nil,13218,10359,0,0,0);

As you can see with the examples above each map has its own unique name given as the first parameter in the brackets. Next up is it's item type, which is obviously Map, then the in game item it actually uses, in this case the map we added to the base game from the lootable map tutorial listed above. The last parameter is the "Stash_AnnotedMap" custom name which is needed, and yes it is spelled incorrectly.

We can govern how many in game days it takes before the stash maps become findable, how many barricades are put up around the building, how many traps are inside and how many zombies should spawn inside, these are maximum values, not guaranteed values. We can also choose if the stash maps can only be found on zombies or not.

The buildingX and buildingY co-ordinates are the co-ordinates of the building you want the stash to appear in, in world co-ordinates, you can always use the https://map.projectzomboid.com/ website to help with your co-ordinates if need be.

Next we have to choose what loot table the stash will pull from, in the above examples we are using SurvivorCache1, ToolsCache1, ShotgunCache2 and Guncache2, these act like regular room definitions but for the whole building.

Don't forget you can always check the vanilla stash descriptions in the games "media\lua\shared\StashDescriptions" folder

In the above examples you can see the "addStamp" lines, these will add stamps to your base lootable maps such as arrows, exclamation marks etc, these icons can be found in your zomboid install folder in "media/ui/LootableMaps/". All of the text references ("Stash_WpMap4_Text1" etc) can be found in the games "media\lua\shared\translate\en\Stash_EN.txt" file.

The X and Y co-ordinates to place the stamps are in world co-ordinates in the same fashion as adding a banner or legend to a regular map. You can then also specify a custom colour for your stamp using the last 3 parameters for R,G and B.
Part 2
As you can see in some of the example above we are also spawning in some new containers, some examples are spawning in duffel bags, some wooden crates (carpentry_01_16) and some even as "hidden" floor stashes. Lets take a quick look at each:

stashMap1:addContainer("ToolsBox",nil,"Base.Bag_DuffelBag",nil,nil,nil,nil); - Here we are adding a duffelbag and populating it from the "ToolsBox" definition. It will spawn in a random position in the building.

stashMap1:addContainer("GunBox","carpentry_01_16",nil,nil,nil,nil,nil); - Here we are adding a wooden crate and populating it from the "GunBox" definition. It will spawn in a random position in the building.

stashMap1:addContainer("GunBox","floors_interior_tilesandwood_01_62",nil,"bedroom",nil,nil,nil); - Here we are adding a floor stash to a bedroom and populating it using the "GunBox" definition.

Notice how if a container is using an item (duffelbag) it does not need a tile (carpentry_01_16 or floors_interior_tilesandwood_01_62) and vice-versa. Also notice how a room is specified with the floor stash. The last 3 parameters are for an X,Y and Z postion within the buildings lot, but are not used in the above examples.

These Stash definitions can be found in distributions.lua and as with other distributions can be modded or completely new ones added. As well as the lootable map guide posted earlier in this guide, there is also this guide on customizing loot that can be helpful:
https://theindiestone.com/forums/index.php?/topic/38329-customizing-loot-4151/

And that's it, you now have custom Annotated Stash Maps!