|
|
| (2 intermediate revisions by one other user not shown) |
| Line 1: |
Line 1: |
| This text describes making gadgets. | | This text describes making a gadget. |
|
| |
|
|
| |
| =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.
| |
|
| |
| [[File:rapid_pool_filedust.png]]
| |
|
| |
| 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:
| |
| <code><pre>
| |
| 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,
| |
| }
| |
| </pre></code>
| |
| 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:
| |
| <code><pre> | | <code><pre> |
| function gadget:GetInfo()
| | "move blah now;" so all your shit happens virtually instantly. |
| 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</pre></code>
| |
| | |
| 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.
| |
| [[File:thinkingAboutVulcano.png]]
| |
| | |
| ''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 chose 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 <code>gamedata\explosions\berthashot.tdf</code>
| |
| | |
| 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:
| |
| <code><pre>
| |
| ( 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
| |
| </pre></code>
| |
| | |
| *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:
| |
| | |
| [[File:DesertTriadHillCoordinates.jpg]]
| |
| | |
| 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:
| |
| <code><pre>Spring.SpawnCEG ("BERTHASHOT", 3830, 390, 3600)</pre></code>
| |
| | |
| 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
| |
| </pre></code>
| |
| | |
| <code>if (f%10 == 0) then</code> 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:
| |
| <code><pre>
| |
| /cheat
| |
| /globallos
| |
| </pre></code> | | </pre></code> |
|
| |
|
| |
| Now we finally see the smoke:
| |
|
| |
| [[File:DesertTriadVulcano.gif]]
| |
|
| |
|
| |
|
| |
| ==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
| |