Map Database  •  FAQ  •  RSS  •  Login

Script changes in RC3

<<

Lewin

User avatar

KaM Remake Developer

Posts: 3822

Joined: 16 Sep 2007, 22:00

KaM Skill Level: Skilled

ICQ: 269127056

Website: http://lewin.hodgman.id.au

Yahoo Messenger: lewinlewinhodgman

Location: Australia

Post 03 Jun 2013, 05:27

Script changes in RC3

Hi guys,
RC3 will see some major changes to the dynamic scripting system, and seeing as lots of people are trying out scripting and making their own missions I thought I should explain the changes. At the moment we're still in beta so we feel it's okay to make changes like this which require everyone to fix their scripts, but for official releases we'll try to keep the backwards compatibility a bit better.



Text and translations
We've changed the way you fetch text from the LIBX translation files. Instead of using States.Text and States.TextFormatted you now use "markup" to fetch strings:
  Code:
Actions.OverlayTextSet(5, 'Some text before my translated bit <$1> some text after')
If you've set text ID 1 to 'Translated Message' then that command will display to player 5:
'Some text before my translated bit Translated Message some text after'
So each <$123> gets replaced with the corresponding text from the LIBX file (text ID 123 in that case).

Why did we do this? Because it's a bad idea to let the script access text directly from the translations. It could cause errors in multiplayer because the code could run differently depending on your language (for example "if States.Text(1) = 'something' then"). That was also the reason why strings weren't allowed as global variables in the past, because they would cause save files to become inconsistent.

The text related commands have changed because of this:
  • Removed: States.Text and States.TextFormatted
  • Renamed: Actions.SetOverlayText to Actions.OverlayTextSet
  • Added: Actions.OverlayTextSetFormatted
  • Added: Actions.OverlayTextAppend
  • Added: Actions.OverlayTextAppendFormatted
  • Added: Actions.ShowMsgFormatted


New types allowed as global variables
You can now use the follow types as global variables:
  • Enumerations
  • Sets
  • Records (like struct from C)
  • Dynamic arrays (non-fixed length)
  • Strings
  • Multi-dimensional arrays
This includes any combination of these things that you can imagine! So for example you could have a multi-dimensional dynamic array of records containing a set of an enumeration and a string, as I show here with my variable AllTheThings:
  Code:
type TDay = (dMon, dTue, dWed, dThu, dFri, dSat, dSun); TMyFancyRecord = record BusyDays: set of TDay; MyName: string; FavouriteDay: TDay; end; var AllTheThings: array of array of TMyFancyRecord; procedure OnMissionStart; var I: Integer; begin //Allocate space in arrays //After these lines the maximum element you can access would be: AllTheThings[2][5] SetLength(AllTheThings, 3); for I:=0 to 2 do SetLength(AllTheThings[I], 6); AllTheThings[0][0].MyName := 'Lewin'; AllTheThings[0][0].FavouriteDay := dTue; AllTheThings[0][0].BusyDays := [dMon, dThu, dSat, dSun]; end; procedure OnTick; begin if dSun in AllTheThings[0][0].BusyDays then Actions.OverlayTextSet(-1, AllTheThings[0][0].MyName + ' is busy on Sunday'); end;
You can learn how to use any of these types in a Delphi/Pascal tutorial. Unfortunately PascalScript doesn't support all the features that Delphi does (such as "if dFri > dMon then", SetLength with multiple dimensions in one call, etc.), but it's got most of them and is still very powerful.



New commands
  • States.UnitDirection
  • States.HouseSchoolQueue
  • States.HouseWeaponsOrdered
  • States.GetAllUnits
  • States.GetAllHouses
  • States.GetAllGroups
  • States.GroupColumnCount
  • States.HouseIsComplete
  • States.IsFieldAt
  • States.IsWinefieldAt
  • States.IsRoadAt
  • States.PlayerWareDistribution
  • Actions.HouseWeaponsOrderSet
  • Actions.HouseSchoolQueueRemove
  • Actions.GiveWeapons
  • Actions.PlayerAddDefaultGoals
  • Actions.PlayWAV
  • Actions.PlayWAVAtLocation
  • Actions.PlayerWareDistribution
  • Actions.PlayerShareFog
  • Actions.PlanRemove
  • Actions.HouseDisableUnoccupiedMessage
  • Actions.AIRecruitLimit
  • Added parameter "Silent" to Actions.HouseDestroy
  • -1 can be used to mean "all players" in the following commands:
    • States.IsFieldAt
    • States.IsWinefieldAt
    • States.IsRoadAt
    • Actions.OverlayTextSet
    • Actions.OverlayTextSetFormatted
    • Actions.OverlayTextAppend
    • Actions.OverlayTextAppendFormatted
    • Actions.ShowMsg
    • Actions.ShowMsgFormatted
    • Actions.PlayWAV
    • Actions.PlayWAVAtLocation
As always, read the wiki page to learn how any of these commands work.

Questions/comments are welcome :)
Cheers,
Lewin.
<<

sado1

User avatar

Council Member

Posts: 1430

Joined: 21 May 2012, 19:13

KaM Skill Level: Skilled

Post 03 Jun 2013, 08:32

Re: Script changes in RC3

Thanks for all the stuff you added, now I surely will have more freedom in my crazy scripting ideas :) However, I don't like nagging people for something multiple times, but is it possible to also implement GiveRecruits (for adding recruits to the barracks automatically) before this release gets official? It seems that this one will be the newest official release on 1st September (the end of the dynamic scripts competition; and also the release date for my entry for it), and I want my map to be playable on the public version as well. I could just add schools for each player (which I'm going to do for the time being), but using schools is not going to fit into my idea well.
<<

Siegfried

User avatar

Knight

Posts: 494

Joined: 24 Jul 2009, 22:00

Post 03 Jun 2013, 09:39

Re: Script changes in RC3

First a request: please don't do the 2 weeks until the final release! This would mean one single weekend to implement the changes for us, that's too little time to go. A second weekend would be very much appreciated.

The changes are good. I would have needed the dynamic arrays yesterday, now I've found a complicated solution that works with a static array. Well, that's bad luck for me ;)

The global strings are very welcome, at least from my side. As well as the enumerations. Many thanks that you picked those suggestions! :) And records ... well, I haven't used any of them, yet I can say that I love them.

But the more I work with Pascal, the stranger it gets. I almost see no difference between a set and a dynamic array. Is it the same unneccessary overcomplication like the function/procedure-thing or the rules for the semicolon? To me it seems like a set is a lightweight dynamic array with some limitations which the 'real' dynamic array does not have. So where exactly is the advantage of using a set?

And a last question: do you plan to implement any functions that allow a further manipulation of displayed text?
<<

Lewin

User avatar

KaM Remake Developer

Posts: 3822

Joined: 16 Sep 2007, 22:00

KaM Skill Level: Skilled

ICQ: 269127056

Website: http://lewin.hodgman.id.au

Yahoo Messenger: lewinlewinhodgman

Location: Australia

Post 03 Jun 2013, 10:09

Re: Script changes in RC3

We don't plan to add too many more script commands before release because we don't want to do any complex work which could introduce bugs. I'll discuss it with Krom. Of course we'd like to add every command that has been requested but if we do that the release won't be ready until Christmas.

There are lots of differences between sets and arrays. Sets don't have any order, they're just a collection of items (so the sets [1,2] is exactly the same as [2,1]). Remember set theory from maths (or even venn diagrams)? A lot of that applies. You can use set operations like addition, subtraction, intersection, etc. You can also check if one set is a subset of another.

They're useful for stuff like properties of an object. For example, in the KaM Remake engine each tile on the map has a set of passibility (canWalk, canBuild, canMakeRoads, etc.) which tells you what is allowed on that specific tile. There can be any combination of these items, and you can easy check "can I walk on this tile". You can also check "can I walk or build on this tile" by checking if [canWalk, canBuild] is a subset of the passability. Of course we could have a separate boolean for each of these properties (canWalk, canBuild, etc.: Boolean), but that would be much less efficient and less elegant. That's what we mostly use them for in the Remake, collecting multiple properties or states into one thing.

But the biggest difference is the way they are implemented underneath. A set is implemented as a bitmask (like you sometimes see in C where you OR bits together to store properties of an item, each bit specifying whether a certain property is enabled). This means operations on them are VERY fast, because the CPU loves working with bitmasks. Operations like "in" take only a few x86 instructions when compiled. Adding and removing items from sets is simply boolean operations (OR/ANDing bitmasks together), so that's equally as efficient.

Another random example where we use sets is ignoring network commands that are not allowed during peacetime. We have a constant: "BlockedByPeaceTime: set of TGameInputCommandType" which contains all the commands you are not allowed to use during peacetime (TGameInputCommandType is an enumeration). Then when we get a command we check "if CommandType in BlockedByPeaceTime then Exit;" so we don't process the command. Simple, elegant and efficient :) I'm actually not sure how you could accomplish something like that without sets...

The difference between functions and procedures is simple, a function returns something and a procedure doesn't. Think of a procedure as a void function from C. I think it can make the code easier to read in large classes because it gives you a clear distinction between "getters" and "setters". But it's really not a big difference, it's only strange if you're not used to it.
<<

Krom

User avatar

Knights Province Developer

Posts: 3280

Joined: 09 May 2006, 22:00

KaM Skill Level: Fair

Location: Russia

Post 03 Jun 2013, 10:42

Re: Script changes in RC3

I would not like to delay the release much longer because it is already long since previous release (9th November 2012). And as Lewin pointed out, adding script commands is an endless process. Besides each new scripting command needs testing and sometimes trivial commands trigger major bugs due to flaws in our design.

We might release a follow up release in several weeks after this one, as we usually did in the past - fixing minor bugs that got away in beta-testing.
Knights Province at: http://www.knightsprovince.com
KaM Remake at: http://www.kamremake.com
Original MBWR/WR2/AFC/FVR tools at: http://krom.reveur.de
<<

sado1

User avatar

Council Member

Posts: 1430

Joined: 21 May 2012, 19:13

KaM Skill Level: Skilled

Post 03 Jun 2013, 10:56

Re: Script changes in RC3

OK, I felt a bit bad about myself already, while writing my last selfish post :) Even if you don't do a follow-up release, I'd appreciate if you just implemented the command I need, in some time after this release - I can just compile a svn revision, give it to a few people and test my script with them. Now let's try to get this release out as soon as possible, it's quite some time since the last one indeed.
<<

Siegfried

User avatar

Knight

Posts: 494

Joined: 24 Jul 2009, 22:00

Post 03 Jun 2013, 10:59

Re: Script changes in RC3

OK, it took some time but with your explanation I realize now what a set is. It cannot have two times the same object, right? I pre-judged the sets from some poor examples that I found online. If this was an exam, I would have failed miserably ;) C#, php and javascript don't have sets, so I almost forgot about them.

With those additions PascalScript seems to be almost feature-complete, so we can use object-orientated solutions. That's awesome!
I just wonder, are there equivalents for stdlib-maps, too?
<<

Lewin

User avatar

KaM Remake Developer

Posts: 3822

Joined: 16 Sep 2007, 22:00

KaM Skill Level: Skilled

ICQ: 269127056

Website: http://lewin.hodgman.id.au

Yahoo Messenger: lewinlewinhodgman

Location: Australia

Post 03 Jun 2013, 11:15

Re: Script changes in RC3

That's right, sets can only contain each item once, somehow I forgot to mention that in my explanation :P It's interesting, not many languages have sets and yet I find them really useful.

It's not object oriented yet because we don't support classes. That's potentially possible in the future but adds complications.

What's an stdlib-map?
EDIT: You mean this?
http://www.cplusplus.com/reference/map/map/
That's not a standard feature in PascalScript/Delphi 7. I believe newer versions of Delphi (XE/XE2) have an equivalent for it (they also support generics which is kind of required to do it properly). It probably wouldn't be too hard to write a class that does it in a simple kind of way (using TObject instead of generics). But we don't use anything like that in the KaM Remake engine, we mostly just use plain old lists.
<<

Siegfried

User avatar

Knight

Posts: 494

Joined: 24 Jul 2009, 22:00

Post 03 Jun 2013, 11:41

Re: Script changes in RC3

I really should stop posting here while doing other things. I am only confusing you ;)

I meant the C++ STL. stdlib is of course the actual implementation of the standard template library.
C++ STL has many containers like vectors, sets, arrays, stacks etc. It also has a map, which is an array that can be accessed with any class rather than just with integer. So you can imagine something like
  Code:
map MMap; MMap["text"] = 1;
This is also possible in php.

*edit: exactly what you edited into your post
<<

Lewin

User avatar

KaM Remake Developer

Posts: 3822

Joined: 16 Sep 2007, 22:00

KaM Skill Level: Skilled

ICQ: 269127056

Website: http://lewin.hodgman.id.au

Yahoo Messenger: lewinlewinhodgman

Location: Australia

Post 03 Jun 2013, 12:12

Re: Script changes in RC3

I meant the C++ STL. stdlib is of course the actual implementation of the standard template library.
C++ STL has many containers like vectors, sets, arrays, stacks etc. It also has a map, which is an array that can be accessed with any class rather than just with integer. So you can imagine something like
  Code:
map MMap; MMap["text"] = 1;
This is also possible in php.
No that's not possible. Although you can index arrays by enumerations which gives a similar affect:
  Code:
type TDay = (dMon, dTue, dWed, dThu, dFri, dSat, dSun); var FreeTimeEachDay: array[TDay] of Integer; //Then you can do stuff like: FreeTimeEachDay[dMon] := 5;
<<

Tef

User avatar

Lance Carrier

Posts: 64

Joined: 15 Apr 2013, 15:12

KaM Skill Level: Skilled

Post 04 Jun 2013, 11:47

Re: Script changes in RC3

Awesome changes!

However, after a quick inspection I noticed an error in the wiki page. For example, under States I can see OverlayTextSetFormatted, and two lines below that: OverlayTextSetFormatted? I guess you mean OverlayTextAppendFormatted for that second command? :wink:. Maybe somebody could re-check the entire wiki-page for correctness? I'll provide more feedback in the coming days. Keep up the good work!
<<

Lewin

User avatar

KaM Remake Developer

Posts: 3822

Joined: 16 Sep 2007, 22:00

KaM Skill Level: Skilled

ICQ: 269127056

Website: http://lewin.hodgman.id.au

Yahoo Messenger: lewinlewinhodgman

Location: Australia

Post 04 Jun 2013, 12:02

Re: Script changes in RC3

Awesome changes!

However, after a quick inspection I noticed an error in the wiki page. For example, under States I can see OverlayTextSetFormatted, and two lines below that: OverlayTextSetFormatted? I guess you mean OverlayTextAppendFormatted for that second command? :wink:. Maybe somebody could re-check the entire wiki-page for correctness? I'll provide more feedback in the coming days. Keep up the good work!
Thanks for reporting that, I fixed it. Checking the entire wiki is a mammoth task that would probably take an hour or two because there's so many commands and parameters now. I don't think it's worth the effort, if further copy-paste mistakes are noticed we can fix them any time.
<<

Krom

User avatar

Knights Province Developer

Posts: 3280

Joined: 09 May 2006, 22:00

KaM Skill Level: Fair

Location: Russia

Post 04 Jun 2013, 12:16

Re: Script changes in RC3

When keeping everything alphabetical we can use Merge tools to certain extent to verify parameter names and arguments (with some smart replacements to make structures more alike)
Knights Province at: http://www.knightsprovince.com
KaM Remake at: http://www.kamremake.com
Original MBWR/WR2/AFC/FVR tools at: http://krom.reveur.de
<<

Siegfried

User avatar

Knight

Posts: 494

Joined: 24 Jul 2009, 22:00

Post 04 Jun 2013, 19:58

Re: Script changes in RC3

I'm running crazy with Pascal.

OK, let's look at the following code. It works:
  Code:
var TEAM_OF_PLAYER: array[1..8] of integer; TEAM_MEMBERS: array[0..4] of set of byte; procedure DoSomething; var i: integer; begin for i := 1 to 4 do TEAM_MEMBERS[i] := []; for i := 1 to 8 do TEAM_MEMBERS[TEAM_OF_PLAYER[i]] := TEAM_MEMBERS[TEAM_OF_PLAYER[i]] + [Byte(65537)]; end;
This validates.
Let's introduce a minor change:
  Code:
var TEAM_OF_PLAYER: array[1..8] of integer; TEAM_MEMBERS: array[0..4] of set of byte; procedure DoSomething; var i: integer; begin for i := 1 to 4 do TEAM_MEMBERS[i] := []; for i := 1 to 8 do TEAM_MEMBERS[TEAM_OF_PLAYER[i]] := TEAM_MEMBERS[TEAM_OF_PLAYER[i]] + [Byte(i)]; end;
If you don't see it at first glance: I've changed the last part of the second for-loop from [Byte(65537)] to [Byte(i)]. And suddenly it does not validate any more:
  Code:
[Error] (10:100): Type mismatch
But I don't quite understand why? 65537 is interpreted as integer - that's why I do the casting with Byte(65537). And the number needs >16bit to be drawn, so it should not be different from a defined integer,
But i is explicitly defined as an integer, and it does not work. Why?

Are you sure this thing is bug-free?
<<

Krom

User avatar

Knights Province Developer

Posts: 3280

Joined: 09 May 2006, 22:00

KaM Skill Level: Fair

Location: Russia

Post 05 Jun 2013, 05:17

Re: Script changes in RC3

Try changing it to "i: Byte" and see how it goes.
Usually you would not need "set of Byte" either, you would declare it "type TPlayerIndex = (p1,p2,p3,p4,p5,p6,p7,p8); var a: set of TPlayerIndex; i: TPlayerIndex; for i := Low(TPlayerIndex) to High(TPlayerIndex) do .."
Knights Province at: http://www.knightsprovince.com
KaM Remake at: http://www.kamremake.com
Original MBWR/WR2/AFC/FVR tools at: http://krom.reveur.de

Return to “Feedback / Discussion”

Who is online

Users browsing this forum: No registered users and 10 guests