User:Knorke/Sandbox2
This text describes making gadgets.
Gadgets must be in a map or game
For getting started with a widget, we could just put the file in the spring folder and start coding. Unlike widgets, gadgets can not be used "locally" like this: They must be contained in a game or map archive. So we must find a way to put the gadget into the game or map.
>>> If you just want to know "How to do this" then skip directly to next chapter. <<<
The problem is that games and maps usually come in form of zipped archives, or in case of lobby downloaders as many small files.
That makes adding new files cumbersome:
- Unpack the archive
- Add the new script file or edit it
- Repack the archive
So we must turn a map or game into an .sdd archive.
That is explain in more detail in general modding tutorial: ADDLINK FIXME
For first experiment it does not matter if the gadget is in the map or in the game.
Another way is to create a test-mutator. That is basically a game that "includes" another game, like an add-on. The advantages are:
- No need to edit existing game and maybe run into problems.
- The test-game filesize stays small enough to share easily with others, to get help.
- One can still use all the units, features & effects of the original game. That is useful for testing.
Personally I recommend the test-mutator. XTA is a good canidate as base-game choice because:
- in some ways it is more basic
- the unitnames are human-readable. For example "arm_windgenerator" instead of "armwingntor"
- Some games try to hide as much engine GUI as possible, however for testing that is not so useful.
The Test Mutator folder
1) Create folder: games\MyLuaStuff.sdd
2) Create file: games\MyLuaStuff.sdd\modinfo.lua ( Modinfo.lua )
With this content:
return {
name='XTA LuaStuff',
description='lolool',
URL='http://code.google.com/p/xta-springrts/',
shortname='XTA',
version = '9.744',
mutator='LuaStuff',
game='Total Annihilation',
shortGame='TA',
depend = {"XTA 9.744"},
modtype=1,
}
FIXME: mutator details, can it work with any xta version
3) Test with spring.exe if the mutator shows in game list and can be played
First gadget: Welcome, new unit!
1) Create folders: games\MyLuaStuff.sdd\LuaRules\gadgets
2) Create file: games\MyLuaStuff.sdd\LuaRules\gadgets\mytestgadget.lua
3) For first widget we had done an empty widget that did nothing. In the widget-selector-menu we could still check if things were working right. So we just take the Hello-Unit widget example and turn it into a gadget:
function gadget:GetInfo()
return {
name = "test gadget",
desc = "testing Lua things",
author = "your name",
date = "today",
license = "GNU GPL, v2",
layer = 0,
enabled = true,
}
end
if gadgetHandler:IsSyncedCode() then
function gadget:UnitFinished(unitID, unitDefID, teamID)
Spring.Echo ("Welcome, new unit!")
end
else --unsynced below
end
We notice it looks very similiar to the widget, except instead of widget::xxx there is gadget:xxx
The GetInfo()-thing again contains some informations about the script, but is otherwise not interessting and to save space will be left out when posting code.
4) Load the game and build a few units. The gadget should welcome each unit.
Vulcano example
An example of the process when making gadget.
Pretend you are making a map and want to add a vulcano.
Note: If we wanted, at this point we could move the Lua into a map-archive. But for testing it is easier to continue using the test-mutator-game.
Define vulcano problem
We want to make a vulcano. Now need to think what excactly is this vulcano is supposed to do.
- Should the vulcano damage near units?
- Should it throw burning rocks across the map?
- Should it merely be a visual effect, just some smoke on a hill?
For this tutorial we just the last option. (superlame!)
How to make smoke
Now that we know we want to make smoke, the new question is: How to make smoke? One way is to use Spring's particle system called CEG:Main Games can use these CEGS to create explosion, muzzle flashes, fire and so on.
Since our test-mutator is based on XTA, we can use all its effects.
Here we are going to use the effect "BERTHASHOT" which is defined in the file gamedata\explosions\berthashot.tdf
As the name implies, that effect is usually used when a "Big Bertha" cannon fires a shot. We pick it because it might vaguely look like a smoking vulcano.
How to spawn the CEG?
So how can we make this "BERTHASHOT" effect appear on our vulcano hill? Surely there must be some function call...
We clicked arond the CEG:Main page a bit and discover CEG:Calls
It seems there are various ways to use CEGs, for example weapons can use them.
Since we already decided we want to make a gadget, the relevant part is CEG:Calls#Synced_Lua_Gadget_CEGs which brings us to Lua_SyncedCtrl#Other
Spring.SpawnCEG
On Lua_SyncedCtrl#Other we discover the function Spring.SpawnCEG and its parameter list:
( string "cegname" | number cegID,
number posX = 0, number posY = 0, number posZ = 0,
number dirX = 0, number dirY = 0, number dirZ = 0,
number radius = 0, number damage = 0
) -> nil | boolean success, cegID
- It seems to expect the name of the CEG as first parameter.
- We already got a CEG name: "BERTHASHOT"
- The posX,posY,posZ parameters seem to be the coordinates where the effect appears.
- Note to self: Find coordinates of some hill that looks like it needs some smoke.
- We have the effectname and where it should appear. The other parameters seems useless to our purpose so we ignore them.
- They will use default values.
Location, location, location
We decide to use the map "DesertTriad".
At the bottom right corner there seems a be small hill, perfect vulcano material:
1) The hill where we want smoke to appear.
2) The tooltip that shows the coordinates, when we mouse pointer onto the hill.
Protip: Look at Gamedev:UnitsOfMeasurement to learn about coordinates system!
Putting parameters into Spawn.CEG
Putting it together:
Spring.SpawnCEG ("BERTHASHOT", 3830, 390, 3600)<code><pre>
Where in the gadget should we put that?
Into <code>gadget:UnitFinished()<code> callin, like with the Hello-Unit example?
Then the vulcano would only smoke when a new unit is created.
We need to find a better callin-function from the [[Lua:Callins]] page!
Some callin that gets triggered regularly... so we can have nice constant smoking.
We find:
GameFrame(frame) - ''Called for every game simulation frame (30 per second). ''
...thus we write:
<code><pre>
if gadgetHandler:IsSyncedCode() then
function gadget:GameFrame (f)
if (f%10 == 0) then
Spring.SpawnCEG ("BERTHASHOT", 3830, 390, 3600)
end
end
else --unsynced below
end
if (f%10 == 0) then is added so that a new effect is only spawned every 10 frames.
Also see http://answers.springlobby.info/questions/412/gadgetgameframe-modulo-operation-explained - oh 404! (FIXME)
Smoke in your eyes
Save, start spring, look at the mountain.
Do you see smoke? Likely not because this smoke-effect is only visible when units have vision on it.
So either move a unit to the hill or type into chat:
/cheat
/globallos
Now we finally see the smoke:
What did we learn?
Writting the script is just part one part of making gadget.
From programming perspective, the vulcano example is quite simple.
The harder part was...
- finding a starting point
- setting up an editable archive
- finding the right functions
- learning about CEGs
- figuring out general "Spring stuff" like coordinates.
For example had we not known that some particle-effects require vision to be visible, we might have been wondering forever why the vulcano does not work - even if everything in the script was correct.
Luckily, after a while this general "Spring stuff" becomes more familiar.
FIXME: wording


