Awesome, I also found it a bit unsightly.Tobi wrote:In master, I removed unitID argument to all Lua unit script related call-ins and call-outs: it's available as upvalue anyway., and seeing "unitID unitID unitID" everywhere drives me crazy
If you already wrote some script, you can just remove the unitID argument from all call-ins and pretty much all Spring.UnitScript.* functions. (e.g. Turn, Move, etc.)
I'll try to remember updating the wiki shortly.
Lua unit scripting
Moderator: Moderators
Re: Lua unit scripting
Re: Lua unit scripting
For those interested; I've experimented a little bit with aspect oriented programming-like techniques when making a unit script.
For example, in S44 there are some units that are normally stealthed, but become radar visible for a short duration after firing. Excluding this part the script for such unit may be nearly identical to that of other units, and there may also be units with a totally different script that still have exactly this behavior.
In either case, a traditional implementation would definitely result in code duplication, or if-then hell.
So I created a small function 'aop_include' which includes a file, and joins all functions in script table to functions already existing in script table. (That corresponds to following JPM: join point is function execution, pointcut includes only functions in script table.)
If you don't know about AOP, you can view what it does simply as prepending the statements of the script functions in the included file to the functions that already exist at the point the include is executed.
In the end this resulted in a file for the stealth-unless-firing that looks like this (a bit simplified), and can be added with a single line 'aop_include "stealth.lua"' to any other unit script, while keeping the behavior of already defined Create/FireWeapon1 functions.
instead of some ugly 'if VISIBLE_PERIOD then ... end' changes at the respective places in the generic tank script I made.
Note that I have no plans (yet) to include this by default in the unit script framework. It's just a nice example of what you can do with Lua unit scripts, and may give others ideas
For example, in S44 there are some units that are normally stealthed, but become radar visible for a short duration after firing. Excluding this part the script for such unit may be nearly identical to that of other units, and there may also be units with a totally different script that still have exactly this behavior.
In either case, a traditional implementation would definitely result in code duplication, or if-then hell.
So I created a small function 'aop_include' which includes a file, and joins all functions in script table to functions already existing in script table. (That corresponds to following JPM: join point is function execution, pointcut includes only functions in script table.)
If you don't know about AOP, you can view what it does simply as prepending the statements of the script functions in the included file to the functions that already exist at the point the include is executed.
In the end this resulted in a file for the stealth-unless-firing that looks like this (a bit simplified), and can be added with a single line 'aop_include "stealth.lua"' to any other unit script, while keeping the behavior of already defined Create/FireWeapon1 functions.
Code: Select all
local VISIBLE_PERIOD = VISIBLE_PERIOD or 5000
function script.Create()
SetUnitValue(COB.STEALTH, 1)
end
local function Stealth()
SetUnitValue(COB.STEALTH, 0)
Sleep(VISIBLE_PERIOD)
SetUnitValue(COB.STEALTH, 1)
end
function script.FireWeapon1()
StartThread(Stealth)
end
Note that I have no plans (yet) to include this by default in the unit script framework. It's just a nice example of what you can do with Lua unit scripts, and may give others ideas
Re: Lua unit scripting
I prefer the pascal-like OOP way via `inherited`, so you have a much better control _when_ code gets executed 
(I even implemented something like that for Chili's class system)
But sure a lot of such unitscript code is independent and doesn't conflict, so the AOP way will save a lot `inherited`s here.
(I even implemented something like that for Chili's class system)
But sure a lot of such unitscript code is independent and doesn't conflict, so the AOP way will save a lot `inherited`s here.
Re: Lua unit scripting
You have to explicitly make a chain of subclasses if you want to add multiple aspects to a single class in this case, right?
(I've never developed in pascal, am I right `inherited` is basically the same as NameOfBaseClass::Method(...) in C++ or super.Method(...) in Java?)
(I've never developed in pascal, am I right `inherited` is basically the same as NameOfBaseClass::Method(...) in C++ or super.Method(...) in Java?)
Re: Lua unit scripting
2x yupTobi wrote:You have to explicitly make a chain of subclasses if you want to add multiple aspects to a single class in this case, right?
(I've never developed in pascal, am I right `inherited` is basically the same as NameOfBaseClass::Method(...) in C++ or super.Method(...) in Java?)
Re: Lua unit scripting
This is similar to wordpress hooks then? In wordpress some code will define an action like in the footer there's a callout for an action, then plugins can use this as a hook to add their own callouts to print stuff out.
- CarRepairer
- Cursed Zero-K Developer
- Posts: 3359
- Joined: 07 Nov 2007, 21:48
Re: Lua unit scripting
Bumple.smoth wrote:CarRepairer wrote:No conversion tool yet?
You are making me *FRUMPLE*
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
Is it possible to call a lua script from a tdf unit definition?
EDIT:
Nevermind - made a stupid mistake preventing it from working...
EDIT:
Nevermind - made a stupid mistake preventing it from working...
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
What would this look like in Lua?
Code: Select all
while( get BUILD_PERCENT_LEFT )
{
sleep 400;
}
Re: Lua unit scripting
Umm, I've not done too much yet Lua Unitscripting yet, so I'm not so sure on how to put the pieces together (and I may be mistaken with things), but some info:
buildProgress should then correspond to the value you get from "get BUILD_PERCENT_LEFT"
(The first four values returned [which , since we don't want them, we just "skip" via the "_"] are: health, maxHealth, paralyzeDamage and captureProgress). From here.
corresponds to the other bit. (From here)
Erm, while loops, erm... haven't put to much use, would have to guess on the syntax, sorry.
Code: Select all
_,_,_,_,buildProgress = Spring.GetUnitHealth(unitID)
(The first four values returned [which , since we don't want them, we just "skip" via the "_"] are: health, maxHealth, paralyzeDamage and captureProgress). From here.
Code: Select all
Spring.UnitScript.Sleep ( 400 )Erm, while loops, erm... haven't put to much use, would have to guess on the syntax, sorry.
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
The Sleep and the while loop isn't the problem. It's about how to determine when the building is built (or next to be completed as afaik that function gets validated when the building is 99% complete or something)...
I'll have a look at what you linked...
I'll have a look at what you linked...
Re: Lua unit scripting
Ah, ok. I'm afraid the documentation I linked to won't really help to answer that question - I linked it more as a place to look in for future cases of certain unitinfo or such that you want.
My guess is as good as yours, but I would have assumed buildProgress is either in percent or finished corresponds to maxDamage (ie maximum HP). Percent seems more likely to me. The quickest way to find out (besides someone here enlightening us) is probably to immediately after setting that variable (oh, you'll need to declare the variable somewhere of course...). Best in a place that it'll get called all the time during construction!
Edit: Oh, and of course if it is in percent you'd just need to do to check for finished
or / (to check it's not / less than a hunded)
My guess is as good as yours, but I would have assumed buildProgress is either in percent or finished corresponds to maxDamage (ie maximum HP). Percent seems more likely to me. The quickest way to find out (besides someone here enlightening us) is probably to
Code: Select all
Spring.Echo (buildProgress)Edit: Oh, and of course if it is in percent you'd just need to do
Code: Select all
buildProgress >= 100or
Code: Select all
buildProgress ~= 100 Code: Select all
buildProgress < 100 - CarRepairer
- Cursed Zero-K Developer
- Posts: 3359
- Joined: 07 Nov 2007, 21:48
Re: Lua unit scripting
BEWARE! This code is in cob which evaluates 0 to false (yuck!). It returns some sort of number ranging from 0-1 or 0-100, and when the unit hits 100% built this would return 0 because of the "LEFT." Lua does not evaluate 0 as false so when you do convert your scripts, be aware of this fact and don't forget the ~= 0 part. If you do forget, lua will loop this forever.Master-Athmos wrote:What would this look like in Lua?
Code: Select all
while( get BUILD_PERCENT_LEFT ) { sleep 400; }
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
Ok so if I use Spring.GetUnitHealth what would I have to do to write the buildprogress number into a variable?
Re: Lua unit scripting
Code: Select all
local buildProgress = select(5, Spring.GetUnitHealth(unitID))-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
Thanks but is there anything else I have to take care of? I echoed the variable but it always is nil...
EDIT:
Ah no I guess it was my bad...
EDIT:
Ah no I guess it was my bad...
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
Ok so I ran into another problem while doing the Bladewing script. When the deactivate script part starts to run (when landing) it should run an animation. Unfortunately it "crashes" i.e. refuses to work at any WaitForMove command and I don't understand as to why. So here's the error report and I also zipped up all relevant files so you can try it for yourself (removed)...
Any suggestions?
Code: Select all
[ 30162] LuaRules::RunCallIn: error = 2, CLuaUnitScript::Deactivate, [string "scripts/corbladew.lua"]:47: attempt to call global 'WaitforMove' (a nil value)
Last edited by Master-Athmos on 11 Mar 2010, 18:56, edited 1 time in total.
-
Master-Athmos
- Posts: 916
- Joined: 27 Jun 2009, 01:32
Re: Lua unit scripting
It's the only part of the script that contains any WaitForMove commands and it's called exactly after a Move order (each)...
EDIT:
Ah ok you meant the spelling - will check that...
EDIT:
Ah ok you meant the spelling - will check that...
Last edited by Master-Athmos on 11 Mar 2010, 18:41, edited 1 time in total.
Re: Lua unit scripting
you said WaitForMove, which follows casing conventions, but according to that error, you tried to call WaitforMove (lowercase F)error wrote:attempt to call global 'WaitforMove'
