Search the Community

Showing results for tags 'tutorial'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • News & Announcements
    • News
  • Project Zomboid
    • PZ Updates
    • General Discussions
    • Bug Reports
    • PZ Support
    • PZ Multiplayer
    • PZ Community & Creativity
    • PZ Suggestions
  • PZ Modding
    • Tutorials & Resources
    • Mods
    • Items
    • Mapping
    • Mod Ideas and Requests
  • General Games Development
    • Indie Scene
  • Other Discussions
    • General Discussion
    • Forum Games & Activities
    • Pen & Paper / Community RPGs

Found 38 results

  1. So... you want hotkeys the player can press that does something for your mod. The problem: The player should be able to reconfigure these keys, so they don't conflict with the players existing setup or other mods they have loaded. Sure you can have these keys setup in a 'settings.lua' file the player can edit, but that leads to its own problems... If a user edits this file, and the mod is designed for multiplayer, then they'll have issues connecting to servers since the checksums won't match. Maybe you're feeling clever, and decided to write these settings into a settings.ini file instead, and just read the ini on loading (thus not having to worry about checksums), but that's a problem too....users rarely read the documentation, and hate manually editing files in notepad! So...the only real answer is to have a proper GUI where they can edit these settings, and what better GUI to use then PZ's own options screen! For this tutorial I'll explain using some work I've been doing on the ORGM mod today. I needed 3 new hotkeys: for equipping the best pistol, best rifle, and one for the best shotgun. Nice and clean there, no need to manually edit file, or screw up the luachecksums, or need to explain to users how to do it other then: 'it will be in your pz options screen' Here's our script in full: All the key bindings listed on the options screen are stored in the global table called keyBinding First we need to find the index of the option we want to insert after: local index = nil for i,b in ipairs(keyBinding) do if b.value == "Equip/Unequip Stab weapon" then index = i break end end The next chunks of code are wrapping in a 'if index then .... end' block, but I'll omit that here just so I can break this 'if statement' into smaller pieces (you can see it in the full script in the spoiler above) Since we got our index and know our insertion point, lets insert the new options: table.insert(keyBinding, index+1, {value = "Equip/Unequip Pistol", key = 5}) table.insert(keyBinding, index+2, {value = "Equip/Unequip Rifle", key = 6}) table.insert(keyBinding, index+3, {value = "Equip/Unequip Shotgun", key = 7}) Note these keys actually correspond to 4, 5 and 6 respectively (esc is key=1, swinging weapon is key=2, firearm is key=3, and stabbing weapon is key=4) You can also use constant values for these, if you look in shared/keyBinding.lua, you'll see rack firearm is key = Keyboard.KEY_X Now we need to overwrite the MainOptions:create() method, so we can fix some translation issues: local oldCreate = MainOptions.create function MainOptions:create() oldCreate(self) for _, keyTextElement in pairs(MainOptions.keyText) do repeat if not keyTextElement or not keyTextElement.txt then break end local label = keyTextElement.txt if == "Equip/Unequip Pistol" then label:setTranslation("Equip/Unequip Pistol") label:setX(label.x) label:setWidth(label.width) elseif == "Equip/Unequip Rifle" then label:setTranslation("Equip/Unequip Rifle") label:setX(label.x) label:setWidth(label.width) elseif == "Equip/Unequip Shotgun" then label:setTranslation("Equip/Unequip Shotgun") label:setX(label.x) label:setWidth(label.width) end until true end end Notice the first thing in that block is we store the original MainOptions:create() method in a variable, and call it first thing in our overwrite. By doing this we're just basically appending our new code to the end of the original function. The problem is if we don't do this, our options will appear as "UI_optionscreen_binding_Equip/Unequip Pistol" on the screen, unless you have a proper translation entry. Since we dont, we need to change the label translations so we don't have that "UI_optionscreen_binding_" prefix. As well as changing the text that gets shown, we need to reset the x position, and the width of the label or they'll still be positioned too far off. By calling label:setTranslation() it fixes the label.x and label.width variables, but doesn't actually adjust the positions so we need to call label:setX() and label:setWidth() manually. And thats it for the options screen...all you need to do to have the custom keys show up and be configurable. This is where our 'if index then .... end' block actually ends. Note you'll still have the translation problem when the user clicks to change the key to something else, the popup will need fixing.... you have to overwrite MainOptions:render() for that, I won't be covering that here since its a minor issue, and doing that might be incompatible if 2 mods use this same technique. The code above can be used by multiple mods at the same time without issue, even with our overwrite: If your mod overwrites MainOptions:create(), and another mod loads after and uses the same technique, then their overwrite ends up calling yours, and yours then calls the original function. Now for the final piece, the event hook when the player presses a key: Events.OnKeyPressed.Add(function(key) local player = getSpecificPlayer(0) if key == getCore():getKey("Equip/Unequip Pistol") then player:Say("Key pressed: Equip/Unequip Pistol") elseif key == getCore():getKey("Equip/Unequip Rifle") then player:Say("Key pressed: Equip/Unequip Rifle") elseif key == getCore():getKey("Equip/Unequip Shotgun") then player:Say("Key pressed: Equip/Unequip Shotgun") end end) Our key presses here don't actually do much, the player just says which of the keys options got triggered. But that's all there is to it, custom user configurable keys that don't force players to manually edit files, and bypass server lua checksum comparisons.
  2. As you (probably) already know, PZ allows us to define timed events using OnEveryTenMinutes, EveryHours, and EveryDays. As handy as they are, sometimes we want a more refined system. Maybe we want a event to trigger in 15 minutes, and possibly repeat itself a few times then stop. Maybe we want something to happen every 60 seconds in game. Well I got bored this morning and cooked up such a system... (this would go in the lua/shared folder) First we create our Timers table: Timers = { ActiveTimers = {}, } This will hold our functions, and the sub-table ActiveTimers will hold our actual timer queue. Now we need a handy function to add timers to our table: Timers.add = function(delay, repeats, callback, args) local hours = getGameTime():getWorldAgeHours() local t = { delay = delay, callback = callback, args = args, repeats = repeats, trigger = hours + (delay/60), } = ZombRand(100000) .."-".. t.trigger Timers.ActiveTimers[] = t return t end This function takes 4 arguments: delay = the number of minutes to wait before triggering our timer. This should be a integer value greater then 0. repeats = the number of times to repeat the timer, after the first triggering. If repeats is 0, nil or false, it will only fire once. If true then it will endlessly fire. A value of 2 will trigger a total of 3 times (the initial trigger, then 2 repeats) callback = the function to call when this timer is triggered. It should accept 2 arguments: the timer itself, and whatever value is in the 'args' variable args = passed to your callback function. This can be anything, although you should be careful not to pass variables that may have expired (ie: a IsoPlayer object on a server, in case that player disconnects before the timer is triggered) Its going to be up to you to make sure your callback function properly verifies anything you pass to it as args. Notice we use getGameTime():getWorldAgeHours() to help define when this timer should trigger (see the t.trigger variable in the above function). This will return a float value such as 125.25, which would mean 125 hours and 15 minutes into the game (125.50 is 125h and 30min). Since our 'minutes' are a percent value of 1 (15 minutes = .25) we use delay/60 Now we need a function to remove our timers just in case we need to cancel early: Timers.remove = function(timer) if type(timer) == "table" then -- not a proper timer table if not then return end timer = end Timers.ActiveTimers[timer] = nil end The timer argument can be one of 2 things: the actual timer table returned by Timers.add(), or the timer id. Now those 2 important functions are out of the way, time for our function that actually checks if a timer should be triggered: Timers.check = function() local current = getGameTime():getWorldAgeHours() for id, timer in pairs(Timers.ActiveTimers) do if timer.trigger <= current then if not timer.repeats or timer.repeats == 0 then Timers.ActiveTimers[id] = nil elseif type(timer.repeats) == "number" then timer.repeats = timer.repeats - 1 end timer.trigger = current + (timer.delay/60) timer.callback(timer, timer.args) end end end basically we loop through our Timers.ActiveTimers table, and if the timer.trigger is less then the current world age hours, its time to call the callback function! Notice if the timer.repeats is a number (and not 0) it lowers the repeat by 1. It also sets up the next timer.trigger value. Pretty easy stuff. Now we need to be able to call the Timers.check() function on a interval, using PZ's events system. There's 2 events we can use, each with benefits and drawbacks: Events.OnTick.Add(Timers.check) This method using OnTick will give you the most accurate timers and allows you to setup timers with a delay of 1 minute. Its drawback is that its called ALOT (multiple times per 1 second of game time), so if your planning on having alot of active timers at once, performance may suffer and you should probably use this instead: Events.EveryTenMinutes.Add(Timers.check) The drawback here is timers are effectively only triggered every ten minutes. So now for a example of a timer added client side (they can be added server side as well) local callback = function(timer, args) if not timer.repeats or timer.repeats == 0 then args:Say("Last Call!") else args:Say("Timer Triggered!") end end Events.OnGameStart.Add(function() Timers.add(15, 3, callback, getSpecificPlayer(0)) end) On logging into the game, this will make our player say "Timer Triggered!" every 15 minutes, 3 times, then 15 minutes later say "Last Call!" Please note these timers are NOT saved on exiting (or server shutdown), I'll leave that part to you creative people to figure out a method of doing so. This is after all, a tutorial on timers, not saving data
  3. So I was working on some code for our server mod, and it turned out pretty cool. Since I haven't written a tutorial in a while, I thought I'd share. The problem: I wanted to create special upgraded items, and unique(ish) ones, without having to define the objects in the media/scripts/*.txt files, or having to mess around with distribution tables and all that nonsense. The items also had to be able to inherit properties from the base items they were copying. But, that being said...this tutorial isn't so much about the end goal, but the methods used to accomplish it. Warning: some of the tricks used are semi-advanced and not normally done for sanity purposes. It's useful to be familiar with the InventoryItem class API, and the HandWeapon subclass for this tutorial particularly the various 'get' and 'set' methods, since thats what we'll be using (in a very backwards and dynamic way!) The full code (well, partially edited) for the script is here, but I'll break it down into smaller pieces below: Now the first bit kinda speaks for itself: local UPGRADE_CHANCE = 10 -- 1 in # chance item is upgraded local SPECIAL_CHANCE = 100000 -- 1 in # chance item is special The chances that a spawned item will be a 'upgraded version' or a 'special version'. So first we need to create some tables holding the new stats for our upgraded items. For this example, all the items are weapons but any item will work: local UpgradedItems = { ["Base.KitchenKnife"] = { { absolute = { Name = "Fancy Kitchen Knife", }, multiplier = { ConditionLowerChance = 2, } } }, ["Base.Axe"] = { { absolute = { Name = "Hatchet", TwoHandWeapon = false, OtherHandUse = false, }, multiplier = { MinDamage = 0.7, MaxDamage = 0.7, MaxRange = 0.7, MinimumSwingTime = 0.7, SwingTime = 0.7, Weight = 0.7, ActualWeight = 0.7, }, } } } local SpecialItems = { ["Base.KitchenKnife"] = { { absolute = { Name = "Lorena Bobbitt's Knife", CriticalChance = 100, }, multiplier = { ConditionLowerChance = 10, } }, { absolute = { Name = "Jack the Ripper's Knife", }, multiplier = { ConditionLowerChance = 10, MaxDamage = 1.5, }, }, }, ["Base.Axe"] = { { absolute = { Name = "Lizzy Borden's Axe", CriticalChance = 100, }, multiplier = { ConditionLowerChance = 4, }, }, { absolute = { Name = "Paul Bunyan's Axe", }, multiplier = { ConditionLowerChance = 4, TreeDamage = 4, }, relative = { MaxDamage = 1, MinDamage = 1, }, }, }, ["ORGM.ColtSAA"] = { { absolute = { Name = "Billy the Kidd's Colt SAA", HitChance = 75, AimingTime = 5, }, }, } } For those UpgradedItems and SpecialItems tables, the key/value pairs are 'the full name of the item', and the value is another table. That table contains a second layer of tables: each possible upgrade. Take a look at the SpecialItem one for "Paul Bunyan's Axe" { absolute = { Name = "Paul Bunyan's Axe", }, multiplier = { ConditionLowerChance = 4, TreeDamage = 4, }, relative = { MaxDamage = 1, MinDamage = 1, }, }, It contains all 3 sections (the other items only contain 2 sections each), 'absolute', 'multiplier', and 'relative'. Absolute sets a value to a specific value. Multiplier takes a items current value, and multiplies it. Relative takes a items current value, and adds onto it. Now, the function that does the actual item upgrade: local upgradeItem = function(item, upgrade) if not item or not upgrade then return end if upgrade.absolute then for key, value in pairs(upgrade.absolute) do item["set" .. key](item, value) end end if upgrade.multiplier then for key, value in pairs(upgrade.multiplier) do item["set" ..key](item, item["get" ..key](item) * value) end end if upgrade.relative then for key, value in pairs(upgrade.relative) do item["set" ..key](item, item["get" ..key](item) + value) end end end This function takes 2 arguments, the item to be upgraded, and the upgrade data. This is the part that calls the InventoryItem and HandWeapon methods, but you'll notice there's no actual method calls hardcoded in there such as item:setName(value) or item:setConditionLowerChance(value)! Instead, we're treating these items as actual lua tables, and building the method names dynamically from strings: item["set" .. key](item, value) so when the key is "Name" and the value is "Paul Bunyan's Axe", its checking the 'item' table for 'setName', and treating the returned value as a function, passing it 2 arguments: the item itself, and "Paul Bunyan's Axe". This is identical to: item:setName("Paul Bunyan's Axe") If the key is "ConditionLowerChance" and the multiplier value is 4, then this: item["set" ..key](item, item["get" ..key](item) * value) becomes this: item:setConditionLowerChance(item:getConditionLowerChance() * 4) I should mention at this point: this is a completely backwards way of doing it and generally not advisable. You can drive yourself nuts calling methods dynamically this way when you need to debug a error. BUT it is completely valid way of dynamically deciding on method calls using strings, instead of having a massive pile of if/elseif conditions. So now we have a function that can create our upgraded/special items from normal ones, and tables holding our upgrade data, now for the final part: deciding on when to upgrade: Events.OnFillContainer.Add(function(roomName, containerType, container) -- see if any of our items that spawned have possible upgrades for itemName, upgrades in pairs(UpgradedItems) do repeat local items = container:FindAll(itemName) if not items then break end for i=1,items:size() do repeat if ZombRand(UPGRADE_CHANCE) +1 > 1 then break end upgradeItem(items:get(i-1), upgrades[ZombRand(#upgrades) + 1]) until true end until true end -- see if any of our items that spawned have possible special versions for itemName, upgrades in pairs(SpecialItems) do repeat local items = container:FindAll(itemName) if not items then break end for i=1,items:size() do repeat if ZombRand(SPECIAL_CHANCE) +1 > 1 then break end local item = items:get(i-1) if not item then break end upgradeItem(item, upgrades[ZombRand(#upgrades) + 1]) -- set condition to max since this is a special item:setCondition(item:getConditionMax()) until true end until true end end) We simply hook the OnFillContainer event. This event is triggered AFTER the base files have filled out items in a container, allowing us to see what spawned. You'll notice I use a funky way of looping through the upgrade tables here: for itemName, upgrades in pairs(UpgradedItems) do repeat local items = container:FindAll(itemName) if not items then break end ... until true end That snippit above is technically a double loop, the 'for .. end', and the 'repeat ... until true' part. Why would I do such a thing? While lua doesn't have a keyword 'continue' for skipping the rest of the code and jumping to the next repeat of the loop. All you can do is 'break' out of a loop. By using this funny loop syntax, we can use 'break' as a skip: it breaks out of the 'repeat .. until ..' part, and goes straight to the part of the 'for ... end' loop. Doing this cuts down on a pile of nested 'if' statements. For example if I wrote the first 'for' loop normally: -- for .. do repeat .... until .. end for itemName, upgrades in pairs(UpgradedItems) do repeat local items = container:FindAll(itemName) if not items then break end for i=1,items:size() do repeat if ZombRand(UPGRADE_CHANCE) +1 > 1 then break end upgradeItem(items:get(i-1), upgrades[ZombRand(#upgrades) + 1]) until true end until true end -- for .. do .... end for itemName, upgrades in pairs(UpgradedItems) do local items = container:FindAll(itemName) if items then for i=1,items:size() do if ZombRand(UPGRADE_CHANCE) +1 == 1 then upgradeItem(items:get(i-1), upgrades[ZombRand(#upgrades) + 1]) end end end end These are small loops without too many nests, so its not overly a big deal here, but its a handy trick to know that many people probably aren't aware of. But there we go, dynamically created special items that spawn without editing the script files or distribution tables, and inherit values from the base items. Hopefully if actually read all of that you learned a trick or two. Plus, how can you go wrong when you see this as a characters 'favorite weapon':
  4. This is very similar to adding foraging zones to your map, (step 6 of this tutorial: ) Simply add the following code to your map mods' PZW file the same way as in step 6 of the above guide: <objecttype name="ParkingStall"/> <objectgroup name="ParkingStall" color="#85929e" defaulttype="ParkingStall"/> List of vehicle zone names to use in WorldEd: bad good medium sport farm junkyard trafficjams trafficjamn trafficjame trafficjamw rtrafficjams rtrafficjamn rtrafficjame rtrafficjamw police ranger fire mccoy fossoil postal spiffo radio ambulance burnt The first group is the most common type of vehicle zones used. The second group are for traffic jams pointing in specific directions to immitate the flow of traffic. The ones prefixed with r will spawn less than the regular trafficjam zones. The third group are specific zones for the type of vehicles listed, they are still also spawn random cars but will also spawn the vehicle listed. The final one will add random burn out vehicles. Vehicle zones should be placed as a multiple of 4x3 tiles (4x3, 8x6, 28x3 etc) with 4x3 being a single vehicle, 4 being its side and 3 being its front/back. You can choose any color values you want for the different zones, just make sure they are hex color codes. Once done, load your map mod up in WorldEd, open a cell and add your new vehicle zones as you would foraging zones. Whenever you add a zone you need to use the objects panel on the left of the WorldEd window to give the zone a name (use the names listed above) that will be visible in WorldEd as a tag over the zone, making it easier to keep track of what you have placed where, if these are left blank then the game will default back to grabbing random vehicles from the ParkingStall zone. Example: After you have added vehicle zones to all of your cells, save your map. Once saved, generate your lots and then write objects to lua. You now have vehicle spawns in your map. If you are having trouble with your vehicle zones, you can always take a look at the vanilla objects.lua within the muldraugh folder of your zomboid install, once opened just search for "ParkingStall" to see examples of vehicle zones used in the vanilla vehicle branch. For aligning vehicles in parking stalls: Select a ParkingStall object. In the Properties panel, click the "add" button under Templates. Choose one of the 4 ParkingStallX templates. You should see "Direction=X" where the object name is displayed. The direction controls where the front (or back) edge of each vehicle is aligned. In the picture you can see a Direction=E ParkingStall facing a Direction=W ParkingStall. This is used to ensure the vehicles don't overlap each other, and leaves space for the player (and zombies) to walk between them. For single parking stalls, there is usually no need to choose a direction. The FaceDirection property can be added to ParkingStall objects to align the front of a vehicle to the edge specified by the Direction property. When this property is "false" or isn't assigned to a ParkingStall object, the vehicle will face in a random direction as before. This can be used for parallel-parked vehicles for example.
  5. Any full tile roof peice that is currently not over a room definition in your building needs a room definition. For any bits that are above an internal room, simply make sure that room has a room definition (all room in buildings should, even hallways etc). If the roof bit is over an outside area (such as a porch) then instead of giving it an internal room definition, which could possibly mess with loot tables etc, use the new room definition made for this situation - emptyoutside. In the example below you can see that this building has a porch roof outside the front door, all other bits of roof are already over a pre-existing room definition and so we don't need to worry about them. We do need to add an emptyoutside room definition on/under the porch roof however as there currently is no room definition outside the building. In this example, the porch roof is on the roof layer of floor 2. If we check Ortho view you can see that a room definition of emptyoutside yellow) has been applied to the corrosponding tiles on floor 2. Once applied, simply save the building and move on to the next. Once all buildings are done, close buildingEd and open your map in WorldEd, generate lots and you're done, your map should now support the new roof occlusion system! If you're having problems getting it to work properly, remember: every "full tile" roof peice (the little overhang peices you see in the example above do not need to adhere to this rule, just leave them as is if you have any) must be "over/on" a room definition, so make sure every room in your buildings has a room definition (including hallways etc). Add a room definition of "emptyoutside" (without " ") to any full tile roof peices that do not sit "over/on" an internal room definition. Make sure to generate lots in WorldEd once all of your relevant buildings have been updated.
  6. Hey guys I need some help with TileZed's BuildingEd. I just finished a cool building that I worked so hard on, saved it and everything, didn't click on anything out of the ordinary. When I went to WorldEd, I clicked on my building, didn't show a preview image. When I dragged it out onto my Cell, it didn't show a building, neither did it plop a building when I placed it on my map itself. Then I went to BuildingEd to see if I messed something up, and instead I got an error saying, "Error Reading Building - Invalid Object Coordinates (1, -3 Line 2209, Column 72". What does this mean and how can I fix it without having to remake my whole tower? THANK YOU! My building's png is still in one of the .pzeditor folders, so idky it won't show in WorldEd or let me edit it either in BuildingEd.
  7. Ok when using the wall tool make sure for these sides you click on Exterior wall and select your texture. Click the multicolored square at the top toolbar and you get the room tool. then go to the plus and click add room When you open it up you see there are two names, the top one doesn't matter, the second one indicates what spawns there, so if im making a bedroom put bedroom for internal room name. this is a good list to help you figure out the names for spawns (THANK YOU RingoD123 for the roomlist). Then go down and click interior walls none (if you used the wall tool) do the same for Tri Go to floors and pick your floor tiles you want, i choose carpet for this bedroom If you click on the little color box, it will let you choose a color so you don't confuse yourself when you have more than one room like 2+ bedrooms, one you can set to blue, another to red. if you want or you can keep using the same one if it's going to use the exact same floors. then you go to the exterior walls and select what you want the outside walls to be, if you want to use the wall tool, select none and it will look like this If you want it to match or use a different color for the hallways outside the bedroom go to exterior walls and select your wall (i decided to match mine). If you go to Ortho you get an overhead view and you'll notice that your rooms are visible based on the color you picked earlier you can do everything without using the room tool if you want, then when you want to spawn stuff(you will need to use the room tool for that) you just set everything in the room tool to none, and go to exterior walls and click it to NONE and it will look like this (this way you can continue using the wall tool). Wall tool version This is how you do floors in ISO mode rather easy. Just go to floors when you have your room selected red bedroom(or whichever you picked) and pick the floor tile you can switch back and forth once you have the rooms setup using the textures on the right, just change the Room drop down menu I have highlighted and it will automatically fill it in Red Bedroom right window click on tile, bam, blue bedroom click on tile, bam, etc etc Also dont be a NUB put lightswitches in your house or it will be pitch black Lighting - Indoor Also if you want to spawn items not found in a bedroom in a bedroom but not mess up dressers too here's how, make a new room with a new internal name - I picked gunstore for gun spawns, picks a gun locker for furniture and placed it. set everything to none, except the same color floor, then this is where ORTHO helps and the color coding click the draw room tool after selecting the new room from the drop down menu you'll notice I have 4 square selected (only need one for the gun locker) but the furniture is blocking the tile so I did 4 for you to see As you can tell it all looks the same in ISO mode, but anything that is storage will spawn gunstore stuff now on those 4 tiles So when you have stuff like offices, that you want office supplies, but also have something like a mini fridge, or cabinets, you can just do that and keep the same textures, but have different spawns! I hope I explained it well. Hopefully there will be more to come! I often get questions in Discord so since I go through the effort to walk people through it I figure I'd share it here! Again TY StarKitty for the motivation! Happy Mapping!
  8. So earlier today, it was brought to my attention there are some new tiles that "Starkittycat || Game Dev || YT" made me aware of. One of those new tiles is Sliding Glass Doors! So here's how to use them on your house to pretty em up all nice. Ok top left click on Building - Then tiles Left side the top menu click on Doors Then in the middle window pane, scroll till you get to fixtures_doors_01, then on the right side the doors will appear. Go down and click on the white sliding glass door(or the red ones). Then you see my mouse cursor in the bottom left is over the Plus symbol. click Add Tiles Click Ok when you see it added to fixtures_doors_01 on the bottom left menu. Ok then go to ISO mode and click on Door Icon at the top toolbar, then click on Door Frames in the right side menu, Select NONE otherwise it will act strange This is what happens if you don't click none, apparently the modified it for doors to act sideways. This is it with door frames at none. Now I'm going to do windows. Ok, so click on the windows, then select the white window one without a handle, Go to the bottom left and click the plus. (just like we did with doors Then in ISO mode click on the Window Tool in the top toolbar, then go to the windows, on the right side menu and select the white sliding door window under fixtures_doors_01 Now you don't have to go to Tiles ever again for those textures! it is a little silly, but it saves time later on. I hope this helps everyone add some awesome sliding glass doors to their houses! Happy Mapping and thanks to StarKitty for motivating me to do this!
  9. This tutorial assumes you know the very basics of Lua: what a variable is, and how to assign one. what a function is, and how to call one and pass variables to it. what a table is, and how to declare one. It is dedicated to modders new to Lua, and is a general tutorial on Lua... not specific to modding PZ. Variables and function scope: This seems to be one of the more overlooked aspect I've noticed in mods, and is EXTREMELY important for efficient and fast code. There are 2 scopes: global and local. * Global variables can be accessed by any part of the code, from any function, in any file, and are declared like: * Local variables can only be accessed from the file (or function) that they are declared in. The more variables declared, the longer its going to take to find any specific one. Think of it like a phonebook... if you need to look up a number and that book has 1000 different numbers in it, it will take longer to find the one you want. Ideally you only want the book to contain numbers your actually planning on calling. One of the reasons Lua is used as a language for a lot of games is due to its speed. One of the reasons its fast is because by default it doesn't pollute the global space with unneeded stuff. The most important thing to remember: ALL VARIABLES ARE GLOBAL BY DEFAULT UNLESS DECLARED LOCAL. This is often overlooked. If we wanted to make sure a variable can not be accessed outside the file or function (thus not polluting the global namespace), we declare it like this: local modName = "My new mod" If we wanted a to declare this in a function printModInfo instead: function printModInfo() local modName = "My new mod" print(modName) end Had we left out the 'local' key word there, modName reverts to global, and can now be accessed anywhere. Not only is it bad for performance, it also runs the risk of accidentally over writing another variable...if someone else's mod used the same variable name in the global namespace. Lets assume we actually want modName to be global, as well as modInfo, modAuthor and modVersion, so we can access them from other files in the mod. We could declare them all global but why pollute the global space more then we have to? We're better off sticking them in a global table: MyModData = { modName = "My new mod", modInfo = "My description", modAuthor = "Me!", modVersion = 1.0 } print(MyModData.modName) It may not seem like we've saved much, only adding 1 item into the global space instead of 4, but it adds up. Tables are important for organizing and separating data. This same concept applies to functions, they can exist in the global or local space, and are assumed global unless declared with the local keyword. They can also be declared in 2 styles: -- global function printModInfo() ... end printModInfo = function() ... end -- local local function printModInfo() ... end local printModInfo = function() ... end You may have noticed the second style there actually creates a function but assigns it to a variable name, this is perfectly valid and can be a handy trick: function printModInfoStyle1() ... end function printModInfoStyle2() ... end printModInfo = printModInfoStyle1 we can reassign printModInfo to Style1 or Style2, depending on some condition and call it later simply as printModInfo() Lets say you want to add a Event that triggers on keypress: local function someFunction(key) ... end Events.OnKeyPressed.Add(someFunction) Remember to declare that function local, its not getting called from anywhere else. Actually, since its only getting passed to Events.OnKeyPressed.Add, and not even getting called locally, you can shortcut and skip polluting the local space as well: Events.OnKeyPressed.Add(function(key) ... end) Some coders may disagree with that last example, but remember the trick to writing efficient Lua is to keep the scope as small as possible, since we'll never need that function again, there is no point assigning it a name. If you create a number of functions, and the only code that calls those functions exists within the same file, be sure to make them local. The same thing I said above about sticking global variables into a table to avoid namespace pollution also applies to functions. If all those functions you declared you need to access elsewhere, put them in a table: MyModFunc = { functionNo1 = function() ... end, functionNo2 = function() ... end, functionNo3 = function() ... end, } MyModFunc.functionNo4 = function() ... end -- this works too This isn't related to global/local scope, but is often the most confusing (and annoying) part for new Lua coders so worth mentioning. Functions inside tables can actually be declared and accessed 2 ways: MyModFunc = { } function MyModFunc.functionNo1() ... end function MyModFunc:functionNo2() ... end and calling them as: MyModFunc.functionNo1() MyModFunc:functionNo2() Notice the use of : in functionNo2 instead of the . The first style is a normal function, and behaves exactly like you'd expect. The second style is technically called a 'method', it will pass a variable named 'self' to the function. In this case 'self' is the table MyModFunc. The functionNo2 method is basically doing this: function MyModFunc.functionNo2(self) ... end MyModFunc.functionNo2(MyModFunc) Now that all that is sorted out, here's a additional scoping trick... functions can be created inside other functions: local functionNo1() local myVariable = "some text" local functionNo2 = function() print(myVariable) end return functionNo2 end local result = functionNo1() result() -- prints "some text" this calls the first function, which returns the second, the second (now in the variable 'result') is called, and prints "some text" While the above bit of code itself not overly useful, it demonstrates a few points: functions inside functions, and variables are inherited from the above scope (even locals) and can be used after their scope has ended.
  10. Here you will find a (hopefully) comprehensive guide to map modding using TileZed, from scratch, to uploading to Steam Workshop. Step 1) Installation and setup Spoiler - Download the latest version of TileZed here ( Unzip the download to a destination of your choice (c:\, or desktop for example), it's usually best to create a new folder first, called for example, "Zomboid Mapping" and unzip the download into that folder, you will end up with 3 new folders, TileZed, WorldEd and Tiles. - To load the program, navigate to the TileZed folder and double click on TileZed. WorldEd and BuildingEd are both opened from within TileZed's menu's. 3 Step 2) Creating a new map - Creating A Master Image Spoiler The first thing you need to do to create a new map mod is to create some basic images you can import into WorldEd. You will need a paint program such as Paintshop, Gimp or Paint.Net (I use and it works great). Open your paint program of choice and create a new image, each pixel of the image will correlate to 1 tile when in game, so, if you want to create a map that is a single "cell" in size, you would create a 300x300 pixel image. If you wanted to make a 2x2 cell map you would create a 600x600 pixel image etc. Once you have created your new blank image save it as a png file (eg. MainMaps.png), this is so you can work with multiple layers, which will make your life way easier! - Creating The Base Map Image Spoiler Now you have your blank map image up and ready we need to setup the exact colours we will be using to draw the game world (when importing your image into WorldEd every pixel gets read and converted into the relevant tile (if the colour is recognised by WorldEd)). Use your programs colour palette to enter the colours below using the RGB values given: -----Base Map Colours---- Dark Grass | 90 100 35 Medium Grass | 117 117 47 Light Grass | 145 135 60 Sand | 210 200 160 Light Asphalt | 165 160 140 Dark Asphalt (main roads) | 100 100 100 Medium Asphalt | 120 120 120 Gravel Dirt | 140 70 15 Dirt | 120 70 20 Dark Pothole | 110 100 100 Light Pothole | 130 120 120 Water | 0 138 255 ----Veg Map Colours---- Dense Forest | 255 0 0 Dense Trees + Dark grass | 127 0 0 Trees + grass | 64 0 0 Mainly grass, some trees | 0 128 0 Light long grass | 0 255 0 None (black) | 0 0 0 Now you are ready to start drawing your base map, for now you should ignore all the colours listed after water as you will be drawing these onto separate vegetation map layers. Example: Spoiler MAKE SURE TO TURN ANTIALIASING OFF AND CHANGE BLEND MODE TO OVERWRITE BEFORE HAND! (otherwise you will get colours not recognized by WorldEd, leading to extra work later). - Creating The vegetation Map Image Spoiler Now you have created your base layer which should contain your main roads (using the dark asphalt colour), paths and side roads (light asphalt, dirt, gravel dirt), dirt, water, sand and grassy ground (dark/medium/light grass), save this image as a BMP (eg. MyMap.BMP) (if warned about flattening the image just select yes/continue/ok) it's now time to start drawing the vegetation map on a new layer. Close the BMP image you just saved and create a new layer on your original .png,have it above your base layer (it should put itself there automatically), copy your original layer and paste it onto the new layer, then hide/untick your base layer. On this new layer start by selecting the None(black) colour from above and flood fill all the roads (and any other area where you do not want vegetation to grow such as water, sand etc (erosion vegetation will still work fine)) and delete any/every other colour from this layer, leaving just the black areas you just created. Now start drawing the other five colours (the ones you ignored when creating your base map) on places where you do want vegetation to spawn. Start off with using a seperate layer for each colour, starting with the Light long grass, just flood fill that entire layer with it, then drag your black "no veg" layer above it, this allows you to see the road/building layout easily. Then work your way up through the other colours (creating new layers for each one, each one above the last in the order list) as needed, all the way to the dense forest one. Save your PNG now, you're going to make some temporary changes you dont want to save. To save this as a vegetation image, make sure your base layer is still hidden/unticked (so only your vegetation layers are visible) and then start merging your vegetation layers together, from the top down. You should now be left with 2 layers, a single vegetation layer, and your hidden base layer, save the image as a BMP (eg. MyMap_veg.BMP) (if warned about flattening the image just select yes/continue/ok), note that this image MUST be saved with the same name as your base map BMP with the added "_veg" at the end, it must also be saved in the same folder as your base map BMP. Once you have saved the veg map BMP, close that image and then close your PNG WITHOUT saving, unless you want your vegetation layers to be permanently merged, making it a lot harder to make edits, if needed, in the future. Example: Spoiler - Creating The Zombie Spawn Map Image Spoiler You will also need to create a new image called a zombie spawn map to tell the game about the density of zombies in our map, this is a black and white image that is 10x smaller than your base and vegetation images, so, if your map image is 600x600 pixels, your zombie spawn map would be 60x60. Start by flood filling it black (black means no zombies), then add white and grey lines/circles/patches where you want zombies to spawn, white is highest density, getting lower and lower with darker greys. (example), Save this in the same folder as your base map and veg map, again giving it the same name but this time with the "_ZombieSpawnMap" suffix (eg. MyMap_ZombieSpawnMap.BMP). It can be handy to make sure anti-aliasing is enabled when creating this image as it will naturally add shades of darker grey around any white or greys you place. You now have all the required images to create a new world in WorldEd. Example: Spoiler - Importing into WorldEd Spoiler Open TileZed, click on the Tools menu and then Click on WorldEd, this will open a new window, click on New, give it the size of your map (e.g. 2 cells x 2 cells) and click ok, you will now see a number of numbered squares depending on the size of your map. Each one of these squares represents an in game Cell (300x300 tiles). Now, navigate to the folder where your map mod images are stored and drag and drop the base image (MyMap.BMP) into the WorldEd window, making sure it covers all the numbered squares correctly. Once done, click on File and then BMP to TMX, on the window that pops up, click on the 3 dots in export directory and create a new folder (e.g. MyMapMod) for your mod and click on select folder, then before you press ok, make sure "Assign generated maps to world" and "Report unknown colours" are both ticked, then click ok. Click ok on the sanity check (make sure you aren't accidentally overwriting the wrong mod etc) and WorldEd will do it's magic. Now, if you forgot to turn anti-aliasing off, WorldEd will probably pop up and tell you your image contains rogue colours, it will then list each rogue colour found along with the co-ordinates (in pixels) of every pixel with this rogue colour, you will need to open your images, find ALL of these pixels/colours, replace them with the correct colour(s) from step 2 then re-import into Worlded, otherwise you will end up with errors in your game world when it comes time to play. If WorldEd didnt throw up any colour errors then all you need to do now is click on file and save, give your world a name (I like to use the same name as the map to avoid confusion) and save, you now have the basics of a new map, to which you can now start adding buildings and world detail! Step 3) Creating/Adding custom buildings Navigate to your TileZed folder and create a new folder inside named Buildings, this is where you are going to save any buildings you make or download. - How to create custom buildings Spoiler Open TileZed. Click on Tools then Building Editor In the new window click on New Building. In the settings window that pops up you can choose a template and the plot size for your building. The templates provide pre-made room definitions for certain types of buildings, which are crucial for spawning the correct loot in the right places. For now choose “none” for the template and leave the plot size at 20x20 tiles. It's always best to make your plot a bit bigger than your actual building and surroundings will be as you can shrink your plot to match your finished building later. Click OK. You will be presented with a grey screen with a grid of 20x20 squares. For now, make sure Iso is selected on the left of the window. The first thing you need to do now is create some room definitions for your new building, this will allow the game to spawn the correct loot into the right places, such as food into kitchens, clothes into bedrooms, medicine into bathrooms etc. At the top of the window, click on Buildings and then Rooms (or you can use the Rooms icon on the toolbar). In the small window that popped up. click on the + in the bottom left to add a new room type. On the right you can now give your new room a name which can be anything you want, and an internal name, which MUST match one of the names in this list: You can now draw your new room on the tile grid by clicking and dragging with the left mouse button (make sure the Draw Room tool is selected at the top of the window). Notice how the colour of the tiles turns to the colour you selected for your room in the previous step. Once you let go of your left mouse button your room will appear. You can change the shape of the room by clicking and dragging more pieces that connect up, or by holding CTRL and clicking/clicking and dragging to delete parts of a room. You will see that placing tiles of the same room type next to each other will automatically delete the internal wall between them, and placing tiles of different room types (e.g. living room and kitchen) next to each other will maintain the internal walls. You can create new internal walls (or delete internal walls) using the Place Wall tool (located to the right of the Draw Room tool). Simply click on the Place Wall icon, select the tiles you want to use for it's interior and exterior facing walls as well as grime etc and then left click and drag your wall on the tile grid, right clicking on a wall you place will delete, to edit it's length, left click on one of its "ends" and drag. So now you've finished placing the rooms for your ground floor you probably want to place some windows and doors. Click on the Place Doors tool at the top left of the window, then using the tile and furniture menu on the right, use the Doors and Door Frames options to select the door you want to use, then simply click on the tile grid where you would like the door to go. Exactly the same method is used for placing windows, except using the Place Windows tool at the top of the window instead (located to the right of Place Doors). You've now placed your windows and doors, but maybe you realised that your building is 1 tile too wide and you need to make it smaller. Just select the Draw Room tool, hold CTRL and click and drag on the area you want to delete. That worked, but your doors and windows that were on that side of the building are now floating in thin air, 1 tile out from the "new" wall. You can easily get around this by selecting the Select and Move Objects icon at the top of the window, then clicking and dragging the area select over the doors/windows etc you want to move, then clickng and dragging one of the rectangles at the base of one of the objects, all objects will move together as one, making bulk/mass changes easier to deal with. Now it's time to place some furniture down, simply use the Tiles and Furniture menu on the right of the window to browse through and select the furniture piece you want, then at the top of the window the Place Furniture icon should now be clickable, once selected simply left click on the tile grid where you would like your furniture to go. Right click will delete a previously placed piece. You will notice that items will automatically orient themselves to have their backs to the wall if placed against one. If put up against 2 walls (such as the corner of a room) you can change its' orientation by moving your mouse cursor within the tile it's to be placed on. You can also select the orientation of furniture by holding the left click down as you place it and moving your mouse round, once in the desired orientation, simply let go of the left mouse button. If you are placing multiple objects on the same tile then the last object added will be drawn on top, so if you want to have a chair on top of a rug, make sure you place the rug first and then the chair. Your ground floor is complete, now it's time to add some stairs and a first/top floor. Click on the Place Stairs icon on the toolbar at the top of the window, select the stairs you want to use in the Tiles and Furniture menu on the right and then left click on the tile grid where you would like to place your stairs. Right clicking on previously placed stairs will delete them. Now click on the Floor icon on the toolbar, this will pop up a new window that lists the floors of the current building (currently only Floor 1). Click on the blue + icon to add a new floor, you should see that it has added Floor 2 to the list, above Floor 1, click OK. Now that you are back to the tile grid you will notice that your building currently looks darker, however if you look at the toolbar you will also notice that the floor icon has changed (now reads Floor 2/2), indicating that you currently have your new floor selected, and any room/items you place will be on this floor. You can now place rooms and furniture etc like before (making sure the correct tool is selected in the toolbar), notice that when you add a room that sits above your previously placed stairs on the floor below, BuildingEd will automatically "cut holes" in the floor to allow the player to move between floors. If any of your lower floors are not covered by rooms on higher floors then don't forget to add some roof pieces over the gaps. To do this, navigate to the floor above and then click on the Place Roof icon in the toolbar and select a roof type (e.g. Flat Top), then on the right of the window select Roof Tops (or Caps/Slopes depending on the roof type being used) under Tiles and Furniture and select a roof tile to use in the area below. Then click on the tile grid where you would like to place the roof tile (e.g. a flat roof tile to cover a ground floor room is placed on the "floor" of the next floor up). When you want to add a roof to your top floor, create a new floor using the Floor icon like before, then select the Place Roof icon in the toolbar, select the type of roof tile you want to add and place on that new layer. Flat roof tiles are by far the easiest to add, bu the prettier sloped roofs can be figure out with a little bit of trial and error, again using right click to remove any previously placed pieces, just remember to have the correct roof type selected in the Place Roof tool depending on what tile you're trying to add. Finally you might want to add detail around the outside of the house such as gardens and paths. To do this, first click on Tile (underneath Iso) on the left side of the window, you should notice that the options on the right of the window have changed. At the top right is a list of every layer, ticked layers have all tiles placed on that layer visible in the tile grid, un-ticking them makes those tiles invisible, allowing you to hide the buildings walls when placing flowers or ground tiles for example. At the bottom right as a list of all of the different tiles you can use. Click on the category and then the desired tile on the right. Left clicking on the tile grid will place the selected tile on the selected layer, overwriting any tile that is already at that location and on that layer. Hold CTRL and left click to remove a tile from the currently selected layer. Lastly you will need to add a room definition for any full tile roof peice that is not over an internal room of your building. This is to allow the new roof occlusion system to function correctly. For any bits that are above an internal room, simply make sure that room has a room definition (all room in buildings should, even hallways etc). If the roof bit is over an outside area (such as a porch) then instead of giving it an internal room definition, which could possibly mess with loot tables etc, use the new room definition made for this situation - emptyoutside. In the example below you can see that this building has a porch roof outside the front door, all other bits of roof are already over a pre-existing room definition and so we don't need to worry about them. We do need to add an emptyoutside room definition on/under the porch roof however as there currently is no room definition outside the building. In this example, the porch roof is on the roof layer of floor 2. If we check Ortho view you can see that a room definition of emptyoutside yellow) has been applied to the corrosponding tiles on floor 2. If you're having problems getting it to work properly, remember: every "full tile" roof peice (the little overhang peices you see in the example above do not need to adhere to this rule, just leave them as is if you have any) must be "over/on" a room definition, so make sure every room in your buildings has a room definition (including hallways etc). Add a room definition of "emptyoutside" (without " ") to any full tile roof peices that do not sit "over/on" an internal room definition. Now your building is complete, its time to save it. If you havn't already, create a folder inside you TileZed folder called buildings, you can create any number of sub-folders in here to help organise your buildings if you like. Now, in BuildingEd, click on File and Save As, navigate to your buildings folder, give your building a name and save it. To make life easier when creating similar buildings in the future it's a good idea to save your buildings template, so when you create a new building you can select it's template and have all of your room definitions, wall tiles etc already set up for you. To do this, click on Building and the Properties, here you can see the default tiles that will be used on any building created with this template. To the left is also a button for checking/editing the room definitions. Clicking on Save Template will ask you for a name and then save it to the list of templates. As you can see you can quickly edit and create multiple templates rather fast using this method. - How to add buildings to your map Spoiler If it's not already open, open WorldEd (open TileZed, clikck Tools and then WorldEd) and load your previously saved map. You can now edit your map by double clicking on one of the cells, it will open a new tab (named cell x,x) containing a preview of what that cell will look like in game. You can use the sliders to navigate the camera around the map as well as holding down control and using your scroll wheel to zoom in/out. To the right of the preview window you will see a couple of areas, one labeled "maps" and one labeled "history", in the maps section, navigate to your buildings folder, you will see all of your buildings listed as tbx files (you can create multiple folders within the buildings folder if you like to help organise your buildings to make them easier to find). All you need to do now is click and drag a tbx from the section on the right onto the preview window (make sure "Select and move lots" is selected on the toolbar at the top of the screen), you will see the building moving with your mouse cursor over the world, just drop it wherever you want it to go. Once you have placed all the buildings you want on this cell click on File and then Save and then close the tab (named cell x,x). You should now be back to seeing your entire map. You can now repeat the process for each other cell. Once you are finished adding buildings (you can always add more later if you want to start off small and test a few things first) come back to the world view and save your map. Step 4) Exporting and testing the map- Exporting Spoiler Before adding world detail such as lamposts, road markings, road signs etc you probably want to load your map up and run around in game to make sure everything is as you want it because any world detail changes you make will be lost if you need to make edits to your BMP files and re-import them into WorldEd. The first thing you are going to need to do is add a spawn point (or more) on your map. To do this you will first need to create a spawnpoint.lua file, just navigate to the folder you created when you imported your BMP's into WorldEd (e.g. MyMapMod) which by default will have been created in your TileZed folder. Once there create a new text document, open it and then click on save as, change Save as type to All files, name it spawnpoints.lua and click save. Then open WorldEd and load your map, double click on the cell you want to add a spawn point to, once it opens, click on the "add spawn point" tool at the top of the window and click on the map where you want your spawn point to go, it will place down a prism to allow you to keep a visual track of your spawn points as well as opening a dialogue box to select the profession that can spawn here (if no boxes are ticked then nothing will be added to the spawnpoints.lua file when you write spawn points). Once finished, save the cell, come back to the world view (close the cell's tab) and click on File and then Write Spawn Points, on the dialogue box which pops up, navigate to and select the spawnpoints.lua you created above and save. Once you have created your spawn point(s), save your map then click on File and then Genrate Lots>All Cells. Here you will be asked for 4 things, the first being the directory your lot files will be saved in, click on the 3 dots and navigate to the folder you created for your map mod when you imported your BMP into WorldEd, then right click and create a new folder called Lots, select this folder. Secondly it needs your zombie spawn map, just click on the 3 dots and navigate to your zombie spawn map and select it. Third is the Tile Definitions folder, again click on the 3 dots and this time navigate to your Project Zomboid Steam Install folder (c:\Program Files\Steam\SteamApps\Common\Project Zomboid), click on the Media folder and then click Select Folder. The last thing is the World Origin. If you are making a stand alone map which is not connected to any other maps then you can just leave this as is. If however you are wanting to add your map to an exisiting world or overwrite a cell(s) in an existing world you will need to change these values. The cell of your map that is at 0,0 (the one furthest to the north west) will be given the values you use here, allowing you to offset your map to make existing maps bigger or overwite cells of an existing map. Once ready, click ok - Getting it in game Spoiler OK now you have all of the files you need to test your map in game, so lets go ahead and do that. First, create a new folder on your desktop (or somehwere easily accesible) and give it a name (e.g. MyMapMod), inside create another folder called media, inside there create a 3rd folder called maps and then inside there, create a final folder called MyMapMod (or whatever the name of your map is). Inside this final folder is where you want to put all of the .lotheader, .lotpack and .bin files that were created when you generated the lots for your map, as well as the spawnpoints.lua file and and objects.lua (dont worry about this for now, you will create one when you add foraging zones later). You also want to create a text file(it will actually be saved as a .info file), using Notepad, in this folder, called map, include the following: Spoiler title=Your map name here lots=Muldraugh, KY description= Your map description here (in this example were adding/overwriting cells in the base games map, but all the files will be kept seperate so the mod only appears when selected in game(hence the lots=Muldraugh, KY)). Click on File and Save as, now instead of saving it as a text file, at the bottom, select Save as type and choose All Files, then name the file The next file you need in this folder is a PNG file called thumb.png, this is the thumbnail used in the games menu for your mod, for now you can just create a blank one using your paint program and save it in this folder. From this folder, navigate up 3 folders until your in the first one and can see the Media folder, in this first folder, alongside the media folder you want to create 2 final files, the first is a file, again just create a txt file (saved as .info instead of .txt) this time called mod and include this info: Spoiler name=The Name Of Your Mod Here id=The Name Of the First Folder You Created Here (e.g. MyMapMod) description=Description Of Mod Here poster=poster.png The very last file you need is another png, just copy your thumb.png you created a little earlier, paste it here and rename it to poster.png All that's left to do now is drag and drop (or copy and paste) that entire folder structure into: C:\Users\YourUsernameHere\Zomboid\mods Then load up Project Zomboid, click on Mods, enable your mod, create a new game and select your map on the world selection screen. You should find yourself spawning in on one of the spawn points you created earlier. If you want to give players the option to spawn at one of the games vanilla locations (Muldraugh, West Point, Rosewood) as well as your own, then you will want to create one more file alongside your spawnlocations.lua called spawnregions.lua, which includes this code: Spoiler function SpawnRegions() return { { name = "Muldraugh, KY", file = "media/maps/Muldraugh, KY/spawnpoints.lua" }, { name = "West Point, KY", file = "media/maps/West Point, KY/spawnpoints.lua" }, { name = "Rosewood, KY", file = "media/maps/Rosewood, KY/spawnpoints.lua" }, {name = "My Map Mod", file = "media/maps/MyMapMod/spawnpoints.lua" }, } end This will show a spawn location pop up in game after selecting your mod as the game world for your new game, in this case allowing the player to select between one of the 3 vanilla locations or the location(s) you set up when you created your mods spawn points. Step 5) Adding world detail Spoiler Now that you have had a run around your map in game and are happy with the layout, vegetation, bulding placement etc it's time to start beautifying your map by adding detail. To start, open TileZed and then open WorldEd, load your map. Right click on the cell you want to add detail to and then click on "open in tileZed". Bring TileZed to the front (or minimise WorldEd) and you will notice you have a zoomed in view of that cell. In map window to the right of the screen, click on the layers tab halfway down, the window above should populate with a number for layers with different names, these are what you will use to place your various bits of detail, allowing you to stack multiple things on top of each other without overriding the previous one (such as road markings on roads, trees on tiles with grass etc). Below this will be a tilesets window listing all of the different tilesets currently used in game, clicking on one of the names will display its contents directly to the right, as you will see, most tilesets have multiple tiles. Adding detail to your world is simply a matter of finding the item you want to place from the tilesets, making sure you're on the correct layer (so placing a tree wont delete the ground tile etc) and then clicking where you want to peice to go (making sure the stamp brush tool at the top of the window is selected). There's a lot of useful tools listed along the top to help you, such as undo and a rectangular select to allow you to copy and paste areas of detail, for example, simply place down some road markings from the street_trafficline_01 tileset on to the FloorOverlay layer, then select the Rectangle Select tool, select the cells with the road markings on, press CTRl+C and then CTRL+V, now you can click away, placing copies of that area (only tiles on the currently selected layer) with a single click, allowing you to place large amounts of detail rather quickly. Once you are finished adding detail to your cell, click on File and Save then close the tab. You can now go back to WorldEd and repeat the process with each other cell, once complete come back to WorldEd, click on File and Generate Lots. Your world detail has now been saved and can be seen in game. Any time you make changes to your map and want to test it in game you will want to re-copy all the .lotpack, .lotheader and .bin files along with your spawnpoints.lua and objects.lua into the folder structure you created in the step above "Getting It In Game", overwriting old files as you go, then copy into: C:\Users\YourUsernameHere\Zomboid\mods as you did before, again overwriting if asked. Step 6) Adding foraging and vehicle zones Spoiler Find the .pzw file for your map mod (generally in the parent folder to your mods .lot files) and open it in a text editor (e.g. Notepad). Look for the line(s) that starts with "<bmp path= ...", after the last one, paste this chunk of code: Spoiler <objecttype name="TownZone"/> <objecttype name="Forest"/> <objecttype name="DeepForest"/> <objecttype name="Nav"/> <objecttype name="Vegitation"/> <objecttype name="TrailerPark"/> <objecttype name="Farm"/> <objectgroup name="TownZone" color="#aa0000" defaulttype="TownZone"/> <objectgroup name="Forest" color="#00aa00" defaulttype="Forest"/> <objectgroup name="Nav" color="#55aaff" defaulttype="Nav"/> <objectgroup name="DeepForest" color="#003500" defaulttype="DeepForest"/> <objectgroup name="Vegitation" color="#b3b300" defaulttype="Vegitation"/> <objectgroup name="TrailerPark" color="#f50000" defaulttype="TrailerPark"/> <objectgroup name="Farm" color="#55ff7f" defaulttype="Farm"/> Save the file and close it. Open TileZed and then WorldEd and load your world, dbl click on the cell you want to add foraging to. Click the "create object" button at the top of the window. At the bottom of the window you will see 2 selection boxes ("Level: 0" and "Obj Grp: <none>") Click on "Obj Grp <none>" and you will see the list of foraging zones you can add to the world. Select the type you want, you can then draw a rectangle on the game world by clicking and holding left mouse button. You can add multiple rectangles of any type and size to each cell, allowing you to be as specific or general as you want. Once done, save the cell, close it and move on to the next. Adding vehicle zones is very similar to adding the forging zones. Simply add the following code to your map mods' PZW file the same way as you did for the foraging zones above. <objecttype name="ParkingStall"/> <objectgroup name="ParkingStall" color="#85929e" defaulttype="ParkingStall"/> List of vehicle zone names to use in WorldEd: bad good medium sport farm junkyard trafficjams trafficjamn trafficjame trafficjamw rtrafficjams rtrafficjamn rtrafficjame rtrafficjamw police ranger fire mccoy fossoil postal spiffo radio ambulance burnt The first group is the most common type of vehicle zones used. The second group are for traffic jams pointing in specific directions to immitate the flow of traffic. The ones prefixed with r will spawn less than the regular trafficjam zones. The third group are specific zones for the type of vehicles listed, they are still also spawn random cars but will also spawn the vehicle listed. The final one will add random burn out vehicles. Vehicle zones should be placed as a multiple of 4x3 tiles (4x3, 8x6, 28x3 etc) with 4x3 being a single vehicle, 4 being its side and 3 being its front/back. Once done, load your map mod up in WorldEd, open a cell and add your new vehicle zones as you would foraging zones. Whenever you add a zone you need to use the objects panel on the left of the WorldEd window to give the zone a name (use the names listed above) that will be visible in WorldEd as a tag over the zone, making it easier to keep track of what you have placed where, if these are left blank then the game will default back to grabbing random vehicles from the ParkingStall zone. Example: After you have added vehicle zones to all of your cells, save your map. If you are having trouble with your vehicle zones, you can always take a look at the vanilla objects.lua within the muldraugh folder of your zomboid install, once opened just search for "ParkingStall" to see examples of vehicle zones used in the vanilla vehicle branch. Once all cells have had their foraging and vehicle zones added close any cells left open so you are back to the main world overview in WorldEd. Click on File and the Generate Lots>All Cells. If they aren't already then make sure your path to your lots directory and zombie spawn image are complete. Then for your tiles definitions folder you want to point that to the media folder inside your Project Zomboid installation folder (steam>common>... etc). Once done, click ok. Click File and then "Write spawn points to lua", then click on File and click "Write objects to lua". Step 7) Uploading to steam workshop Spoiler Create a folder (anywhere for now, desktop is handy) with the name of your mod (e.g MyMapMod), place your mods preview picture (named preview.png) and a .txt file called "Workshop" which includes the following code: Spoiler version=1 title=Your Mod Name Here description=Your mod description here description=Second line of your mod description here (you can add more description= lines if you like) tags= visibility=public then save the file. Within the same folder as these 2 files create a new folder called "Contents", and inside the Contents folder add another folder called "mods". Inside this folder is where you want to copy and paste your mods main folder (the one you have been placing into c:\Users\Yourusernamehere\Zomboid\Mods when you test your mod in game). Once this is done cut/copy/paste the entire folder structure into your C":\Users\YourUserName\Zomboid\Workshop" folder and load up PZ. Click the "Workshop" button towards the bottom left and the click "create and update items", then select your mod (if it doesn't show dbl check you added it to the correct folder which will be shown at the top of the screen). Make sure the items details are correct and then press next, your mod will then be uploaded to steam workshop (wait for the upload confirmation)and should be viewable within the hour. You now have a map mod on steam workshop! Anytime you update your mod, simply copy/paste the updated files over the existing ones in your "C:\Users\YourUserName\Zomboid\Workshop" folder and follow the above step again from loading up Project Zomboid, anyone subscribers will have the update pop up in their downloads automatically. Tips Spoiler Map Image Creation: If you are using, I recommend the Selective Palette plugin. You can choose a palette of colors and all pixels in your image will be assigned to the closest color. Find it here: - Ciber Ninja More Coming Soon FAQ's Spoiler Coming Soon Other Helpful Guides Spoiler Building Making - Current Room Definitions How To Add Custom Texture Packs And Tile Definitions Blackbeard06's Video Mapping Tutorial - Thuztors Mapping Guide PDF How to Support 1x and 2x tiles How to create lootable maps for your map mod How to combine Map mods Big thanks to Capt_Paradox, Blackbeard06, Suomiboi, Thuztor and the whole modding community <3
  11. After a very long time of waiting I have decided to bite the bullet and do my own research and find out how to make a custom map for Project Zomboid. After a Red Bull fueled, grueling 3 days of research I have finally found out how to get started with making a map. I have decided that I would do the community a service and create a tutorial video on how to make a map. A complete all in 1 guide that covers all aspects of the tools and steps needed to get your creativity in gear. The video is long, but worth the watch as you will be on your way to making maps in just a little over 1 hour. I've also added skippable chapters in the video description so you can skip ahead or easily find what your looking for. ~update~ I've added another video explaining the spawnregions.lua file. It is annotated in the video with a link. This wouldn't be possible without some help from others and would like to thank Capt_Paradox, Will, RingoD123, and EasyPickens for your support! If you have any questions please feel free to reply to this topic, the youtube video channel, and or The Indie Stone Community Discord and I will try my best to help you in anyway I can.
  12. UPDATE:Tiles for 2015 didn't work for me or BlackBeard so I linked to 2014 tiles which still work. I have modified the tutorial to reflect this! If someone knows of a fix for 2015 tiles please let me know. Zomboid Mapping Instructions.txt (New Download link for Txt file Tutorial)^^^^^ This is a basic guide to get people from Veg Map to testing their Custom Map in PZ. I'm one of those people, who before I commit to something I want to understand the process to see limitations. I spent 3 days scouring the web for videos and tutorials to learn as much as I could. At which point I think I finally have a good grasp of everything up to the point of testing. I've included some links to tools and tutorials that helped me better understand this as well. Maybe later I'll pretty this up, but for now enjoy! I apologize for any typos! -------------------------------------------------------------------------------- Mapping for Project Zomboid Required: (2015 tiles that didn't work) (2014 tiles that work) (Optional if you do not want to make your own maps for layout/vegetation). Paint Program First: Create a few folders for easy access: Main Folder= Zomboid Mapping SubFolders found in Zomboid Mapping Folder: -Buildings (this is where you will store building files for the Building Editor). -Output (This is where you will find your lot files(map you made) after clicking generate lots in WorldEd). -TmxWorld (This is where your saved map from the PNG/BMP Basemap/Vegetation Map will save too). -Tiles -Tools (This is where you have your Tile Definitions from the that will be props/textures).(Extract the zip file into the Zomboid Mapping Folder,there will be a folder named Tools created, inside that folder will be another called Tiles. This Tiles folder is the one you will use for generating lot's when asked.) These instructions are going to assume you are creating a 1x1 Cell map. Step 1: Create your BaseMap(Roads,Basic Terrain). Step 2: Create your Vegetation Map (The types of Plants/Tree's and Ground Coverage your map will have) Step 3: Create your ZombieSpawnMap Your BaseMap and Veg map should be saved in PNG format. Size for a one cell map= 300x300 for both. Your ZombieSpawnMap should be saved in BMP format. Size for a one cell map= 30x30 Example File names: NewbCity.png(baselayout 300x300),NewbCity_veg.png(Vegetation map 300x300), NewbCity_ZombieSpawnMap.Bmp(Duh,Zombie Spawn map 30x30) I just used NewbCity as the example for my map project. These links will help explain the color codes to use in the paint editor to draw Base Layout map/Vegetation Map. Thuztor's Pdf file for mapping contains good color code info as well pages 5 and 6. If you want to try your hand using Mapzoid to get an idea of what it's like here's the link: Base layout colors Veg Map Colors(I would copy and paste these color palettes to your paint program and use them with the color picker tool to adjust your mapzoid file to your liking since it doesn't always work perfectly.:Thanks to Suomiboi again for his tutorial found here) Also make sure to disable anti-aliasing if you have any issues with incorrect colors (I didn't have too but some programs react differently). Wouldn't let me display the image here so if you want to copy them click on the links or scroll to the bottom of this page. Step 3:Now that you are done using mapzoid or a paint program to create those 3 files(which I would store in the main directory of ZomboidMapping folder) Load up TileZed. Go to the toolbar at the top and look for the tab TOOLS Then go down and select WorldEd. Now a new window popped open with WorldEd. Go to File in the Toolbar and select New and popup window asking the size of the map you want to create. Change it to 1 Cell Width, 1 Cell Height. Great now you have this empty grey square saying 0,0 You might notice in the upper right side of the screen it says Maps with a little window of folders. Navigate to your ZomboidMapping Folder you created earlier. If you saved your files to the ZomboidMapping folder earlier you will now see NewbCity.png. Drag this file from the window into the grey square that says 0,0. You should now see a basic view of the file you created in paint or mapzoid earlier. Great! Go to File tab in the toolbar at the top, Save as> Newbcity.pzw (or whatever your map name is you chose). Step 4: Go to the File Tab again in the toobar at the top, BMP>TMX then select All Cells. You should now have a new popup window asking you all kinds of fun stuff. The only one you should have to change is the top one for Export directory Select that and navigate to your Tmx_World folder you created in Zomboid Mapping earlier and select that. (if you click apply afterwards the window will exit saving your directory but will not complete the BMP>TMX so go through the file tab again doing the same process this time click OK). Next a window should popup saying Bmp to Tmx Sanity Check, click Ok. After a few seconds it should say Finished, Click OK. Step 5: go into TileZed and go to the File Toolbar tab in the upper left corner. Click Open, navigate to Tmx_World folder in the Zomboid Mapping folder you created earlier. Select NewbCity_0_0.tmx or whatever you saved your map as (make sure to keep the name the same across all files). Now you should be able to view your map in TileZed. Some notes: If you plan on changing your vegetation map I highly suggest you do it at this stage before you add props or details in TileZed Because when I tried editing mine afterwards I had to go back and do the BMP>TMX (close out of TileZed Reload the program and load up the file again) only to realize all of my street lines, fences and props were now gone. So make sure you are happy with your layout of roads/forests/vegetation before continuing to detail your map. This should roughly get your started mapping, maybe when I master HouseBuilding/Spawning ETC I will add that later. Step 6: Playing your map! So after all of this you have some really basic map you want to try out right? Ok, so go back to WorldED, Go to the File Tab on the toolbar in the top left. Select Generate Lots, then Select All Cells. Now a new pop window has started. Lots Directory: This is where your map files will save, select the folder we created earlier in Zomboid Mapping called Output. Zombie Spawn Map Image: This is the 30x30 NewbCity_ZombieSpawnMap.bmp you created earlier (or whatever your map is named) it should be in the Main Zomboid Mapping Folder. Tile Definitions: This is all those wonderful images/props for your map which should be located in the Tiles (tools/tiles is where they are now located)folder you extracted to earlier in Zomboid Mapping earlier. (note:Depending upon how you extracted it there might be a Tools\Tiles folder inside of the tiles folder you created earlier).<<<<<< This might explain why even I was confused about the 2015 tiles and the 2014 tiles. So make sure you use the 2014 from World Origin: This tells the game what area of the Zomboid Map you are claiming for your cell. Note( Go to and on the left side click Map Coordinates. Now you will see it say Example: Cell 35x32 which is main st Muldraugh you obviously don't want to cover over a part of the map that has a town in it, so scroll around and find a nice spot where there isn't a a lot of stuff (clear land or forest)). Write down the cells you want and input them into the World Origin and click OK Now all the map files are compiled to the output folder in Zomboid Mapping. Step 7:Now you have to make it a mod. Go to the C:\Users\(your user name\Zomboid\Mods folder. In this folder you will notice another folder called examplemod, you can use this as a template to create your new map mod. So under the Mods folder create a new folder for your map named after your map. New Folder in Mods= NewbCity Inside the NewbCity Folder you will need to create another folder called media. Inside the Media Folder you will have to create another folder called maps. Inside the Maps folder you will have to create another folder called NewbCity (yes again!) Inside the 2nd Newbcity folder there should be the following: 0_0.Lotheader (0_0 is the World Origin you picked earlier so if you choose cell 35x32 it would say 35_32.Lotheader) Chunkdata_0_0.bin (again 0_0 is just an example for your world origin) World_0_0.lotpack (again again 0_0 is just an example) These 3 files are the files that were created in your output folder after you went through generating lots in WorldEd, you should copy them here. the other required files are: Description.Txt = NewbCity - Population ~750 <LINE> <LINE> (V1.1). U=BTL <Note>>:I figured this out but looking at New Denvers Files so I modified them to test my map, just change it to your map name.> file looks like this: title=Newb City lots=Muldraugh, KY description=Newb City - Add a short description of your map here Spawnpoints.lua : This file will designate where your player spawns in the game based on character occupation Updated because I was missing a closed bracket - Ty Blackbeard function SpawnPoints() return { constructionworker = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } }, fireofficer = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } }, parkranger = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } }, policeofficer = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } }, securityguard = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } }, unemployed = { { worldX = 38, worldY = 26, posX = 180, posY = 180, posZ = 0 } } } end You will notice that WorldX and World Y refers to which cell. You will also notice posx and posy refers to the tile in your cell/map. If you look at your map in TileZed you will see in the bottem left corner numbers like Example:180,172 These are your tile coordinates. So find a tile you want to spawn and write down the numbers. Now modify that file for which cell you picked earlier on the PZ map under worldx and worldy Now modify that file for which tile you picked on your map in TileZed under posx and posy Save the file and now you character will spawn in the spot you chose. The next file in the folder will be: Thumb.png This is just a screenshot for your map, you can steal the one out of New Denvers to use as a placeholder for now if you want till you have your own. So let's recap: Inside of the last NewbCity folder you need: 0_0.lotheader Chunkdata_0_0.bin World_0_0.lotpack Description.txt Spawnpoints.lua Thumb.png Make sure you have all 7 files. Ok now go back to the Mods\Newbcity folder (the first newbcity or your mapname folder with the media folder in it). There should be 2 files in here: (this is another file to describe your map) Poster.png (Another screenshot photo) contains this: name=NewbCity id=NewbCity description= This is NewbCity for newbs trying to map. poster=poster.png If you want to get rolling you can modify the files in the examplemod folder to make it easier. If you want a better understanding of these files I suggest you download NewDenvers map to take a look at this link: Step 8: Load up Project Zomboid Go to mods in the bottom left corner and go to NewbCity(or your map name and activate it) Create a single player game and you will see your Newbcity(or your map name) as a spawn location. Join the game and you will notice that you spawned at the location you designated earlier in the spawnpoints.lua file. Play your barren wasteland of a map and enjoy! Big thanks to EasyPickins, Blindcoder, Thuztor, Suomiboi, Mendonca for their tools and tutorials which helped me make it to testing my own custom map. Courtesy of BlackBeard! Great comprehensive tutorial!
  13. I made some posts in the Hydrocraft mod thread showing the java behind melee combat and some quick thoughts on it. See here and here I am going to use this thread to summarize my findings, so others can use them as a reference. Firstly: Skill modifiers and weapon categories. What do they affect? By how much? If the weapon has the category "Unarmed", no perk related. The only calculation for unarmed is that it is capped at 0.7 damage per hit. NOTE MODDERS: This means if you categorize a weapon in your scripts as unarmed, putting max damage higher than 0.7 does nothing. These are not intuitive at all. Rather than either starting at 100% damage and increasing (bonus damage) or starting at a low point and reaching 100% at level 10 (competency), skills in project zomboid are a mixture of both. If the weapon has the category of "Blade" or "Axe", use Blade Accuracy perk (java name=PerkFactory.Perks.Axe): If the weapon has the category of "Blunt", use Blunt Accuracy perk (java name=PerkFactory.PerksBlunt): Both Axe and Blunt perks affect damage the same way. 0:30%, 1:40%, 2:50%, 3:60%, 4:70%, 5:80%, 6:90, 7:100%, 8:110%, 9:120%, 10:130% Or, to put it more compactly: Damage = TotalDamage*(0.3+PerkLevel*0.1) If the weapon is "Ranged" (not category), Aiming level affects critchance, not damage. The calculation is weapon.critchance + weapon.AimingPerkCritModifier * (AimingLevel/2) So for calculating the maximum crit of you custom guns, add the amingcritmodifier only 5 times, not 10. Lastly calculated, If the weapon has the category of "Axe" and the target is NOT knocked over. Double damage. Yup, axes do double damage to all standing targets. ORDER OF CALCULATION None of these calculations are exclusive! Furthermore, none of the melee checks actually restricts themselves to melee weapons. So, if you have a firearm (isRanged=TRUE) with the categories Unarmed,Axe,Blunt, and you attack a standing zombie, the following would happen. Get damage from weapon/wielder. If damage is more than 0.7, reduce to 0.7 (unarmed). damage *= 0.3+AxeLevel*0.1 damage *= 0.3+BluntLevel*0.1 critical chance = weapon.critchance + weapon.AimingPerkCritModifier * (AimingLevel/2) damage = damage*2 (Axe) There may be checks earlier in the code to prevent such items from existing at startup, but I know you can make these with lua. NOTE: I have yet to find any references to "improvised" in the code. I'll keep looking. Next time, Strength, endurance, push back, knockdown, and YOU!
  14. Hey Folks, i tried the last hours to set up a linux server for Project Zomboid and it was very difficult to find some usefull informations, because all of it was very old. So i want to share my short solution of setting up the server successfull at the end. The instruction is for users with basic to advanced knowledge about linux. 1. Open the ports of you Router for UDP/TCP: 16261 bis 162XX (XX = 61+<number of players>) 8766 bis 8767 27015 (TCP should be enough) 2. install steamcmd and login (for login: "login <username> <password>") Follow this instructions: 3. after login insert: "app_update 380870 validate" 4. go to the PZ folder in Steam/steamapps/common/... or where you forced the installation to. 5. "./" (give it some time, the process is not ready in a few seconds) 6. insert and confirm an admin password and wait until the process shows "Server Started" (or something like this) 7. shut it down and go to the folder: /home/<user>/Zomboid/Server/ 8. edit servertest.ini (more or less important stats: MaxPlayers / RCONPassword / Password / server_browser_announced_ip; If you want to host a public Server, you need to edit the PUBLIC stats) 9. start the server with "./" again. You should be able to connect now 10. optional: start/stop Script to start the server, create a new file with a name like "" and insert (Maybe you need to create the "output" folder in you user-space first): #!/bin/bash nohup ./ &>/home/<user>/output/zomboid & disown and to stop the server create "" and insert: #!/bin/bash TEST=`ps -e | grep ProjectZomboid6 2>&1` kill $TEST | cut -d' ' -f1 If you have any questions, hints or improvements, tell me
  15. BayCon (Also known as El_Buhdai, or Ɛɭ Ɓʊɧɖąį) Presents... Something I had been meaning to write for awhile but never had the time... A guide so extensive, that it should be highly referred to... Ɛɭ Ɓʊɧɖąį~βαɣƇᴑŋ's Extensive and Comprehensive Guide to Surviving The Zombie Apocalypse [WIP] Pre-Introduction Introduction My goal with this is to make an almost fool-proof, community-made guide to surviving long amounts of time in Project Zomboid. I want it to cover almost every possible scenario, with steps and tools for how to stay alive when faced with as many specific dangers as possible. Clearly, I can't do this completely by myself, so your feedback, additions, and personal experience would be greatly appreciated as we try to make the very best Project Zomboid Survival Guide Available! Introduction The moment you start up a new game in Project Zomboid, you've already lost. You won't survive. There is no hope at all, no reason you should believe that you will make it in the new world of death that you are placed in, but does that mean you should give up? Hell no! You may not be able to survive in Project Zombod, but you can at least extend your poor little character's life for as long as possible, and here's how. Let's get started. 10 Things You Will Need To Survive Where Others Would Surely Perish... 1. A sharp mind and quick wits 2. Knowledge that, no matter what your situation is, you are never safe from your inevitable death 3. A constant sense of constant caution, without ever getting cocky 4. The right equipment and the know-how to use it effectively and efficiently 5. Effective and efficient ways of getting what you need and don't have 6. The ability to think ahead about how your current actions, no matter how big or small, will affect your character down the line 7. Some level of stability, or at the very least a strong system or process for living on the run. 8. (Harsh Multiplayer Only) The ability to outsmart other players, and use their lives as potential sacrifices for you or your group's. 9. Strategy and the motivation to plan for tomorrow, today.. 10. Just good ole' fashioned, good friggin' luck... You Can't Know How To Survive, Unless You Know All the Ways You Can Die It only makes sense, right? Know all the ways you can die, and figure out every possible way to prevent those things from happening. Simple, right? Well, not quite. Here are a list of as many possible ways you can die (If I miss something or add one that isn't true, I would appreciate it if you would let me know.). There are plenty of ways you can die in each of these categories, but I wanted to keep them small in numbers and go into more detail with each of them individually. They are bound to change due to feedback, here they are.. [Zombies + Zombie Infection] [illness + From Food + From Tainted Water] [Non-Zombie-Related Cuts, Gashes, and Wounds + Infection + Blood Loss] [Fatal Burns] [Fractures and Broken Bones, Falling Too Far] [Lack of Food And/Or Water] [Other Players + Peer Player-Inflicted Injuries]
  16. Steam Server Setup (QUICK TUTORIAL)

    A one minute six second guide to set up a PZ Steam Server! (not sure how to make it visible here.) Don't forget to PORT FORWARD!
  17. How ZombRand() works.

    ZombRand() is used in many mods to get random numbers. However, many are using it incorrectly, and because it returns a random value, they are not realizing they have a bug. The most common problem I have seen is when code is written similar this; n = ZombRand(2);if n == 2 then....else....endn == 2 will always be false as ZombRand(2) will never return 2, only 0 or 1. What is ZombRand(n)? ZombRand is an exposed implimentation of rand.Int(n) with a couple of changes. What does it do? Given value n, ZombRand will return a pseudo random number from the set of INTEGERS from 0 to n-1 inclusive. Why ask for n if it only gives up to n-1? The n in ZombRand(n) is not the maximum value wanted, but the range of the result wanted. For example, ZombRand(4) can return 0, 1, 2, or 3, which is exactly 4 values. If you desire results from 1 to n just do foo = ZombRand(n)+1;Special Cases ZombRand(0) is always 0 ZombRand(-n) = -1*ZombRand(n) Hope that clears some things up!
  18. Type = Normal,There are various types of items in Project Zomobid, below you will se each of them with a short description. Normal – A basic item. Drainable – An item that has a certain amount of uses before it's destroyed Food – An item that can be consumed by the character Weapon – An item that can serve as an equpable weapon. Container – An item that can store other items inside it. Clothing – Item worn by the player character. Literature – A readable item like a book or a newspaper. Weight = 1,The weight of an item as seen in-game, it should be a sum of weight + size of the item.Typically used in Item Type: All DisplayName = Example item,Defines the name of the item as displayed in gameTypically used in Item Type: All Icon = ItemIcon,Defines the icon the item will have in-game, the .png file of the icon should be in media/textures folder of the mod and the name must look like this Item_ItemIcon.pngTypically used in Item Type: All UseDelta = 0.1,Defines how many uses a Drainable item has, if it's 0.1 the item will have 10 uses before it's depleted.Typically used in Item Type: Drainable Capacity = 20,Defines the maximum carrying capacity of the container.Typically used with item Type: Container CanBeEquipped = Back,Defines the clothing slot the item is equipped in, typically only used for containers in the form above. BodyLocation = Bottoms,Defines what part of the body a Clothing item is worn on. Can be Bottoms, Shoes or Top Temperature = 8,Defines the temperature resistance a Clothing item gives to the player when worn. CanStoreWater = TRUE/FALSE,Defines if the item can be used to store water. Defaults to FALSE if not used.Typically used in Item Type: Drainable IsWaterSource = TRUE/FALSE,Defines whether or not the item is a source of water. Defaults to FALSE if not used.Typically used in Item Type: Drainable UseWhileEquipped = TRUE/FALSE,Defines if the items has to be equipped in Primary or Secondary slot in order to be used. Defaults to FALSE if not used. ReplaceOnDeplete = Module.ItemID,When the item is depleted (Has no uses left or if you've eaten\drank all of it) it will be replaced by Module.ItemID ReplaceOnUseOn = WaterSource-WaterBottleFull,If the item is used on something it will turn into something else, in the case above, if used on a Water Source (Item\Water Barrel\River) it will become WaterBottleFull IsCookable = TRUE,Defnises whether or not the item can be Cooked using Fire Pits, Stoves or BBQ. If the item is cookable and stores water, it can be used to boil it to remove the tainted water effect. Defaults to FALSE if not used. DangerousUncooked = TRUE,If TRUE, eating the food item without cooking will result in it having a semi-poisonous effect. HungerChange = -20,Defines how much hunger will be removed upon consumption, if the value is Positive, consuming the item will make the character more hungry. ThirstChange = -20,Defines how much thirst will be removed upon sonsumption, if the value is Positive, consuming the item will make the character more thirsty. StressChange = -20,Defines how much stress will be removed upon sonsumption, if the value is Positive, consuming the item will make the character more stressed. UnhappyChange = -20,Defines how much happiness will be removed upon sonsumption, if the value is Positive, consuming the item will make the character more unhappy. BoredomChange = -20,Defines how much boredom will be removed upon sonsumption, if the value is Positive, consuming the item will make the character more bored. FatigueChange = -20,Defines how much fatigue will be removed upon sonsumption, if the value is Positive, consuming the item will make the character more tired. EnduranceChange = 20,Defines how much endurance will be removed upon sonsumption, if the value is NEGATIVE, consuming the item will make the character more fatigued. Alcoholic = TRUE,If TRUE consuming the item will make the character drunk. If used for Bandage items, it will act as disinfectant. DaysFresh = 6,Defines the amount of days before a food item starts to rot. DaysTotallyRotten = 10,Defines the amount of days before the food item rots completely, becoming poisonous. MinutesToCook = 40,In-Game Minutes before the item is cooked, use with Cookable = TURE, MinutesToBurn = 110,In-Game Minutes of Cooking the item before it becomes Burned. Poison = TRUE,Defnines if the item is poisonous upon consumption. PoisonDetectionLevel = 1,Unknown, probably defines the difficulty of detecting poison if used in Evolved Recipe. PoisonPower = 5,Defines the power of poison, the higher the value, the more lethal it is upon consumpion. 5 Is PoisonIvy (White Berry) 45 is Bleach level. UseForPoison = 1,Unknown, possibly amount of PoisonPower goes into Evolved Recipes. FoodType = Fruits,Unknown, no known use as of Build 32 AlwaysWelcomeGift = true,Unknown, no known use as of Build 32 CustomContextMenu = Take,Will replace "Eat" text in the context menu for food items. EvolvedRecipe = Stew:3;Pie:3;Soup:3;Sandwich:3;Salad:3;Roasted Vegetables:3,Item can be used in Evolved Recipes, in the above case, it could be used in Stew, Pie, Soup, Sandwitch and so on... DisplayCategory = Ammo,Will be displayed as the item's category, can be anything but custom Categories need a Translation file. CanBandage = true,If TRUE the item can be used as a Bandage for wounds. BandagePower = 4,Defines how good a bandage is, higher values make the bandage last longer before it goes Dirty. ReduceInfectionPower = 50,If used, it will reduce infection (NOT Zombie Infection, it reduces regular wound infection, it might slow down zombie infection though, uncofirmed) Tooltip = Tooltip_UseOnHealthPanel,Will display tooltip if item is moused over in inventory, requires Translation file that defines the text to display. Known Preset Tooltips: Tooltip_Painkillers,Tooltip_PillsAntidepressant,Tooltip_PillsBetablocker,Tooltip_PillsSleeping,Tooltip_tissue_tooltip,Tooltip_IronSight,Tooltip_Scope,Tooltip_AmmoStrap,Tooltip_Sling,Tooltip_FiberglassStock,Tooltip_RecoilPad,Tooltip_Laser,Tooltip_RedDot,Tooltip_ChokeTubeFull,Tooltip_ChokeTubeImproved,Tooltip_Trap,Tooltip_Generator,Tooltip_UseOnHealthPanel,Tooltip_Vitamins, RequiresEquippedBothHands = TRUE,If TRUE the item HAS TO be equipped in Both Hands in order to even be carried. TeachedRecipes = Make Bread Dough,If Read the item will teach the character how to make Bread Dough, any Recipe name can be used.Typically used with Literature NumberOfPages = 260,Defines the number of pages a Skill Book has.Typically used with Literature Skill Books SkillTrained = Trapping,Defines what skill the Skill Book gives a multiplier to. LvlSkillTrained = 3,Minimum skill level required to read the skill book. NumLevelsTrained = 2,Amount of skill levels the multiplier will apply to beginning with LvlSkillTrainer. CanBeWrite = true,If TRUE the item can be used to write on if the character has a Pencil or Pen Weapon Type Only Below: MELEE/RANGED WEAPONS MinRange = 0.61, Defines the minimum range at which the weapon is effective, if the target is closer, he will be pushed away. Possibly 1 = 1 tile. MaxRange = 1.5,Defines the maximum range at which the weapon is effective. Possibly 1 = 1 tile. WeaponSprite = Fireaxe,Defines the weapon model used. MinAngle = 0.2,Unsure, defines the angle at which the weapon is effective. HitAngleMod = -30,Unsure, as above. SwingTime = 3.0,Defines the default time it will take for the swing animation to play out. MinimumSwingTime = 3.0,Defines the minimum time it will take to swing the melee weapon, affects the speed of animation and DPS. KnockBackOnNoDeath = TRUE,If TRUE the weapon will knock back the target if the strike was not lethal. SwingAmountBeforeImpact = 0.002,Defines the time from start of the swing before it makes an impact. Categories = Axe,Defines the weapon Category. Can be Blunt, Blade, Axe, Improvised, Unarmed SubCategory = Swinging,Defines the weapon Sub Category. Can be Swinging, Stab, Firearm ConditionMax = 15,Defines the maximum durability of the weapon. ConditionLowerChanceOneIn = 30,Defines the chance for weapon condition to lower when used. SplatNumber = 1,Unsure, Possible affects how many blood splats comes out after impact. SplatSize = 5,Unsure, possible affects how much blood comes out with each splat. SplatBloodOnNoDeath = TRUE,Defines whether or not blood comes out if the strike was not lethal. PushBackMod = 0.3,Modifies the strength with which the target is pushed back upon impact. MinDamage = 1,Defines the minimum damage. MaxDamage = 2.5,Defines the maximum damage. MaxHitCount = 2,Defines how many targets can be hit with a single attack. DoorDamage = 35,Defines the amount of damage done to doors. Doors have 100 HP by default. TreeDamage = 35,Defines the amount of damage done to trees. Trees have 100HP by default. IdleAnim = Idle_Weapon2,Defines the idle animation that plays when the character is holding the weapon. SwingAnim = Bat,Defines the swinging animation that plays when the weapon is used RunAnim = Run_Weapon2,Defines the animation that plays when the character runs with the weapon. CriticalChance = 20,Chance to inflict critical, lethal damage upon the target. WeaponWeight = 3,Higher values cause exertion faster. KnockdownMod = 2,Defines the knockdown modifier, higher values mean it will be easier to knock the target down. TwoHandWeapon = TRUE,If true the weapon will be most effective if equipped in both hands. CloseKillMove = Jaw_Stab,Defines the type of close kill move, used for knives and some other stabbing weapons only. CantAttackWithLowestEndurance = TRUE,If TRUE the weapon can't be used if the character is under Extreme Exertion moodle. EnduranceMod = 0.5,Modifies the amount of endurance used up when swinging the weapon. Higher values mean exertion comes on faster. Weapon Type Only Below: RANGED SPECIFICRanged weapons will use a lot of variables, if not all, used by melee weapons, below you will find variables specific for Ranged Weapons, they would probably all work with a melee weapon, you can experiment. AmmoType = BerettaClip,Defines the type of Ammo being used. To the best of my knowledge, reloading requires .lua code. ImpactSound = null,Defines the sound created after impact. SwingSound = 9mmShot,Defines the attack sound. SoundVolume = 75,Defines the volume of attack sound. ToHitModifier = 1.5,Unsure, possibly a modifier for a chance to hit the target. NPCSoundBoost = 1.5,Unknown. No use as of Build 32. Speculated boost to sound if used by NPC so more zombies hear it and come. Ranged = TRUE,Defines if the weapon is a ranged weapon. ProjectileCount = 1,Defines the amount of projectiles created by shooting the weapon. ShareDamage = FALSE,Unknown effect. IsAimedFirearm = TRUE,Defines if the weapon needs to be aimed. UseEndurance = FALSE,Defines if using the weapon uses up endurance. MultipleHitConditionAffected = FALSE,Unknown. SoundRadius = 150,Defines the sound radius, higher values cause more zombies to hear it from more far away. AimingPerkCritModifier = 10,Defines Aiming Skill Bonus to Critical Chance AimingPerkRangeModifier = 1.5,Defines Aiming Skill Bonus to Range. HitChance = 45,Default chance to hit the target. AimingPerkHitChanceModifier = 15,Defines Aiming Skill Bonus to Hit Chance. AimingPerkMinAngleModifier = 0.05,Defines Aiming Skill Bonus to Min Angle. RecoilDelay = 20,Unsure. Defines time that must pass between shots. SoundGain = 1.5,Unknown effect. ClipSize = 15,Maximum amount of ammo that can go into the weapon. Again, .lua code is required for the weapon to be re loadable. ReloadTime = 10,Defines the time needed for the weapon to be reloaded. AimingTime = 40,Defines Aiming Difficulty, lower values increase chance to hit with low aiming time. PiercingBullets = TRUE,If true, multiple objects can be hit by a single projectile if they are in the right angle. Weapon Type Only Below: THROWN SPECIFIC UseSelf = TRUE,If TRUE the item itself will be used up when attacking. PhysicsObject = Aerosolbomb,Defines the thrown item sprite. ExplosionPower = 70,Defines the power of the explosion created upon impact. ExplosionRange = 6,Defines the AoE of the explosion. FirePower = 97,Defines the amount of fire that will be created upon impact. FireRange = 6,Defines the AoE of fire. triggerExplosionTimer = 50,Defines the time before exlosion if placed. ExplosionSound = smallExplosion,Defines the sound of explosion. PlacedSprite = constructedobjects_01_32,Defines sprite used if the weapon is placed as a trap. I hope this helps anyone who wants to create their own items for PZ. Remember, this is just a list of variables, don't use all of them, it's not required. Take a look at items.txt and newitems.txt to see what variables are used by what items and base your items off that.
  19. Hey guys, This is a bit of a Work In Progress right now, but now there's a few posts up in the series, I'm open for critique. From the 5th post onwards, I'm trying a slightly different format based on feedback I received from the first 4 entries. There's more snippets of functioning code, complete working code at the end of it (also available to grab on GitHub), and a few more fully interactive demonstrations where applicable. Realmscape HTML5 Game Engines in JavaScript Blog Series Briefly: This is a blog series I've started on the components of a Game Engine, based around actually making an engine of your own in JavaScript. It was originally going to be written alongside a refactor of our near feature-complete engine, but has since taken a turn to cover things slowly and a little more thoroughly. The examples are in JavaScript, because it is reasonably close (complexity-wise) to pseudo-code, and will run on anything with a web browser. It's easy to learn, easy to translate from, and does not under-perform too badly on a range of devices. I'll update this post with new content, as I remember, and turn this into something a bit more legible when I get time. Current posts: (in order) Making an Engine, or making Games?The Basics: Development EnvironmentThe Basics: Game LoopBasic Math: InterpolationThe Very Beginning (Making a text-based interface)Human Interaction (Handling user input)Keyboard Bindings (Create reconfigurable key binds)Prototype, var, and Object oddities (WIP)Planned posts: (vaguely ordered) These will happen eventually, but after some feedback from JavaScript novices I'm taking it a bit slower than previously anticipated. The Basics: Handling User InputService LocatorThe Basics: Asset LoadingRendering: TextBasic Entities: StructurePrototype: The Engine So FarRendering: 2DRendering: 3DAI: Finite State MachinesAI: Behaviour TreesAI: PathfindingPhysics & Collisions
  20. Need Help with custom Tileset

    Hello! Have some Problems with my Tileset. I have the tileset successfully inserted into the editor and can use it there, all fine. But when start the game the object does not appear ingame. I have tryed some Tutorials but nothing work for me :/ What I've done: - Insert new Tileset 64/128 - Make Properties and save it in Editor file/Tiles/newtiledefinitions.tiles- Make Tilesset in Building Editor, so i can place it on Map. Whats next? Ingame all works, only my custom Tileset not :/ Hope anyone can help with explanation or a tutorial link for the current version of the editor. =) Thanks
  21. Buenas a todos, he decidido abrir este tema porque he buscado en el Foro y no he encontrado uno concreto (si estuviese equivocado, por favor, hacédmelo saber y de ser necesario lo eliminaré). En este Post se resolverán dudas sobre el juego, problemas y demás, claro está, en español con el fin de ayudar a aquellos que no entiendan el inglés o, por alguna otra razón, quiera postear en nuestro idioma, en cuyo caso también serán bien recibidos. Intentaré ayudaros en todo cuanto pueda, pero esto es trabajo de todos. Recordad siempre tener respeto por las demás y no usar un lenguaje violento o agresivo, porque si no, ya sabéis lo que toca. Gracias y a ver si este Post sirve para ayudar a alguien. Saludos desde España.
  22. hello community today I created a video tutorial for the creators of sprites that have issues to tilezed agreagar its objects, it is long but show the essentials for successfully add each object in the right position enjoy. Video subtitles are in Spanish so that should translate to English
  23. So I became VERY bored and decided to share what I've found out about the game trough my own playtrough. This is by the way in no special order. :!: -ALWAYS loot corpses. They do often have something valuble like bags or even an axe! -On the subject of axes, DON'T use the axe for combat unless you have to. You will have to use the axe to get planks later in you session so you do NOT want it to break. -Even after the water has been turned off you will be able to find some water left in sinks, toilets and bathtubs. Bathtubs have the most water left in them. -Don't fight zeds near windows. If you swing and break the window you are possibly going to call all the others zeds to dinner. -Checklist for main base. Two floors, not too far from the center of either west point or muldraugh, bedroom on top floor, bookcase for easier sorting of books and such. -Garbage bags should always be on the "shopping-list". You will need them for rain collectors. -Guns are a bad idea. Just don't use them.
  24. Tutorial: World Objects

    Creating and Manipulating World Objects Seen questions pop a few times regarding placing objects on the map so decided to make a little tutorial on it. Most of the tutorial is written in a single file included in a mod you can download below. The code is commented so you can see whats going on. I recommend loading the lua file in your favorite editor and starting a custom game without zombies with the mod activated in windowed mode so you can play with the mod ingame and read the stuff in the lua file. How it works? The mod allows you to place a red cube on a empty tile, every time you click that tile again the code will do some stuff with the object, you can all see it in the code comments. Target audience. The mod is written for beginning modders, however it might be that there's some stuff useful for more experienced modders here and there. You'll have to judge it yourself. Code. The code is written so that one can follow the tutorial line by line, as such it does not reflect proper implementation but rather serves as a showcase of things you can do and implement properly yourself. You can also build uppon the code supplied in the mod to use it as a testbase for experimenting with objects and their methods. I suggest also digging in TIS lua files regarding buildable objects and their context menu's. About sprites. To create a graphic for your object you'll need to make a transparent image of 64 width and 128 height. This covers one tile and one layer of height in the game. Included in the mod are a few sprites, i suppose you could use "cube_floor.png" as a template: About java. It's highly recommended you have some way of looking up java source classes & methods. The javadocs can be used, personally i've used JDGUI up until now. With JDGUI you can open any class file in <root>/zombie/ directory and it opens up the entire project space as such: Many of these classes are made available in lua to work with. Often they require to be constructed first. To do so you can look up the constructors: In lua you'll have to use the 'new' method like so: local myObj ="parameters here");By matching the set of parameters in .new() to the ones found in the java constructors you can call the appropriate one. All other methods can then be called on that instance of the IsoObject like so: myObj:setSprite("test");local sprite = myObj:getSprite();The lua file for reference Download Regards, Turbo
  25. Heya fellow survivors. In this thread I will write a tutorial series describing everything I know about moding for Build25+ so far. Please note that some of the information I supply is what I think and might not be 100% correct. I want to make this series as I want to get all the information in one place, and because I found it diffacoult to find all the information myself when I started. Part one: Folder Structure. This is the folder structure as of Build 25 through 26.mymod: file, poster.png and all the icons your mod items use goes here. (NOTE: All icons MUST start with "Item_" like so: Item_iconname.png. Note the capital I, it's important)mymod/media/lua/client: Lua files in here are executed client side.mymod/media/lua/server: Lua files in here are executed server side. (NOTE: You ARE starting a server when you start a new sp world, so world gen stuff goes here EVEN ON SINGLEPLAYER!)mymod/media/lua/shared: I don't know the exact purpose of this folder, but I have noticed that it loads before the client and server files are loaded.mymod/media/scripts: Item and recipe scripts goes in here, just plain .txt files. That's what I know about the new folder structure so far. If you have changes or want me to add stuff, feel free to post below and let me know. Part two: The file is the most important file of any mod as it is the way to get the modloader to know it's a mod.The file contains this information:name=Name you will see in the mod listposter=poster.png (This is the image shown in the mod list)id=yourmodid (This is the id which the modloader reads when it is looking for mods that may requre this mod)require=mod1id, mod2id, etc. (This tells the modloader that this mod requires mod1 and mod2 where mod1id is the id of mod1 and alike with mod2)description=A description of your mod, what does it do?url=When you make your pzmods page for your mod you can add the link here. You can then access this link from the mod within the mod loading screen. That's about it for the It may seem simple, and it is pretty simple. But it is also the most important file of your mod, so don't forget about it. Part three: Simple Recipe Mod. Next up, I will teach you how to make your own recipes in your mod.It very simple, at least the way I do it. For this tutorial we will be adding two recipes.1. Dry towel2. Dry bathtowel All you have to do here is the following:1. Find the "mymod/media/scripts" directory.2. Find/make a new file called "yourmod_recipes.txt", or a better name if you are creative, and open it in your favorite text editor.3. Now for the "coding" part (Well, as the folder suggests, it's more scripting than actual coding here ) Start by adding the module (this is basicly the id of the recipes, if you ever need to include them. In another mod maybe.)module yourmod_recipes (or a better name){ <-- Remember these, those are most important! "Recipes goes here"}Now, import the items we will be working with, as we are using items from the base game, we will include the module "base". If you use moded items, you need to requre the mods items module here.module yourmod_recipes{ imports { <-- Again. remember these! Base } "recipes goes here"}Now we are adding the actual recipes. Don't worry, it'll be over very soon.module yourmod_recipes{ imports { Base } recipe Dry Towel <-- Recipe name, this will apear in the inventory when we rightclick a wet towel. { <-- And once again. remember these for each recipe DishClothWet, <-- Requires a wet towel, you can check the "Steam\SteamApps\common\ProjectZomboid\media\scripts" for item files in which the items are listed. Result:DishCloth = 1, <-- As you might have guessed, this is what the recipe will give you once it is done. Time:120.0, <-- And here is the time of the recipe (How long it will take in in-game seconds) } recipe Dry Bath Towel <-- Here I have added the same recipe, but for bath towels. { BathTowelWet, Result:BathTowel = 1, Time:120.0, }}NOTE: REMEMBER the "," after each line! And that's it for the recipes! Yes, you are done. Part four soon to follow! So stay tuned for that. We'll take items next! ---- Update: It's been a while, sorry about that. Honestly.. School have taken a lot of my time this year because I'll be graduating this summer, so I really wanted to give it everything I got. Anyway, enough of the boring blabbering.. I'll continue this guide in January and then see how much I can work on it from then. I'll also see if there has been any large changes in my other examples as I go. TL;DR: School, busy, continuing in January. ---- -Sejemus