|
Post by Quintaxel on Oct 16, 2016 15:03:27 GMT 1
So far I have not seen the use of storing functions into tables in any map script. This is strange, because this one of the more powerful features of Lua.
I have scripted the code below just as an example of what I mean. The script itself is not useful, it's just used as a demonstration.
In this example functiona(a) and functionb(b) do the same thing. They return the square of the argument so the value for (a) or (b) respectively
-- Calling function stored in an array (example) -- Example Quintaxel 15-11-2016
function functiona(a) local result = a*a; return result;end; --function funca(b) local result = b*b; return result;end; (different notation for function)
function functionb(b) --Squares the value of b and returns it. local result = b*b; return result; end;
function DisplayResult () local f = {Func1 = functiona, Func2 = functionb}; --Functions are put into table f local total = (f.Func1(5)) + (f.Func2(3)); -- Adding the result of Func1 with --argument 5 and Func2 with argument 3 DisplayTrace ("Result of function a + result of function b = %g",total); Suicide (); end;
function Init() DisplayTrace ("Init is running"); RunScript ("DisplayResult", 3000); end; Now with this method one could make a custom library with custom BK functions.
|
|
|
Post by Quintaxel on Dec 21, 2016 16:54:21 GMT 1
The "Blitzkrieg SciTE Editor 1.7" is the most popular IDE for writing map scripts. Recently I discovered Geany another popular IDE that IMO is a great improvement in terms of user friendliness over the SciTE editor. Geany has an auto complete function which comes in very handy. There is a portable version of Geany for Windows available so you do not need to install Geany if you want to give it a try. In the above screenshot you can notice that the BK functions are highlighted (light blue). This is not the case in the standard portable version of Geany but if someone is interested than I can post the file and instructions to fix syntax highlighting for BK functions.
|
|
|
Post by Quintaxel on Jan 2, 2017 17:04:32 GMT 1
I always wondered why mappers do not make use of waypoints in maps to get better control over units. Waypoints can be put on the map as Scriptareas. So to make a unit move along a path made of waypoints I made this little function below. It's quite straightforward but should anyone require further explanation then please let me know. function FollowWayPts(...)
--Script by Quintaxel 31-12-2016
local i = 3;
if arg[2] ~= -1 then -- Check if the unit exists while arg[i] ~= nil do
QCmd (arg[1],arg[2],GetScriptAreaParams (arg[i]));
i = i + 1;
end;
end;
Suicide();
end; Now let's say you have created waypoints on your map (Q1,Q2,....,Q20) and would like to move a unit with scriptId 100 along a path made from waypoints Q1 > Q5 > Q7 > Q3 > Q15 then you would just have to use the function as follows. FollowWayPts (0,100, "Q1","Q5","Q7","Q3","Q15");
or using aggressive movement;
FollowWayPts (3,100, "Q1","Q5","Q7","Q3","Q15"); That's it.
In the demo below the function is used as follows;
function WptsSquads()
DisplayTrace ("It Begins !");
FollowWayPts (0,100,"Q1","Q2","Q3","Q9","Q10","Q12");
FollowWayPts (0,200,"Q4","Q8","Q7","Q13");
FollowWayPts (0,300,"Q5","Q6","Q11");
RunScript ("WptsTanks", 12000);
Suicide();
end;
function WptsTanks()
FollowWayPts (0,400,"T1","T4","T2","T3","Q11");
FollowWayPts (0,500,"T1","T2","T3","Q6","Q13");
Suicide();
end;
I know it's a poor demo. Creating this post takes far more time than scripting a function.
|
|
kaoz
General
inter faesces et urinam nascimur
Posts: 1,112
|
Post by kaoz on Jan 2, 2017 17:50:42 GMT 1
Some mappers have used waypoints, but maybe in a different manner. Look at patrolling units and units following (a) specific route(s). It's what makes the AI less of being a sitting duck.
But ok, your script seems to take it take to a higher level. Clearly, you are a good scripter. As a mapper, i am not so good in abstract thinking and therefore i applaud and stand in awe for your lines of code. You should use it to spice up (existing) maps. I do not doubt you could bring interesting additions to existing lua scripts.
|
|
BigJoe
General-major
Posts: 538
|
Post by BigJoe on Jan 2, 2017 18:01:09 GMT 1
|
|
|
Post by Scyooff on Jan 2, 2017 19:20:43 GMT 1
Quintaxel is coming from the future
|
|
|
Post by Quintaxel on Jan 3, 2017 12:31:27 GMT 1
Thanks for your kind words kaoz . I hope to simplify scripting for mappers by creating new functions that do not really require much knowledge of Lua scripting. I often read that mappers get stuck on the scripting part of map making but IMO Lua scripting itself should not stop anyone with the ambition to make maps for BK ! I's however important that a mapper knows what he expects from AI based upon the layout of the map and the possible scenario's. This requires other skills than coding and could be done by using some kind of 'pseudo code' or describing the possible scenarios. eg. - Make tank group of 10 units (Script ID's, 1010 to 1090) assault the trench near bunker - If the tank group loses 3 units or more then retreat the tankgroup to ScriptArea (name scriptarea) - When tanks arrive then repair tanks an replenish lost units. - If the Player loses the AA gun then send bombers to support tank group. This is what a mapper should be able to provide to a scripter. I always considered this to be the more difficult part of map making. Scripting is then merely a matter of translating these expectations into a language that the AI understands. This is more my thing. I might try to spice up an existing map with vanilla gameplay. I will get on this later in this thread. Firts I need to code a function to get the floor and ceiling of a number, an alternative for math.floor and math.ceiling included in the Lua math library. As BK Lua does not include the standard libraries I have to create my own library functions.
|
|
bb
General
Blitzkrieg junkie (tried to quit several times).
Posts: 1,362
|
Post by bb on Jan 28, 2017 3:53:19 GMT 1
Question to the script master: I have an idea to improve the way the AI will react against tanks: I can give one single script number to each player tank between, let´s say, 300 to 310, so, when a tank enter in a AI zone, lets say "defence1", one enemy AT squad (script 100) will just attack the right tank and ignore other secondary targets. The most common way to script this should be
BUT, this code will burden the script with lots of active functions and eventually affect the performance of the game, also is a code painful to write and revise. So, is possible to give one single command to the squad 100 to attack anyone of the tanks between 300 to 310 entering the script zone "defence1" ?
|
|
|
Post by keepitsimple on Jan 28, 2017 15:39:52 GMT 1
Hi bb , The following script might help to make it a little easy to script. DisplayTrace("ScriptRunning!"); function Defence1() AttackUnit(100,301,1,1); DefendArea(200,4,1); end; -- if unit 301 of player is in AreaNr 1 then unit(s) 100 will attack unit 301. -- if 4 of more units of player are in AreaNr 1 then unit(s) 200 will attack the AreaNR 1 function Init() RunScript("Defence1",4000); end; ---------------------------------------------------------------------- -------------- New command: AttackUnit ---------------- ---------------------------------------------------------------------- function AttackUnit(iScriptID,iScriptIDunit,NrUnits,AreaNr) local num = GetNScriptUnitsInArea(iScriptIDunit,"Defence_"..AreaNr); local alive = GetNUnitsInScriptGroup(iScriptID); if num>= NrUnits and alive>=1 then DisplayTrace("AttackUnit %g is attacking %g",iScriptID,iScriptIDunit); Cmd(3, iScriptID, GetScriptAreaParams("Defence_"..AreaNr)); QCmd(1, iScriptID , iScriptIDunit); elseif alive==0 then -- Script stop if AI has no more unit iScriptID left -- Suicide(); end; end; -- iScriptID is number AI unit that should attack -- iScriptIDunit is number of player in area Defence_<AreaNr> with AreaNr=a number -- NrUnits is number of units from player in area Defence_<AreaNr> -- AreaNr is number of the area to defend. The area on the map is called Defence_1 or Defence_2. -------------------------------------------------------- --------------- New command: DefendArea ---------------- ------------------------------------------------------- function DefendArea(iScriptID,Nr, AreaNr) local num = GetNUnitsInArea(0,"Defence_"..AreaNr); local alive = GetNUnitsInScriptGroup(iScriptID); if num>= Nr and alive >= 1 then DisplayTrace("DefendArea %g is attacking" ,iScriptID); Cmd (3, iScriptID ,GetScriptAreaParams("Defence_"..AreaNr)); -- only tanks, spg and infantry will follow this order. Trucks including armored vehicle will not! -- elseif alive==0 then Suicide(); end; end;
|
|
|
Post by Quintaxel on Jan 28, 2017 17:03:22 GMT 1
|
|
bb
General
Blitzkrieg junkie (tried to quit several times).
Posts: 1,362
|
Post by bb on Jan 29, 2017 19:53:25 GMT 1
keepitsimple: Very useful script, thanks a lot, I'll try. Still, this wasnt exactly what I had in mind, I wanted a simple script where I could join all the functions used in my example "atank0, atank1, atank2...", so any unit between the script number 300 to 302 (and so on...) entering in the "defence1" area would be attacked by the unit nr. 100. Thanks
|
|
kaoz
General
inter faesces et urinam nascimur
Posts: 1,112
|
Post by kaoz on Jan 31, 2017 12:48:24 GMT 1
If the squad is already in the zone, you could use the AI settings (in MapEditor) as well. This way you need no scripting.
|
|
kaoz
General
inter faesces et urinam nascimur
Posts: 1,112
|
Post by kaoz on Feb 2, 2017 16:43:31 GMT 1
bb, don't be scared to use many functions. I have a map with at least 30 unique ScriptID's and each have a condition attached. True, i always play -1 game speed (-2 when bombing from enemy plane), but it didn't give me problems.
I believe although, there is a difference when you would place them all under Init() function. Functions running under Init() will keep 'cycling' the functions until they have ended (in the specific time you have set). Init() should only contain basic functions. It is better to start all other functions/triggers from f.e. revealObjective. Start a chain from there and then it is possible to give 30 functions/commands in like 30 seconds. 1 second for each.
This is only my experience, correct me if i'm wrong.
|
|
bb
General
Blitzkrieg junkie (tried to quit several times).
Posts: 1,362
|
Post by bb on Feb 4, 2017 6:05:42 GMT 1
kaoz, thanks, I'm still working with this, I usually use lots of functions without major problems but I wanted to make more clean scripts, also I would like to master more the art of script. To be sincere, I have some problems to understand the "local" comand and the right way to use it in the scripts. If someone could light me here...
|
|
|
Post by keepitsimple on Feb 4, 2017 13:24:26 GMT 1
Hi bb , Variables in programming can be declared global or local. Why the difference? A global variable a computer holds in it's memory. A local variable is one remember as far as the function. Outside the function the variable doesn't exist as far as computer go's. One point of warning with regard to global variables. The computer remember the value from one map to next (if have not stop the game in between). The following statement is often us SetIGlobarVar("GameObjective1",1). With a fresh start the computer has no memory of a value of GameObjective1. Add hence, GetIGlobarVar("GameObjective1",0)= 1 is not true. However, if the previous game the player made SetIGlobarVar("GameObjective1",1) then this statement is true in next game. This why you should always initials your global variables. If at start of your script you declare SetIGlobarVar("GameObjective1",0); then you make sure that the Game engine doesn't remember a previous value.
|
|