Jump to content

Recommended Posts

Examples/Templates for Mods is now available to download!

A series of mods that provide an example and template for creating new mods for different purposes to help new modders understand how to mod the game properly.

NOTE: EXAMPLE MODS NOT UPDATED YET. POSTED NEW VERSIONS OF GAME FILES USED BY THESE EXAMPLES AND MODS BASED ON THEM FOR THE DOORWAY UPDATE.

Alternate Files for Mods (revised for Doorway Update)

Provides a set of alternative version of game files to exapand game's modding support. Refer to the new ModLib mod to handle this.

Example Tuning Mod (still ok for Rain Update)

Example basic mod for changing the settings in the tunings.lua file.

Example Recipe Mod (revised for Rain Update)

Example basic mod for changing an the recipe of an existing craftable item.

--- Corrected to not cause game crash, make sure to use latest version ---

Note: if want to use custom image, must use alternate recipe.lua in New Structure Example

Example Non-Prefab Override (revised for Rain Update)

Shows how to override non-prefab files in the game. In this case, we are changing the rabbit's brain and stategraph as wll as the trap component.

Note: In order to override stategraph files, your mod must use the included alternate version of entityscript.lua

Example Prefab Override (revised for Rain Update)

Shows how to properly override an existing prefab in the game. In this case, the custom rabbit.lua changes the dropped loot for rabbits and beardlings. Note: appears prefab.xml no longer required

Example New Structure (revised for Rain Update)

Provides an example framework for creating a new structure type prefab with placement. Now with custom recipe texture. Currently uses existing animation files until a method for creating new ones can be determined.

Note: Includes an alternate version of recipe.lua that must be used in order to use custom images for a recipe.

Example Add Placer Mod (revised for Doorway Update)

This example mod shows how to add a placer to the marble pillar so it can be built in a fashion similar to other structures from the crafting menu.

--more to following in future--

Posted Image

mod thumbnail is a classic code example....see if you can make it out and run it!

Edited by WrathOf
  • Like 1

I'll will definitely try this. I've always wanted to make mods.EDIT: [MENTION=10271]WrathOf[/MENTION]I want to turn the rabbits into vicious murdering machines but I can't get them to attack me.They just run after me and try to attack but they either do no damage or just don't bite me.How would I be able to make them bite me?

Edited by Alvhem

New example for overriding non-prefab game files.

Note: This includes an alternate version of entityscript.lua which *must* be included in your mod only if you are overriding stategraph files.

Let me know if you come across any other files that do not allow an override version to get loaded. thx

Hmm, the recipe example worked fine when I made it just after the Winter Update....but now it is failing with the dreaded texture file error....which is odd since I am not changing the textures, just the ingredients. I'm investigating it now. :S

Hmm, the recipe example worked fine when I made it just after the Winter Update....but now it is failing with the dreaded texture file error....which is odd since I am not changing the textures, just the ingredients. I'm investigating it now. :S

Hey could you maybe add a brain structure type with the running away and stuff?

Ok, worked out the problem with the Recipes example mod....we will now need to include an override for the included crafting.lua file when changing or adding crafting recipes.There is currently a bug in the game code where the Ingredients class used by the Recipes class is being overwritten by the Crafting class for its UI needs....derp :S

really weird, i tested with a unmodified lua ur override method for prefabs.xml with GLOBAL.TheSim:LoadPrefabDefs( MODROOT.."" )but ds will not run. my log file shows no error but corrupt ending. of course i use winters tale. we will talk sooni go sleep nowregards

Was it a stategraph file? If so, did you make sure to include the entityscript.lua file I provided in the mod's scripts folder? this is currently required until the base game is fixed.EDIT:On second thought, I don't think I understand...what lua file were you trying to override and did you make sure to update the mod's prefab.xml with the correct pathing info?

Edited by WrathOf

no stategraphs. just a normal lua like campfire.lua e.g

sure ur example mod "Example Prefab Override

" works on rabbit.lua but u did test it on other files like campfire? it wouldn't work.

regards

Edited by dontstarver.wiki

Ok, I have updated the example mods....still reviewing the New Structure mod so please wait on this as you will need the revised entityscript.lua file.[MENTION=8560]dontstarver.wiki[/MENTION]Try replacing the prefab files with the new game version. It appears we no longer need to provide a prefab.xml file....the game now automatically loads the prefabs from a mod's scripts/prefabs folder. Yay...less work!

Actually, it was the recipe.lua file....reviewing too many mods. :Dhttp://dl.dropbox.com/u/43476419/Example%20Mods%20recipe_lua%20for%20Rain%20Update.zipLooks like they stripped the "cost" parameter from the class so make sure your new recipes use the new format....refer to the game's new recipes.lua for examples.EDIT:I have not tested this confirm but I assume you still need to create and load a prefab.xml file for *new* prefabs....otherwise how would the game know about them. :D

Ok, I have updated the example mods....still reviewing the New Structure mod so please wait on this as you will need the revised entityscript.lua file.

@dontstarver.wiki

Try replacing the prefab files with the new game version. It appears we no longer need to provide a prefab.xml file....the game now automatically loads the prefabs from a mod's scripts/prefabs folder. Yay...less work!

good news :applause:

Thanks Wrath for the templates and stuff! I kinda wanted to edit the prefabs without editing them directly in the actual files incase I messed up and that. Thanks, I can understand the mods more now! :)Edit: I also wanted to ask if the modmain.lua file needed any coding or can it just have any text because if it does then stuff is getting complicated! xDEdit: Ok so the modmain.lua file doesn't need coding, just found out. :)

Edited by IIAIIStarzII

I've been experimenting with the templates and I learned that AddGamePostInit() can only be used once in the modmain.lua. Could I get around this restriction by using multiple LUA files in the mod rood, or would it require making completely separate mods?---I've also examined the example/template for recipes. But after changing multiple recipes (like a lot), I started thinking about putting the changes in a table or nested list and running that through the GetRecipe() and Ingredient() functions.The problem is that I'm still a silly noob when it comes to programming. And while I'm quite confident I can get the loop working by studying examples of 'for k, v in pairs' in the code, the problem is getting the list right.So far I've come up with this example (and it looks to me as elegant as a hippo in a tutu).

MOD_recipe_list =	{			MOD_farmplot = {name = "farmplot", ingr_list = {ingr_1 = {"poop", 4}}},		MOD_farmplot2 = {name = "farmplot2", ingr_list = {ingr_1 = {"poop", 8}, ingr_2 = {"twigs", 8}}},		MOD_farmplot3 = {name = "farmplot3", ingr_list = {ingr_1 = {"poop", 12}, ingr_2 = {"boards", 6}}}	}
The amount of lists within lists doesn't seem right to me. I've been thinking combining table and lists, but I haven't found enough good examples of table code in the game yet to imagine how to do that. Especially the method of getting the data into the table.Also I'm having troubles with not all recipes having the same number of ingredients, having to choose between nested lists and a nested 'for k,v in pairs' method, or one big table and then fishing out empty values.So I'm a bit stuck on this, and while I found easier ways to change the recipes (simply with the Recipe() function), I really want to solve this as a learning experience and would love some expert advice on how to tackle it.

[MENTION=3587]Stroomschok[/MENTION]

Yes, you are only allowed 1 game and sim post init callback per mod....why are you needing more?

My recipe example was intentionally basic but I have been debating on adding a few variations.

For tweaking purposes, it seemed easiest to just get the recipe and alter it but technically as you have found, you can just redefine the whole thing using the Recipe class constructor function to overwrite the previous definition.

For extensive recipe alteration, I think I would just go with overwriting the definitions directly and not bother with GetRecipe....but as a programming exercise....

Assuming your intent is to get an existing recipe definition and iterate over a data structure that only lists the changes....

--Localize globals usedRECIPETABS = GLOBAL.RECIPETABSIngredient = GLOBAL.IngredientRecipe = GLOBAL.Recipe--Define list of recipe changesMOD_recipe_changes = {		farmplot = {					--Name of game recipe changing		ingredients = {				--List of new ingredients			{"poop", 4},			--List of Ingredient parameters		},		tab = RECIPETABS.FARM,		--Crafting tab assignment		level = 0,					--Science level required (0, 1, 2, or 3)		placer = "farmplot_placer",	--Prefab to use during placement		min_spacing = 3.2,			--Spacing between this recipe and next or previous, not working though	},	farmplot2 = {		ingredients = {			{"poop", 8},			{"twigs", 8},		},		min_spacing = 10,	},    farmplot3 = {    	ingredients = {    		{"poop", 12},    		{"boards", 6},    	},		level = 0,    },}local function ProcessMyRecipeList(list)	--Iterate over list of recipe changes by name/data pairing	for name,data in pairs(list) do		local recipe = GLOBAL.GetRecipe(name)		if recipe then			if data.ingredients then				--temp list				local new_ingredients = {}				--Iterate over list of ingredient data by index/data pairing				for i, item in ipairs(data.ingredients) do					local ingredient = Ingredient(item[1], item[2])		--assumes index1=name and index2=amount					if ingredient then						--Add ingedient to temp list						table.insert(new_ingredients, ingredient)					else						print("Unable to make ingredient "..item[1]..", "..item[2])					end				end				--Transfer new list of ingredients to recipe				recipe.ingredients = new_ingredients			end			--Transfer tab setting if found			if data.tab then recipe.tab = data.tab end			--Transfer level setting if found			if data.level then recipe.level = data.level end			--Transfer placer setting if found and make sure it is loaded			if data.placer then				recipe.placer = data.placer				if TheSim then GLOBAL.TheSim:LoadPrefabs{data.placer} end			end			--Transfer min spacing setting if found			if data.min_spacing then recipe.min_spacing = data.min_spacing end			--or use this alternate method if you prefer			--recipe.tab = data.tab or recipe.tab			--recipe.level = data.level or recipe.level			--recipe.min_spacing = data.min_spacing or recipe.min_spacing		else			print("No recipe found for "..name)		end	endendlocal function modGamePostInit()	ProcessMyRecipeList(MOD_recipe_changes)endAddGamePostInit(modGamePostInit)

I ended up just making this whole example in order to work it out and not sure how I would explain it in words anyways. :lol:

Designing data structures in Lua can get messy in a hurry. :D

Well I don't 'need' more then one, but when changing multiple different things within the same mod, I thought it would be more tidy giving their own AddGamePostInit.---The advantage about the GetRecipe() function is that it doesn't require also putting the unchanged recipes in the list, because it doesn't mess with the order of the crafting menu. I noticed that using the Recipe() function, reloads it at the bottom of its tab.---I see you just went ahead and completely wrote the whole thing, instead of just correcting my list and letting me try to solve it :PI'm studying it now and I have some questions:

farmplot2 = {	ingredients = {		{"poop", 8},		{"twigs", 8},	},
The two ingredient lists don't get names like ingr_1 = and ingr_2 like I did. Am I correct in understanding that by stating:mylist = {{x1 , y1}, {x2, y2}}this is the way to turn a list into a table or are these still simply nested lists? (I do notice however you access them using [] brackets, which I found in LUA documentation to belong to tables).---
local recipe = GLOBAL.GetRecipe(name)
The name input is simply the name of the list and not in the format with double quotations (like "farmplot'') The example in the recipe mod templates uses:
local recipe = GLOBAL.GetRecipe("panflute")
Now I'm confused when it's imperative to use the double quotations and not. (In which lua do these 'internal' names even get declared?)---
43	if data.ingredients then44		--temp list45		local new_ingredients = {}46		--Iterate over list of ingredient data by index/data pairing47		for i, item in ipairs(data.ingredients) do48			local ingredient = Ingredient(item[1], item[2])		--assumes index1=name and index2=amount49			if ingredient then50				--Add ingedient to temp list51				table.insert(new_ingredients, ingredient)52			else53				print("Unable to make ingredient "..item[1]..", "..item[2])54			end55		end56		--Transfer new list of ingredients to recipe57		recipe.ingredients = new_ingredients58	end
I don't completely understand the purpose of line 48. It seems to me that you're putting the execution of the function into a variable, for the purpose of checking with the IF statement in line 49 whether it actually has a recipe, but why? If there was no recipe the FOR loop in 47 should have already stopped, correct?And then putting that variable again into a new table in line 51 and then used it 57: why? Hasn't the Ingredient() function already been executed at line 48 and the ingredients in the game changed?If you store them in recipe.ingredients, doesn't that simply store it into a local 'copy' of GLOBAL.Recipe.ingredients, without changing anything in the game or being of any further use?Also: does line 48's Ingredients() again gets re-executed when the variable holding it is put in that table, and again in recipe.ingredients? (Is that the purpose of doing it?)---I am is VERY grateful for the sage advice so far :) Edited by Stroomschok

Ok, so actually, the *whole* value of MOD_recipe_changes is a table....anything within { } is a table in Lua. That table can contain nested tables which can contain nested tables....yada...yada.....and tables in lua are just syntactic sugar for multi-dimensional arrays as found in other languages but the index for these arrays can be any supported Lua value type. Essentially, you have very limited restriction for greater flexibility but this can lead to confusion.

I purposely chose the format to show you the 2 ways of defining the tables and iterating over them. The first being as you were doing by assigning explicit index "names" and the second being where you use the implicit index "order" (1,n)

You will find in the documentation that table = { name1 = value1, name2 = value2, ... } can be accessed as table["name1"] = value1 which is convenient in cases where you have string based names for things.

Where as in the case of table = { value1, value2, ... } you can access this by the built-in numeric index like an array so table[1] = value1 in cases where you do not need a specific name for each index.

How best to design the structure of your custom tables depends on what the data is, where it comes from and how you plan to iterate over it.

In the case of mylist = {{x1 , y1}, {x2, y2}} you are defining a table with 2 entries, each of which define a table containing 2 entries....i.e. a 2 dimensional array in which an entry can be accessed by mylist[x][y] and can therefore be iterated over using a nested for loop where the outer loop iterates over x=1, #mylist and the inner loop iterates over y=1, #mylist [x] ....yeah...just blew your mind there. :D

----------

At line 49, I am storing the result of the Ingredients class in a variable that I then validate before using...this is mainly for error handling purposes and what I consider best practice but not absolutely required. This is not about the recipe but ensuring that the values I passed to the Ingredients class resulted in a usable instance of it.

The recipe expects a list of ingredients which I am building based on what I find in the main changes table. It is not a one-for-one evaluation? Hard to explain I guess. Ingredient is only for 1 entry in a recipe's ingredients list. Also, there are no "global" ingredient definitions laying around as there are for the recipes, they are defined as you need them.

On the copies question....um, nearly everything in Lua is passed as a memory reference, not as "copies". When I am passing my local ingredients to the recipe, it is getting a reference to that memory location. Then on the next recipe I am re-declaring the ingredients variable which gives me a *new* memory location which I then pass to that recipe.

Oh and just consider your one Game/Sim PostInit as your mod's "main" and organize your code as functions you can call from it to keep things readable unless your changes are minor in which case just put it in the "main".

EDIT:

On the recipe sort order, that is not implemented at the moment, so yes, when you redefine them they go to the bottom of the list. The menu is built based on the order of recipe creation for now.

Edited by WrathOf

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...