User:Knorke/Sandbox2

From Spring
Revision as of 18:47, 5 November 2014 by Knorke (talk | contribs) (templates for tips,fixmes)
Jump to navigationJump to search

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.

Tip
If you just want to know "How to set up a test-folder" 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:

  1. Unpack the archive
  2. Add the new script file or edit it
  3. 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.

Tip
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 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)

Where in the gadget should we put that? Into gadget:UnitFinished() 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:

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