Ruleset Modding Tutorial

This tutorial is about creating variant from existing ruleset. Creating new ruleset from scratch will be covered in Stub ruleset.
At the moment this is just a copy from tutorial I wrote Feb-2011 with minimal
wiki formatting added.
==Where files should be located so Freeciv finds them?==
Depends on OS. I have to investigate Windows and Mac OS X cases. Anyway, you can check where default files distributed with Freeciv are located and can be sure that Freeciv searches that directory. For example, "amplio2.tilespec" and "default.serv" are files located to such directory.
Dino sez - Mac OS X is same as unix, but I found added rulesets can also be found when added to a directory named ~/.freeciv/2.5 (substitute the version number of freeciv you are using for 2.5).
FREECIV_PATH
==General==
Our first examples cover a case where one creates modified version of an existing ruleset. Help for writing completely new ruleset from scratch is only in the end. We are making modified version of default ruleset and name of the new ruleset is "cazfimod".
==Setup initial version to start development with==
- Make copy of directory "default" (subdirectory of directory found in (2)) under name "cazfimod", but don't include file "default.lua" in the copy. You need your own version of "default.lua" in quite special cases only, and having it makes maintaining ruleset harder. If you are basing your new ruleset to ruleset other than default,t's likely that even the original ruleset has no "default.lua".
- Create file cazfimod.serv containing single line:
rulesetdir cazfimod
- Edit cazfimod/game.ruleset section [about]. Set name and description of the ruleset. We do this now just to have some visible change compared to default ruleset in our new ruleset, so we can check in-game that it's really being used instead of default one
- Start freeciv client (I'm using gtk-client).
- "Start New Game"
- In "Ruleset Version:" list there should now be "cazfimod" available. If not, probable reason is that "cazfimod.serv" file is not in correct place.
- Select cazfimod ruleset and "Start"
- "Help" -> "About Ruleset". This should now display ruleset description we earlier gave to cazfimod.
- Quit client
==Add tech==
- Add to cazfimod/techs.ruleset following entry among existing [advance_...] entries:
[advance_freeciv]
name = _("Freeciv")
req1 = "Computers"
req2 = "None"
flags = ""
graphic = "a.freeciv"
graphic_alt = "a.university"
- Start game with cazfimod ruleset again.
- "Civilization" -> "Research". There should be new tech "Freeciv" in the tech tree after "Computers" technology.
- Quit client
==Add unit==
- Add to cazfimod/units.ruleset following entry after [unit_spy] entry:
[unit_modder]
name = _("Modder")
class = "Land"
tech_req = "Freeciv"
obsolete_by = "None"
graphic = "u.modder"
graphic_alt = "u.spy"
sound_move = "m_modder"
sound_move_alt = "m_generic"
sound_fight = "f_modder"
sound_fight_alt = "f_generic"
build_cost = 50
pop_cost = 0
attack = 0
defense = 5
hitpoints = 30
firepower = 1
move_rate = 3
vision_radius_sq = 8
transport_cap = 0
fuel = 0
uk_happy = 0
uk_shield = 0
uk_food = 0
uk_gold = 0
flags = "Diplomat", "IgZOC", "NonMil", "Spy", "GameLoss"
roles = ""
helptext = _("\
 Powerful spy, but losing one of these causes player to lose whole game!
")
- Start game with cazfimod ruleset
- Notice in tech tree how tech "Freeciv" now allows new "Modder" unit.
- Notice also how appearance of "Modder" is that of "Spy". We have not added graphics for it yet, so Spy graphics we defined as fallback with "graphic_alt" tag is used.
- Quit client
==Adding gfx for Unit==
It's time to make appearance of Modder distinct from that of regular Spy. That requires changes to tileset. I don't want to mess with default tilesets with this experiment, and neither do I want to create complete tileset from scratch for such a tiny change. Instead I'm going to use little trick, which some people might consider a bit hacky.
We already have default tileset amplio2 with graphics for all our units except Modder installed. Let's reuse files of amplio2 as much as possible, and to just add files with Modder gfx. We do need to create new tileset, but not all the files for it. We'll call that tileset "cazfigfx".
- Create new directory cazfigfx
- Create 64x48 pixel gfx file cazfigfx/modder.png
- Create text file cazfigfx/modder.spec with contents:
[spec]
options = "+Freeciv-2.3-spec"
[info]
artists = "Cazfi and those following his tutorial"
[file]
gfx = "cazfigfx/modder"
[grid_main]
x_top_left = 0
y_top_left = 0
dx = 64
dy = 48
tiles = { "row", "column", "tag"
 0, 0, "u.modder"
}
- Copy amplio2.tilespec as cazfigfx.tilespec
- Edit cazfigfx.tilespec:
 - Change name entry to read "cazfi"
 - To files -entry, add "cazfigfx/modder.spec" after "amplio2/units.spec". Remember to add comma
- Start game with cazfimod ruleset.
- Game still starts with amplio2 tileset (we will improve that later)
- "Game" -> "Options" -> "Local Client" There should be "cazfigfx" selectable in list of tilesets. Select it, and click "OK"
- "Help" -> "Units" -> "Modder"
 Notice how your new gfx is used
==Correct tileset from client start==
If you are starting client from commandline, you can select tileset to be used there already.
freeciv-gtk2 -t cazfigfx
If ruleset and default tileset (or tileset saved in client preferences) are incompatible, you actually cannot wait to get in-game to change the tileset.
==Making ruleset to suggets certain tileset==
We are not happy with the fact that by default (with default tileset) user cannot tell Modders and Spies apart, but user is expected to change tileset separately.
We can improve this.
- In cazfimod/game.ruleset, add following entry before [options]
[tileset]
prefered = "cazfigfx"
- Start client and again select cazfimod as your ruleset. You should be presented with dialog suggesting that you switch tileset. Click "Load tileset"
- Quit game
==Overriding gfx from other file==
We are now using all unit graphics except modder from amplio2's units.png. But we are not happy with Fighter graphics. We again want to avoid making full copies (with associated need to maintain all gfx).
- Edit cazfigfx.tilespec by adding word "duplicates_ok" to "options" When writing this, it results in:
options = "+Freeciv-2.3-tilespec duplicates_ok" This tells Freeciv that we are going to have multiple graphics for same tag, and that's not an error but we do it on purpose. Last graphic for tag will be used. That's why we added "cazfigfx/modder.spec" after "amplio2/units.spec"
- Inrease cazfigfx/modder.png canvas size to 128x48 and add your favorite Fighter graphics to the new 64x48 area.
- Edit cazfigfx/modder.spec by adding line
0, 1, "u.fighter"
 after line
0, 0, "u.modder"
- Check new Fighter graphics in game.
==Running server separately for easier ruleset debugging==
Freeciv is in fact two programs. Client handles user interaction, and in multiplayer environment each player runs client of their own. There is only one server in the game doing the actual game state handling. In single-player environment client is capable of automatically launching server for itself, and that's how we have run the game so far in this tutorial. When we click "Start New Game" client launches server and then connects it.
Sometimes it is beneficial to run server program by hand. One such reason for ruleset reason would be need to see what server outputs. Server's error messages about ruleset problems appear in its own console, which is not visible when server is launched by client.
- Start server (I hope Windows installation too includes icon for this, program name is freeciv-server if you need to launch it from commandline)
- Type "help" for introductory help. Inspect things with further commands like "help help" and "show" as much as you like.
- Start client
- In client: "Connect to Network Game"
- Fill in "Host: localhost", "Port: 5556" "Login: prefered username" and click "Connect"
- Play the game
- Quit the server by typing "quit"
==Observing game with just AIs present==
It can get tiresome to play number of turns over and over again to test some ruleset adjustments. Sometimes you can avoid the need to play yourself by giving control of all players to AI and connecting your client as Observer only.
- Start server and client separately
- Connect client to server
- In client select some of the <Easy AI>s from the list, push right mouse button to open context menu and select "Observe this player"
- In server prompt:
 > rulesetdir cazfimod
 > set timeout 5
 > set minplayers 0
 > set endturn 30
 > hard
 > start
- Quickly make sure your client window is open so you see action there
- Quit server and client
 You have now seen all-ai game attached to an player as an observer. There is another type of observer called "Global Observer".
- Start server and client separately
- Connect client to server
- In client chatline type: "/observe"
- In server prompt:
 > rulesetdir cazfimod
 > set timeout 1
 > set minplayers 0
 > set endturn 30
 > hard
 > start
- See action in client window
- Quit server and client
==Reading server commands from file==
We all are getting tired of writing those same server commands every time we want to run the game.
- Edit cazfimod.serv: Add after "rulesetdir cazfimod" -line:
set timeout 5
set minplayers 0
hard
- Start server.
- Type "read cazfimod.serv"
 - Type "show ruleset" to see that rulesetdir is correctly set.
 - Type "show timeout" to see current value of timeout setting.
 - Believe that all commands from cazfimod.serv have been executed
- Quit server
- Start client
- "Start New Game"
- Select "Ruleset Version:" cazfimod, but *don't* start game yet
- In chatline type "/show ruleset" and then "/show timeout"
- "Cancel"
- "Quit"
==Adding building/wonder==
- Edit cazfimod/buildings.ruleset, add following entry before
 [building_capitalization]:
[building_scenario_league]
name = _("Scenario League")
genus = "SmallWonder"
reqs =
 { "type", "name", "range"
 "Tech", "Computers", "Player"
 }
graphic = "b.scenario_league"
graphic_alt = "b.united_nations"
obsolete_by = "None"
build_cost = 300
upkeep = 0
sabotage = 0
sound = "w_scenario_league"
sound_alt = "w_generic"
helptext = _("Scenario League does absolutely nothing?\
Does scenario creator know what he is doing?")
- Check in game that there now is small wonder (building that each player can build to one city) Scenario League coming available from Computers.
==Effects==
- Add following to the end of cazfimod/effects.ruleset:
[effect_scenario_league]
name = "HP_Regen"
value = 100
reqs =
 { "type", "name", "range"
 "UnitType", "Modder", "Local"
 "Building", "Scenario League", "Player"
 }
- Replace helptext of Scenario League in cazfimod/buildings.ruleset with this: "Makes all Modders to regenerate all their hitpoints every turn when they don't move."
 I'll explain this a bit. Above effect definition means that value of effect type "HP_Regen" is increased by 100 when following requirements are true:
 - Unit in question is Modder.
 - Player has building Scenario League.
As there are no "HP_Regen" effects with negative value, increase of 100 means that at least value of 100 is reached.
Unlike with units, techs, buildings... field "name" is not something you invent yourself and would be visible to user. Instead it's name of the effect type you want to affect. See doc/README.effect for list of possible effects and what they do. Same document also contains list of possible requirement ranges (range within which there must be something fulfilling requirement)
==When should _("some text") be used?==
In case you are wondering why some texts in ruleset are wrapped inside _() and if that's important for your ruleset to work, I'll explain why it's used.
Freeciv does not use those markings, it simply ignores them.
var = "value"
is exactly same as
var = _("value")
for freeciv functionality.
It's an external tool that uses those markings. Strings marked that way are collected by gettext for translating. If you are creating custom content that will never be part of distributed freeciv package, you have no need to add those markings; freeciv will not contain translations for them even if you do.
TODO: Should I actually promote proper use of gettext markup in custom content too? Some of the custom content might later get added to freeciv distribution. In that case it would be good if it had the markup already for full localization - no risk of forgetting to add it.
TODO: Explain situation where non-localized ruleset is used in localized freeciv
==Creating a scenario==
I hope that editor usage is self-explanatory enough and leave most of this section out now so I can move to more advanced examples.
Some notes:
- When writing this, only gtk-client has editor functionality
- You can use editor only if you have proper rigths. You cannot
 use to it to cheat in multiplayer game.
- "Edit" -> "Editing Mode" to toggle between editing and playing the game
==Making unique tile==
This works in freeciv 2.3. I hope future versions to bring improvements in this area.
- Edit cazfimod/terrain.ruleset, add to end:
[base_cave]
name = _("Cave")
graphic = "base.cave"
grpahic_alr = "base.fortress"
activity_gfx = "-"
buildable = 0
build_time = 0
defense_bonus = 300
gui_type = "Other"
native_to = "Land"
flags = "NoStackDeath"
helptext = _("Who knows where this cave leads. It gives land units \
excellent protection and they die only one at a time in this tile.")
- If you already know how, add graphics for tag "base.cave" in cazfigfx tileset. Otherwise our new base will use fortress gfx as fallback
- Go to editor (remember to use cazfimod ruleset) You should now be able to place bases of type "Cave" on map. As it's not buildable in game it will ever appear only in where you place it in editor.
==Giving tile only unique graphics==
Above kind of base usage can of course achieve effect of giving tile just unique gfx, and no other special bonuses. Just create a base with wanted gfx that has no kind of gameplay effects. That's actually how it should be done at the moment.
(Whispers) But there's something curious I'll tell you, even though I doubt it will be any way useful. The other day I were browsing the source code when I suddenly noticed some code I had no idea about before. I immediately realized what it was, and have a quite good guess about its history, but it was still a surprise.
Back in 90's three Danish guys started programming project that got name Freeciv. To pay homage to their home country very early versions of Freeciv displayed Danish flag over tiles of their nation. So there was special sprite shown for some tiles in freeciv versions before my times (I started -97). Over the years parts of codebase have gone through many refactorings. People doing refactoring of one layer always enabled at least same level of functionality for other layers as previous version, not really realizing what one particular feature was used for. In most software layers special sprites feature survived, and possibly even
got better (I don't know if it was originally limited to same one hardcoded sprite for all hardcoded tiles, but now it allows any tile to have any sprite with no limitations how many different ones there can be in game) I have not tested it to confirm if it's functional in all required layers, but it seems to me that if savegame defines special sprites, client will display them. The only thing really missing is way to set those sprites. I suppose editor should have such functionality. But even if you cannot set them in game, you can edit the savegame in text editor to add such special sprites. Just add entries like
spec_sprite_x_y = "my_sprite" to [map] section. Replace "x" and "y" with coordinates and "my_sprite" with tag of the sprite you want to use. If someone tests this, let me know the results!
Category:Editing rulesets