Building Resources

Thanks! If I'm borrowing someone else code I always try and get the preferred method of crediting beforehand, that way it's less likely to displease anyone or cause other friction. I won't be editing the LUA at all since I haven't taken the time to really learn it yet so all your credit tags in there will stay as is as long as I'm using it and I'll add credit to each file that uses your LUA, which is my standard practice when using someone else work. I may also be adding a Thank you note to my mod's since I keep getting donated art and this code now.

There is one change you're going to need to make. It's the first line of actual code in BuildingResources.lua:
Code:
include( "SaveUtils" ); MY_MOD_NAME = "b218b309-9df5-4af5-baf9-c297e593398a";
You'll want to change the MY_MOD_NAME = "???" to what ever your mod's unique id is. That will prevent overwriting of data for other mods running at the same time. Provided of course that those mods are also using SaveUtils to save data to a target. Otherwise there will be conflicts. There is only one save slot per target, so mods have to treat it in a compliant manner.
 
Regarding mod combining, allow me to explain it another way. Do a search for the following:

SetScriptData
GetScriptData

These two commands should only appear in SaveUtils.lua. If they appear anywhere else, there is the potential for conflict. Specifically, BuildingResources.lua saves data to all players. If these two commands do appear elsewhere, you need to rewrite that line of code in the following manner, where target is a player, plot, or unit:

target:SetScriptData( value ); becomes save( target, key, value );
data = target:GetScriptData(); becomes data = load( target, key );

key can be any integer or string you want to use, it just has to be the same in load. Basically it names the save and you recall that save by name. Different names for different data being used by different lua files.

If you need some help combining it, just let me know and I'll give it a look.
 
Positive, it works great with existing resources.
Negative, So far I am unable to get it to work with a new resource. I even ignored the custom resource i want and just duplicated everything in the XML about RESOURCE_IRON and then renamed IRON to BLOODIRON (on everything but the art tags) and nothing. No error gets generated in either database.log or lua.log. If I swap the <Building_ResourceChange> <ResourceType> to an existing one it supplies said resource just fine, but if I switch it back to a custom resource it fails.

Sigh, I'll work at it more tomorrow but if anyone wants to see the code for my resource here it is.
 

Attachments

  • lettersofmarque.txt
    3.3 KB · Views: 104
Positive, it works great with existing resources.
Negative, So far I am unable to get it to work with a new resource. I even ignored the custom resource i want and just duplicated everything in the XML about RESOURCE_IRON and then renamed IRON to BLOODIRON (on everything but the art tags) and nothing. No error gets generated in either database.log or lua.log. If I swap the <Building_ResourceChange> <ResourceType> to an existing one it supplies said resource just fine, but if I switch it back to a custom resource it fails.

Sigh, I'll work at it more tomorrow but if anyone wants to see the code for my resource here it is.

Perhaps try using an existing resource mod and then applying it to the building mod? Such as Dales Hardwood mod?
 
Oh right I found that out this morning. You have to have a unit somewhere in your game that requires a resource for it to be considered strategic and visible at the top info panel. Unless of course you run some other mods that take care of this.



So the SaveUtils part of this mod. I may need some coffee, but what is the purpose of this exactly?

IE is it required to save the game period, or just an enhanced save mechanic for the mod? And is it required to get the building resource mechanic to work properly?


I will probably implement your mod into mine at some point, maybe in a few weeks, perhaps a month or so. Looks like it should make a pretty good addition for corporation mechanics among other things. :)
 
I've tried it and it works. Chances are yours works too, it's just not visible. Try also running the mod "AgS - Resource Info Panel" and the new resource will show up in the resource panel. Issues regarding visibility and map resource placement are discussed here:
http://forums.civfanatics.com/showthread.php?t=389782

I was wondering why it used to show up top but stopped doing so, didn't notice it was when i removed the unit requirements. Figures I turn off all other mods when working on mine so thus didn't have the resource info panel loaded. Thanks folks.
 
Oh right I found that out this morning. You have to have a unit somewhere in your game that requires a resource for it to be considered strategic and visible at the top info panel. Unless of course you run some other mods that take care of this.



So the SaveUtils part of this mod. I may need some coffee, but what is the purpose of this exactly?

IE is it required to save the game period, or just an enhanced save mechanic for the mod? And is it required to get the building resource mechanic to work properly?


I will probably implement your mod into mine at some point, maybe in a few weeks, perhaps a month or so. Looks like it should make a pretty good addition for corporation mechanics among other things. :)

In order to save data so that it shows up again when you reload a saved game you have to put that data in the ScriptData. Otherwise you save your game, come back, and the mod no longer works. This is true of all mods that require saved data, which is just about any mod that's any good. Problem is the only data you can put in ScriptData is a string. Keep in mind, every mod running at the same time also uses the same ScriptData save slot that exists on players, plots, and units. There is only one slot per player, plot, and unit and it can only hold a single string. The solution to this limitation is something called serialization. Which is a fancy way of saying it turns complex data structures into a single string. What SaveUtils does is allow you to save what ever you want, strings, tables, booleans, whatever. And you can save as many of them as you want, you just have to give them different keys to identify them by. Best of all, it allows every mod currently running to use the save slot the very same way without over writing the other mod's data. But it does require that every running mod accessing saved data use SaveUtils functions save() and load(). Otherwise conflicts will occure and one mod will overwrite the data of another mod and things will break down. SaveUtils does all the serialization and manages the different mods data. It is also the reason BuildingResources.lua can save a complex table that it recalls each turn.

It is a lot to digest, I know. It is an issue that has been discussed at length by others in this community. SaveUtils is designed to take the work out of it and make it all easy. It just requires that all saving and loading be done thru the save() and load() functions.
 
Ah, so if you start using LUA in your mod, you need the SaveUtils to be able to play your saved game again?

So far, I have gotten by with just XML changes while waiting for people to get spun up on how LUA works in the game.

Getting pretty close to the point where I will begin adding some LUA files to my mod though, so this is good to know.

I am sure once I start trying to combine several LUA files in my mod I will be all over the place trying to make sure it works right. :)
 
I'm more than willing to help. In order for SaveUtils to be truly useful, it has to be adopted. As BuildingResources demonstrates, SaveUtils makes things possible, so there is good reason to adopt it. But more than that, it makes all compliant mods compatible, so the more widely adopted, the easier things get for everyone.

The deserialize() function represents a total of about 30 hours worth of work, by the way. It changes that single save string back into a complex table. I don't mind saying it is one of the more difficult things I have programmed. That's why I put my real name on it. :)

So for combining files, each Lua file that saves or loads will need to have that same line at the top of the file.
Code:
include( SaveUtils ); MY_MOD_NAME="???"
This gives each file access to the save() and load() functions and lets it know what mod it is saving and loading data for. The name should be unique to your mod; I like to use the mod id shown in modbuddy.

Then just make sure the commands SetScriptData and GetScriptData only show up in the SaveUtils file. That it's job and its job only.

I'm happy to look at what ever you have.
 
I'm more than willing to help. In order for SaveUtils to be truly useful, it has to be adopted. As BuildingResources demonstrates, SaveUtils makes things possible, so there is good reason to adopt it. But more than that, it makes all compliant mods compatible, so the more widely adopted, the easier things get for everyone.

The deserialize() function represents a total of about 30 hours worth of work, by the way. It changes that single save string back into a complex table. I don't mind saying it is one of the more difficult things I have programmed. That's why I put my real name on it. :)

So for combining files, each Lua file that saves or loads will need to have that same line at the top of the file.
Code:
include( SaveUtils ); MY_MOD_NAME="???"
This gives each file access to the save() and load() functions and lets it know what mod it is saving and loading data for. The name should be unique to your mod; I like to use the mod id shown in modbuddy.

Then just make sure the commands SetScriptData and GetScriptData only show up in the SaveUtils file. That it's job and its job only.

I'm happy to look at what ever you have.

So pretty much all I have to do is include your SaveUtils.lua in my mod, change the 1 line to something like this:

include( "SaveUtils" ); MY_MOD_NAME = "Procylon's Call to Power Project"

And then make sure it is the last update on my list, and it should work fine as long as no other lua in my mod change SetScriptData/GetScriptData?


So what is the best way to test it when I am ready to implement? Load my mod including a lua file, run a couple of turns, and then try and load it? And then do the same after I include the SaveUtils lua?
 
So pretty much all I have to do is include your SaveUtils.lua in my mod, change the 1 line to something like this:



And then make sure it is the last update on my list, and it should work fine as long as no other lua in my mod change SetScriptData/GetScriptData?


So what is the best way to test it when I am ready to implement? Load my mod including a lua file, run a couple of turns, and then try and load it? And then do the same after I include the SaveUtils lua?

I'm not sure what you mean by "last update on [the] list", but everything else looks correct. If none of the other files use GetScriptDate or SetScriptData then all you need to do is change the MY_MOD_NAME. Your example name should work just fine.

There are several ways to test it out, but I believe the most effective is to run another small mod at the same time who's only job is to inspect the save slot on players. Then you can see what the other mods are saving to the player targets.

This should work: --improved version in post below.
Code:
include( "SaveUtils" ); MY_MOD_NAME = "Procylon's Call to Power Project";
function inspect()
	setCacheState( 0 ); --no cache.
	for index,pPlayer in pairs( Players ) do
		if pPlayer ~= nil and pPlayer:IsAlive() then
			print(out(load( pPlayer )));
		end
	end
end
Events.ActivePlayerTurnStart.Add( inspect );

Incidentally, there is one player target for each human, AI, citystate, and one for what I assume is the minor civ, aka: barbarians. First cities also seem to have the id 8135 or something like that. You'll see it in the output.
 
Actually, let me make a correction. This should work better:

Code:
include( "SaveUtils" ); MY_MOD_NAME = "[COLOR="blue"]Player Save Inspector[/COLOR]";
function inspect()
	setCacheState( 0 ); --no cache.
	for index,pPlayer in pairs( Players ) do
		if pPlayer ~= nil and pPlayer:IsAlive() then
			print(out(load[COLOR="Blue"]( pPlayer, nil, false )[/COLOR]));
		end
	end
end
Events.ActivePlayerTurnStart.Add( inspect );
 
Out of curiosity, was it not possible to make a new table and save the data into the table? From what I've seen of the sql side, it seems possible but not sure if it's as easy to access from lua. That should take care of the save game issue without requiring serializing to a specific string, or is this more because you need flexible non-typed data storage?
 
If you save to the database, not only can it be completely overwritten / deleted the next time mods are changed, but it will not be part of the save game file. That would mean you couldn't take a save from one computer and use it on another.
 
Top Bottom