Map Database  •  FAQ  •  RSS  •  Login

Dynamic Script Usage Questions

<<

Krom

User avatar

Knights Province Developer

Posts: 3280

Joined: 09 May 2006, 22:00

KaM Skill Level: Fair

Location: Russia

Post 12 Apr 2013, 05:19

Re: Dynamic Script Usage

@Ben: Please be more specific in error's description. What is exactly happening, do you get an error message, or houses aren't blocked/unlocked?
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
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 12 Apr 2013, 05:31

Re: Dynamic Script Usage

Nothing in the dynamic script is working at all. I am just getting this error:

Image
I used to spam this forum so much...
<<

Krom

User avatar

Knights Province Developer

Posts: 3280

Joined: 09 May 2006, 22:00

KaM Skill Level: Fair

Location: Russia

Post 12 Apr 2013, 05:45

Re: Dynamic Script Usage

That is because HouseAllow is not a state, it is an action. You need to change it to Actions.HouseAllow(...).
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
<<

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 12 Apr 2013, 06:41

Re: Dynamic Script Usage

Yeah looks like I didn't write that example script properly, I was doing it in a hurry without checking. Remember it this way:

States are when you query the game without changing anything. For example: "How many warriors does player X have?", "How long has the game been running?", "What type of house is this?"

Actions are when you change something in the game, for example "Add a group of warriors for player X", "Show a message to the player", "Allow the player to build this house".

Events (OnSomething) are when the game lets you know that some event occurred, for example "A house was built", "a unit died", "game tick occurred".
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 12 Apr 2013, 13:10

Re: Dynamic Script Usage

Thanks, Krom and Lewin. I'll see if I can get it working now.

And thanks also, Lewin, for your explanation. That helps a bit.

EDIT:

Okay, it is finally recognizing the code, but now it's doing something funky. It is disabling all buildings except the inn, which shouldn't be happening because the inn's ID (27) isn't in my code:
  Code:
procedure OnMissionStart; var I, P: Integer; begin for P := 0 to 5 do if States.PlayerEnabled(P) then begin for I := 0 to 28 do Actions.HouseAllow(P, I, False); Actions.HouseAllow(P, 11, True); Actions.HouseAllow(P, 13, True); end; end; procedure OnHouseBuilt(aHouse: Integer); begin if States.HouseType(aHouse) = 11 then Actions.HouseAllow(States.HouseOwner(aHouse), 13, True); if States.HouseType(aHouse) = 14 then Actions.HouseAllow(States.HouseOwner(aHouse), 9, True); end;
Totally confused... :?
I used to spam this forum so much...
<<

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 12 Apr 2013, 14:07

Re: Dynamic Script Usage

Thanks for reporting, there was a bug in HouseAllow which made it work the opposite way expected. It works as "HouseBlock". So for now if you switch all cases of "True" to "False" it will work :)
But next RC it will be fixed so that HouseAllow(A, B, True) makes the house allowed, and False makes it blocked.
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 12 Apr 2013, 15:07

Re: Dynamic Script Usage

I thought that this was what was happening, so I actually tried switching everything to False, but it still didn't work.
I must have overlooked something. I'll go try again.
I used to spam this forum so much...
<<

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 12 Apr 2013, 15:26

Re: Dynamic Script Usage

I thought that this was what was happening, so I actually tried switching everything to False, but it still didn't work.
I must have overlooked something. I'll go try again.
Don't switch everything to false, swap true with false and false with true.
Also note that the example I gave you wasn't complete, you need to customise what happens in OnHouseBuilt so building the school allows the inn, etc. You also need to allow everything when they build the sawmill to make it use the "normal" unlock order after that.
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 12 Apr 2013, 16:10

Re: Dynamic Script Usage

Don't switch everything to false, swap true with false and false with true.
Yeah that's what I meant. I figured it out; though, and it is working fine :)
Also note that the example I gave you wasn't complete, you need to customise what happens in OnHouseBuilt so building the school allows the inn, etc. You also need to allow everything when they build the sawmill to make it use the "normal" unlock order after that.
Yeah I did it the hard way: manually doing each unlock. I guess that I wasn't thinking. Oh well. More experience I guess :P

Also, if I just wanted to disable just two buildings, and not, say 9-27, could I just do two IDs instead of a range?
Last edited by Ben on 13 Apr 2013, 01:57, edited 1 time in total.
I used to spam this forum so much...
<<

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 12 Apr 2013, 16:44

Re: Dynamic Script Usage

Also, if I just wanted to disable just two buildings, and not, say 9-27, could I just do two IDs instead of a range?
Yes that might be smarter in this case. Just run Actions.HouseAllow twice with fixed IDs (instead of I from the loop), and remove the for loop completely.
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 12 Apr 2013, 17:21

Re: Dynamic Script Usage

Thanks again.

Sado and I were trying to figure out if we could use the OnTick even to run after more than just 1 tick. For example, say I wanted a unit to be created after 1000 ticks. How would I do this?
I used to spam this forum so much...
<<

The Dark Lord

User avatar

King Karolus Servant

Posts: 2154

Joined: 29 Aug 2007, 22:00

KaM Skill Level: Veteran

Location: In his dark thunderstormy castle

Post 12 Apr 2013, 21:23

Re: Dynamic Script Usage

I'm having troubles too. This error occurs: [Error] (8:26): Type mismatch
I'm using the exact same script as before, when it worked just fine. What's changed?
Also, can't it just ignore the scripts that aren't working? Currently nothing works if there's just one tiny mistake; that's pretty annoying, I can't do a thing right now.
  Code:
var Message0Sent: Boolean; Attack1Started, Attack2Started, Attack3Started, Attack4Started, Attack5Started, Attack6Started: Boolean; Attack1Defeated, Attack2Defeated, Attack3Defeated, Attack4Defeated, Attack5Defeated, Attack6Defeated: array [0..3] of Boolean; procedure ShowMsgToPlayers(aMsg: Integer); begin Actions.ShowMsg(0, aMsg); Actions.ShowMsg(1, aMsg); Actions.ShowMsg(2, aMsg); Actions.ShowMsg(3, aMsg); end; procedure CheckAttack1Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack1Defeated[aPlayer] = false) and (States.GameTime > 2400) then begin Actions.GiveWares(aPlayer, 1, 50); Actions.GiveWares(aPlayer, 2, 15); Actions.GiveWares(aPlayer, 7, 15); Actions.ShowMsg(aPlayer, 2); Attack1Defeated[aPlayer] := True; //Actions.SetOverlayText(0; 1; 2; 3, States.TextFormatted(30, [States.PlayerColorText(aPlayer), States.PlayerName(aPlayer)])); end; end; procedure CheckAttack2Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack2Defeated[aPlayer] = false) and (States.GameTime > 6600) then begin Actions.GiveWares(aPlayer, 1, 40); Actions.GiveWares(aPlayer, 2, 15); Actions.GiveWares(aPlayer, 7, 15); Actions.ShowMsg(aPlayer, 4); Attack2Defeated[aPlayer] := True; end; end; procedure CheckAttack3Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack3Defeated[aPlayer] = false) and (States.GameTime > 9600) then begin Actions.GiveWares(aPlayer, 1, 50); Actions.GiveWares(aPlayer, 2, 20); Actions.GiveWares(aPlayer, 7, 20); Actions.ShowMsg(aPlayer, 6); Attack3Defeated[aPlayer] := True; end; end; procedure CheckAttack4Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack4Defeated[aPlayer] = false) and (States.GameTime > 13800) then begin Actions.GiveWares(aPlayer, 1, 50); Actions.GiveWares(aPlayer, 2, 15); Actions.GiveWares(aPlayer, 7, 10); Actions.ShowMsg(aPlayer, 8); Attack4Defeated[aPlayer] := True; end; end; procedure CheckAttack5Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack5Defeated[aPlayer] = false) and (States.GameTime > 16800) then begin Actions.GiveWares(aPlayer, 1, 35); Actions.GiveWares(aPlayer, 2, 10); Actions.GiveWares(aPlayer, 7, 5); Actions.GiveWares(aPlayer, 18, 10); Actions.ShowMsg(aPlayer, 10); Attack5Defeated[aPlayer] := True; end; end; procedure CheckAttack6Defeated(aPlayer: Integer); begin if (States.ArmyCount(aPlayer + 4) = 0) and (Attack6Defeated[aPlayer] = false) and (States.GameTime > 19800) then begin Actions.GiveWares(aPlayer, 1, 30); Actions.GiveWares(aPlayer, 7, 10); Actions.ShowMsg(aPlayer, 12); Attack6Defeated[aPlayer] := True; end; end; begin if (States.GameTime = 50) and not Message0Sent then begin ShowMsgToPlayers(0); //Actions.ShowCountdown(0, 2350); //Actions.ShowCountdown(1, 2350); //Actions.ShowCountdown(2, 2350); //Actions.ShowCountdown(3, 2350); Message0Sent := true; end; //attack wave 1 if (States.GameTime = 2400) and not Attack1Started then begin Actions.GiveGroup(4, 14, 68, 78, 5, 15, 1); Actions.GiveGroup(5, 14, 122, 78, 3, 15, 1); Actions.GiveGroup(6, 14, 68, 112, 7, 15, 1); Actions.GiveGroup(7, 14, 122, 112, 1, 15, 1); ShowMsgToPlayers(1); //Actions.ShowCountdown(0, 4200); //Actions.ShowCountdown(1, 4200); //Actions.ShowCountdown(2, 4200); //Actions.ShowCountdown(3, 4200); Attack1Started := true; end; CheckAttack1Defeated(0); CheckAttack1Defeated(1); CheckAttack1Defeated(2); CheckAttack1Defeated(3); //Attack wave 2 if (States.GameTime = 6600) and (Attack2Started = false) then begin Actions.GiveGroup(4, 19, 68, 78, 5, 20, 1); Actions.GiveGroup(5, 19, 122, 78, 3, 20, 1); Actions.GiveGroup(6, 19, 68, 112, 7, 20, 1); Actions.GiveGroup(7, 19, 122, 112, 1, 20, 1); ShowMsgToPlayers(3); //Actions.ShowCountdown(0, 3000); //Actions.ShowCountdown(1, 3000); //Actions.ShowCountdown(2, 3000); //Actions.ShowCountdown(3, 3000); Attack2Started := true; end; CheckAttack2Defeated(0); CheckAttack2Defeated(1); CheckAttack2Defeated(2); CheckAttack2Defeated(3); //Attack wave 3 if (States.GameTime = 9600) and (Attack3Started = false) then begin Actions.GiveGroup(4, 20, 68, 78, 5, 25, 1); Actions.GiveGroup(5, 20, 122, 78, 3, 25, 1); Actions.GiveGroup(6, 20, 68, 112, 7, 25, 1); Actions.GiveGroup(7, 20, 122, 112, 1, 25, 1); ShowMsgToPlayers(5); //Actions.ShowCountdown(0, 3000); //Actions.ShowCountdown(1, 3000); //Actions.ShowCountdown(2, 3000); //Actions.ShowCountdown(3, 3000); Attack3Started := true; end; CheckAttack3Defeated(0); CheckAttack3Defeated(1); CheckAttack3Defeated(2); CheckAttack3Defeated(3); //Attack wave 4 if (States.GameTime = 12600) and (Attack4Started = false) then begin Actions.GiveGroup(4, 14, 68, 78, 5, 60, 5); Actions.GiveGroup(5, 14, 122, 78, 3, 60, 5); Actions.GiveGroup(6, 14, 68, 112, 7, 60, 5); Actions.GiveGroup(7, 14, 122, 112, 1, 60, 5); Actions.GiveGroup(4, 15, 70, 80, 5, 20, 2); Actions.GiveGroup(5, 15, 124, 80, 3, 20, 2); Actions.GiveGroup(6, 15, 70, 114, 7, 20, 2); Actions.GiveGroup(7, 15, 124, 114, 1, 20, 2); ShowMsgToPlayers(7); //Actions.ShowCountdown(0, 3000); //Actions.ShowCountdown(1, 3000); //Actions.ShowCountdown(2, 3000); //Actions.ShowCountdown(3, 3000); Attack4Started := true; end; CheckAttack4Defeated(0); CheckAttack4Defeated(1); CheckAttack4Defeated(2); CheckAttack4Defeated(3); //Attack wave 5 if (States.GameTime = 15600) and (Attack5Started = false) then begin Actions.GiveGroup(4, 21, 68, 78, 5, 20, 1); Actions.GiveGroup(5, 21, 122, 78, 3, 20, 1); Actions.GiveGroup(6, 21, 68, 112, 7, 20, 1); Actions.GiveGroup(7, 21, 122, 112, 1, 20, 1); ShowMsgToPlayers(9); //Actions.ShowCountdown(0, 3000); //Actions.ShowCountdown(1, 3000); //Actions.ShowCountdown(2, 3000); //Actions.ShowCountdown(3, 3000); Attack5Started := true; end; CheckAttack6Defeated(0); CheckAttack6Defeated(1); CheckAttack6Defeated(2); CheckAttack6Defeated(3); //Attack wave 6 if (States.GameTime = 18600) and (Attack6Started = false) then begin Actions.GiveGroup(4, 16, 68, 78, 5, 50, 3); Actions.GiveGroup(5, 16, 122, 78, 3, 50, 3); Actions.GiveGroup(6, 16, 68, 112, 7, 50, 3); Actions.GiveGroup(7, 16, 122, 112, 1, 50, 3); ShowMsgToPlayers(11); //Actions.ShowCountdown(0, 3000); //Actions.ShowCountdown(1, 3000); //Actions.ShowCountdown(2, 3000); //Actions.ShowCountdown(3, 3000); Attack6Started := true; end; CheckAttack6Defeated(0); CheckAttack6Defeated(1); CheckAttack6Defeated(2); CheckAttack6Defeated(3); end.
<<

sado1

User avatar

Council Member

Posts: 1430

Joined: 21 May 2012, 19:13

KaM Skill Level: Skilled

Post 12 Apr 2013, 22:47

Re: Dynamic Script Usage

Would be nice to actually have a tool that'd check script's integrity without running the map again and again just to see what was the mistake.
<<

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 13 Apr 2013, 01:05

Re: Dynamic Script Usage

I'm having troubles too. This error occurs: [Error] (8:26): Type mismatch
I'm using the exact same script as before, when it worked just fine. What's changed?
We changed quite a lot of stuff since you originally wrote that script. In future releases we'll try to keep backwards compatibility better, but you were using an "alpha" version of the scripting demo back then ;) Here's the stuff which affects your script
- The error you got says there's a mistake on line 8 at character 26. You can see that's this: Actions.ShowMsg, the second parameter needs to be a string (text). You can fetch text out of the LIBX files using States.Text(X). So replace "Actions.ShowMsg(0, aMsg);" with "Actions.ShowMsg(0, States.Text(aMsg));" This allows you to combine text more easily, like I did for the overlay in Annie's Hill. There are more cases where you used "Actions.ShowMsg" in the script, so make sure you fix all of them.
- States.ArmyCount was renamed to States.StatArmyCount
- The "begin .... end." at the bottom of the document (the main bit of code that runs every tick) needs to be replaced with "procedure OnTick;
begin
...
end;"
So basically add the procedure line at the top and replace the final "." after the end with a ";". We changed it to work like this to be more consistent (everything happens through events)

When you get an error like "(8:26): Type mismatch", check what commands you use on that line (8) and lookup in the wiki to make sure you are using them correctly (in this case you provided an integer when it expected a string, so that's a type mismatch)

After fixing those 3 things your script runs without errors for me, and shows me a message :)
Also, can't it just ignore the scripts that aren't working? Currently nothing works if there's just one tiny mistake; that's pretty annoying, I can't do a thing right now.
Unfortunately no, that's the way programming usually works. Because that one mistake could cause nothing else to work in the script. The closest thing we could do is remove every line that causes an error (there's a joke Javascript library that does that...) but that wouldn't be very helpful, since often it will just cause more errors and confuse the user when the wrong stuff happens, for example if we removed an if statement that was broken the conditional code would run every time.
Would be nice to actually have a tool that'd check script's integrity without running the map again and again just to see what was the mistake.
Yes it would, I'm planning to write one for the next RC :)


EDIT:
Sado and I were trying to figure out if we could use the OnTick even to run after more than just 1 tick. For example, say I wanted a unit to be created after 1000 ticks. How would I do this?
Your procedure OnTick will be run EVERY tick of the game, 10 times per second for the entire game. If you want a unit to be created after 1000 ticks use this:
  Code:
procedure OnTick; begin if States.GameTime = 1000 then Actions.GiveUnit(...); end;
So every tick the game will check "is this tick 1000"? If yes, it will run the GiveUnit code. If no, it won't do anything in this case. But you could add more stuff into OnTick:
  Code:
procedure OnTick; begin //Every tick we should set the text overlaid on the screen for player 0 Actions.SetOverlayText(0, 'Current tick: '+IntToStr(States.GameTime)); if States.GameTime = 100 then //After 10 seconds begin Actions.ShowMsg(...); //Show a message Actions.GiveWares(...); //Give the player some wares end; if States.GameTime = 1000 then //After 100 seconds Actions.GiveUnit(...); //Give the player a unit end;
<<

Ben

User avatar

Former Site Admin

Posts: 3814

Joined: 08 Jan 2009, 23:00

Location: California - Pacific Time (UTC -8/-7 Summer Time)

Post 13 Apr 2013, 02:03

Re: Dynamic Script Usage

But this only works once. I thought that the OnTick would work as a loop, but with the gametime action, it doesn't work like that. So how do I make this a loop?
I used to spam this forum so much...

Return to “Dynamic Scripting”

Who is online

Users browsing this forum: No registered users and 5 guests