User:Knorke/Sandbox1: Difference between revisions
1 |
|||
| Line 1: | Line 1: | ||
==test== | Lua tut | ||
=Requirements= | |||
* played a spring game | |||
* texteditor | |||
* copy of SpringTutorialGame | |||
* some small map because those load faster | |||
* Spring set to windowed mode for easier switchting between editor/game | |||
* a very bit familiar with programing (variables, functions, loops, arrays = enough) | |||
=Wupget and friends= | |||
In Spring games there are 3 kinds of Lua scripts. | |||
Crude and simple explaination: | |||
# gadgets: these are the "gameplay code" and do all kind of things. | |||
# widgets: these are for interface. | |||
# unit scripts: animate units & controll their weapons. also have some gadget power. | |||
Making those 3 is not very different but widgets are the easiest to test. | |||
There is also 4) functionality provided by the engine. | |||
'''Also look at this:''' | |||
http://springrts.com/mediawiki/images/1/13/Gadgets_widgets_and_friends.png | |||
All 4 are in a constant fight against each other. | |||
=My first wupdget= | |||
The SpringTutorialGame is simple and good for testing: | |||
You can use any other game but some block player widgets or are very confusing. | |||
1) | |||
Create a txt file like this and there: | |||
Spring\LuaUI\Widgets\myfirstwidget.lua | |||
and copypaste this text into it: | |||
----- | |||
<code><pre> | |||
function widget:GetInfo() | |||
return { | |||
name = "my first widget", | |||
desc = "this is so awesome", | |||
author = "horse 3000", | |||
date = "2009", | |||
license = "GNU GPL, v2 or later", | |||
layer = -10, | |||
enabled = true | |||
} | |||
end | |||
</pre></code> | |||
----- | |||
Nobody cares what excactly this does, but here you can put informations about your widget. | |||
What matters is that without such GetInfo() function Spring will not load the widget correctly. | |||
Since it takes up screen-space it will be left out when code is posted (but it must still be there.) | |||
Start spring.exe and press F11. The "widget menu" opens: | |||
http://springrts.com/mediawiki/images/8/80/Widget_F11menu.png | |||
It is likely already filled with some other widgets contained in the game. | |||
Find your new widget in the list. Click on it to turn it on and off: The name in list should go green or red accordingly. | |||
If that works - congratulation: You made a new widget that does excactly nothing. | |||
=="Hello unit" wupdget== | |||
Add the following at the end of myfirstwidget.lua: | |||
<pre><code> | |||
function widget:UnitFinished(unitID, unitDefID, teamID) | |||
Spring.Echo ("a new unit was finished! It belongs to team " .. teamID) | |||
end | |||
</pre></code> | |||
UnitFinished(...) is a callin function: Those are functions that the engine calls when | |||
certain events happen. | |||
Captain Obvious has already figured out: This function gets called when a new unit is | |||
finished. | |||
Spring.Echo is used to output text to the chat/console. | |||
So this widget should tell when a new unit is made. | |||
4) | |||
Open the widget menu and disable then re-enable your widget: This will reload the | |||
widget. | |||
Now build some units to test it. | |||
For lolz add an error like this: | |||
Spring.Echo (100 + nil) | |||
and reload the widget. | |||
The widgets name is green but turns yellow as soon a unit is build because "nil" can not | |||
be used in math like that. | |||
The error is also displayed in chat and [[infolog.txt]] | |||
Fix the error, reload the widget and it is green again. Oha. | |||
5) | |||
Even if there is a bot/other player building stuff, the widget will not notify on all | |||
their new units. | |||
That is because widgets are limited in what they can "see", to prevent cheating. | |||
The widget only sees what what the player who is running the widget can see, too. This | |||
is to prevent cheating. | |||
6) | |||
change the widget to this and guess what it does? | |||
<pre><code> | |||
function widget:UnitFinished(unitID, unitDefID, teamID) | |||
local x,y,z = Spring.GetUnitPosition (unitID) | |||
Spring.MarkerAddPoint (x,y,z, "a new unit! id=" .. unitID) | |||
end | |||
</pre></code> | |||
It adds a marker point on every new unit! | |||
Note how the unitID parameter from UnitFinished() is passed to GetUnitPosition() | |||
Every unit, feature or weapon projectile in spring has an ID number: | |||
http://springrts.com/mediawiki/images/3/3c/Units_features_projectiles.png | |||
There are never two units with the same unitID at the same time. #YOLO? | |||
No YOLO: when a unit is destroyed its unitID might be reused later for a different unit. | |||
6) | |||
A counter that is increased when units are made: | |||
------ | |||
local counter = 0 | |||
function widget:UnitFinished (unitID, unitDefID, teamID) | |||
counter = counter +1 | |||
Spring.Echo ("now there are " .. counter .. " units") | |||
if counter > 10 then | |||
Spring.Echo ("wow, more than 10 units!") | |||
end | |||
end | |||
------ | |||
Reload the widget and note how the counter gets reseted. | |||
That is how widgets roll: Their variables get cleared on reload. | |||
7) | |||
A counter that stores for each factory how many units it has already produced. | |||
One variable will not be enought here but an array can store multiple things. | |||
Arrays in Lua are tables. Read about tables: FIXME LINK | |||
------ | |||
local buildCount = {} | |||
function widget:UnitFromFactory(unitID, unitDefID, unitTeam, factoryID, factoryDefID, | |||
userOrders) | |||
local n = buildCount[factoryID] --read from table how many units this | |||
factory already built | |||
if n == nil then --was the entry empty? | |||
n = 0 --if yes, start | |||
counting from 0 | |||
end | |||
n = n +1 --increase n by | |||
1. (best comment ever) | |||
Spring.Echo ("This was unit number " .. n .. " from factory " .. factoryID) | |||
buildCount[factoryID] = n --store new buildCount for this | |||
factory | |||
end | |||
------ | |||
UnitFromFactory is basically the same as UnitFinished, but has the usefull factoryID | |||
parameter. | |||
Why the if n == nil? | |||
In Lua everything not initialized is nil (=nothing) and nil can not be used in any math. | |||
(n = n +1 is a math) | |||
Btw shorter version: | |||
buildCount[factoryID] = (buildCount[factoryID] or 0) + 1 | |||
8) | |||
Concatenating a nil is what breaks. Do it like this: Spring.Echo("text", param1, "text", | |||
param2, param3) | |||
Revision as of 00:08, 23 April 2014
Lua tut
Requirements
- played a spring game
- texteditor
- copy of SpringTutorialGame
- some small map because those load faster
- Spring set to windowed mode for easier switchting between editor/game
- a very bit familiar with programing (variables, functions, loops, arrays = enough)
Wupget and friends
In Spring games there are 3 kinds of Lua scripts. Crude and simple explaination:
- gadgets: these are the "gameplay code" and do all kind of things.
- widgets: these are for interface.
- unit scripts: animate units & controll their weapons. also have some gadget power.
Making those 3 is not very different but widgets are the easiest to test.
There is also 4) functionality provided by the engine.
Also look at this:
All 4 are in a constant fight against each other.
My first wupdget
The SpringTutorialGame is simple and good for testing: You can use any other game but some block player widgets or are very confusing.
1) Create a txt file like this and there: Spring\LuaUI\Widgets\myfirstwidget.lua
and copypaste this text into it:
function widget:GetInfo()
return {
name = "my first widget",
desc = "this is so awesome",
author = "horse 3000",
date = "2009",
license = "GNU GPL, v2 or later",
layer = -10,
enabled = true
}
end
Nobody cares what excactly this does, but here you can put informations about your widget. What matters is that without such GetInfo() function Spring will not load the widget correctly. Since it takes up screen-space it will be left out when code is posted (but it must still be there.)
Start spring.exe and press F11. The "widget menu" opens:
It is likely already filled with some other widgets contained in the game. Find your new widget in the list. Click on it to turn it on and off: The name in list should go green or red accordingly.
If that works - congratulation: You made a new widget that does excactly nothing.
"Hello unit" wupdget
Add the following at the end of myfirstwidget.lua:
<code>
function widget:UnitFinished(unitID, unitDefID, teamID)
Spring.Echo ("a new unit was finished! It belongs to team " .. teamID)
end
UnitFinished(...) is a callin function: Those are functions that the engine calls when
certain events happen. Captain Obvious has already figured out: This function gets called when a new unit is
finished.
Spring.Echo is used to output text to the chat/console. So this widget should tell when a new unit is made.
4) Open the widget menu and disable then re-enable your widget: This will reload the
widget. Now build some units to test it.
For lolz add an error like this: Spring.Echo (100 + nil) and reload the widget. The widgets name is green but turns yellow as soon a unit is build because "nil" can not
be used in math like that. The error is also displayed in chat and infolog.txt Fix the error, reload the widget and it is green again. Oha.
5) Even if there is a bot/other player building stuff, the widget will not notify on all
their new units. That is because widgets are limited in what they can "see", to prevent cheating. The widget only sees what what the player who is running the widget can see, too. This
is to prevent cheating.
6) change the widget to this and guess what it does?
<code> function widget:UnitFinished(unitID, unitDefID, teamID) local x,y,z = Spring.GetUnitPosition (unitID) Spring.MarkerAddPoint (x,y,z, "a new unit! id=" .. unitID) end
It adds a marker point on every new unit! Note how the unitID parameter from UnitFinished() is passed to GetUnitPosition()
Every unit, feature or weapon projectile in spring has an ID number:
There are never two units with the same unitID at the same time. #YOLO? No YOLO: when a unit is destroyed its unitID might be reused later for a different unit.
6) A counter that is increased when units are made:
local counter = 0 function widget:UnitFinished (unitID, unitDefID, teamID) counter = counter +1 Spring.Echo ("now there are " .. counter .. " units") if counter > 10 then Spring.Echo ("wow, more than 10 units!") end end
Reload the widget and note how the counter gets reseted. That is how widgets roll: Their variables get cleared on reload.
7) A counter that stores for each factory how many units it has already produced. One variable will not be enought here but an array can store multiple things. Arrays in Lua are tables. Read about tables: FIXME LINK
local buildCount = {} function widget:UnitFromFactory(unitID, unitDefID, unitTeam, factoryID, factoryDefID,
userOrders) local n = buildCount[factoryID] --read from table how many units this
factory already built if n == nil then --was the entry empty? n = 0 --if yes, start
counting from 0 end n = n +1 --increase n by
1. (best comment ever) Spring.Echo ("This was unit number " .. n .. " from factory " .. factoryID) buildCount[factoryID] = n --store new buildCount for this
factory end
UnitFromFactory is basically the same as UnitFinished, but has the usefull factoryID
parameter. Why the if n == nil? In Lua everything not initialized is nil (=nothing) and nil can not be used in any math.
(n = n +1 is a math) Btw shorter version: buildCount[factoryID] = (buildCount[factoryID] or 0) + 1
8)
Concatenating a nil is what breaks. Do it like this: Spring.Echo("text", param1, "text",
param2, param3)