Lua unit scripting - Page 4

Lua unit scripting

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6241
Joined: 29 Apr 2005, 01:14

Re: Lua unit scripting

Post by FLOZi »

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.
Awesome, I also found it a bit unsightly. :-)
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Lua unit scripting

Post by Tobi »

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.

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
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 ;-)
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Lua unit scripting

Post by jK »

I prefer the pascal-like OOP way via `inherited`, so you have a much better control _when_ code gets executed :mrgreen:
(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.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Lua unit scripting

Post by Tobi »

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?)
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Lua unit scripting

Post by jK »

Tobi 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?)
2x yup
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Lua unit scripting

Post by AF »

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.
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: Lua unit scripting

Post by CarRepairer »

smoth wrote:
CarRepairer wrote:No conversion tool yet?

Image

You are making me *FRUMPLE*
Bumple.
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

Is it possible to call a lua script from a tdf unit definition?

EDIT:
Nevermind - made a stupid mistake preventing it from working... :regret:
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

What would this look like in Lua?

Code: Select all

		while( get BUILD_PERCENT_LEFT )
	{
		sleep 400;
	}
SeanHeron
Engines Of War Developer
Posts: 614
Joined: 09 Jun 2005, 23:39

Re: Lua unit scripting

Post by SeanHeron »

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:

Code: Select all

_,_,_,_,buildProgress = Spring.GetUnitHealth(unitID)
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.

Code: Select all

Spring.UnitScript.Sleep ( 400 )
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.
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

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...
SeanHeron
Engines Of War Developer
Posts: 614
Joined: 09 Jun 2005, 23:39

Re: Lua unit scripting

Post by SeanHeron »

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

Code: Select all

Spring.Echo (buildProgress)
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

Code: Select all

buildProgress >= 100
to check for finished

or

Code: Select all

buildProgress ~= 100 
/

Code: Select all

buildProgress < 100 
(to check it's not / less than a hunded)
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: Lua unit scripting

Post by CarRepairer »

Master-Athmos wrote:What would this look like in Lua?

Code: Select all

		while( get BUILD_PERCENT_LEFT )
	{
		sleep 400;
	}
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
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

Ok so if I use Spring.GetUnitHealth what would I have to do to write the buildprogress number into a variable?
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Lua unit scripting

Post by Tobi »

Code: Select all

local buildProgress = select(5, Spring.GetUnitHealth(unitID))
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

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... :P
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

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

Code: Select all

[  30162] LuaRules::RunCallIn: error = 2, CLuaUnitScript::Deactivate, [string "scripts/corbladew.lua"]:47: attempt to call global 'WaitforMove' (a nil value)
Any suggestions?
Last edited by Master-Athmos on 11 Mar 2010, 18:56, edited 1 time in total.
User avatar
aegis
Posts: 2456
Joined: 11 Jul 2007, 17:47

Re: Lua unit scripting

Post by aegis »

WaitforMove vs WaitForMove?
Master-Athmos
Posts: 916
Joined: 27 Jun 2009, 01:32

Re: Lua unit scripting

Post by Master-Athmos »

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...
Last edited by Master-Athmos on 11 Mar 2010, 18:41, edited 1 time in total.
User avatar
aegis
Posts: 2456
Joined: 11 Jul 2007, 17:47

Re: Lua unit scripting

Post by aegis »

error wrote:attempt to call global 'WaitforMove'
you said WaitForMove, which follows casing conventions, but according to that error, you tried to call WaitforMove (lowercase F)
Post Reply

Return to “Engine”