Map Database  •  FAQ  •  RSS  •  Login

Help!

<<

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 20 Jan 2014, 15:17

Help!

I created this topic before, but deleted it again as I thought sado and me found the solution to my problem. But we did not. So now I will rewrite everything and upgrade it a bit. :P

I'm working on the script of TNL 7, and in that mission the player has to break through a barricade which consists of a large number of units. I'm looking for a way to script this objective and I found one, except that it's not working.
What my script should do is: search in a radius of 14 tiles around location (74, 67) for enemy units --> if there are none and both AI players have less soldiers than 5, you win.
What my script does: no idea, but you win as soon as both players have less than 5 soldiers. The other condition never turns true although it should turn true right at the start?

Here is the script itself:
  Code:
Units := States.PlayerGetAllUnits(0); UnitsEnemy := States.PlayerGetAllUnits(1); UnitsEnemy2 := States.PlayerGetAllUnits(2); for i := 0 to Length(Units) -1 do begin if (((States.UnitPositionX(Units[i]) > (PointOfDefenceX - 14)) and (States.UnitPositionX(Units[i]) < (PointOfDefenceX + 14))) and ((States.UnitPositionY(Units[i]) > (PointOfDefenceY - 14)) and (States.UnitPositionY(Units[i]) < (PointOfDefenceY - 14)))) then begin AttackIntruders := True; end; end; begin for j := 0 to Length(UnitsEnemy) -1 do if (((States.UnitPositionX(UnitsEnemy[j]) > (PointOfDefenceX - 14)) and (States.UnitPositionX(UnitsEnemy[j]) < (PointOfDefenceX + 14))) and ((States.UnitPositionY(UnitsEnemy[j]) > (PointOfDefenceY - 14)) and (States.UnitPositionY(UnitsEnemy[j]) < (PointOfDefenceY - 14)))) then BarricadeIntact := True else BarricadeIntact := False; end; begin for k := 0 to Length(UnitsEnemy2) -1 do if (((States.UnitPositionX(UnitsEnemy2[k]) > (PointOfDefenceX - 14)) and (States.UnitPositionX(UnitsEnemy2[k]) < (PointOfDefenceX + 14))) and ((States.UnitPositionY(UnitsEnemy2[k]) > (PointOfDefenceY - 14)) and (States.UnitPositionY(UnitsEnemy2[k]) < (PointOfDefenceY - 14)))) then Barricade2Intact := True else Barricade2Intact := False; end; if (BarricadeIntact = false) and (States.StatArmyCount(1) < 5) and (Barricade2Intact = false) and (States.StatArmyCount(2) < 5) then begin Actions.PlayerWin([0], False); end;
This is all on OnTick. PointOfDefenceX and PointOfDefenceY are constants. You may ignore AttackIntruders, I will be needing it later on. The script does not give an error.
So I guess there is a problem with the condition since BarricadeIntact and Barricade2Intact never turn true. But what? :O

Edit: wait a second... If I set BarricadeIntact/Barricade2Intact as true on OnMissionStart, the same thing happens... So that must mean they are always false, no matter what? Or they are just being ignored in the last part of the script (if lala PlayerWin)? :? I must have made an obvious mistake somewhere. :P
<<

Nissarin

User avatar

Pikeman

Posts: 185

Joined: 26 Sep 2012, 18:11

KaM Skill Level: Average

Location: Poland

Post 20 Jan 2014, 16:17

Re: Help!

  Code:
procedure check_victory_condition; var enemy1: array of Integer; enemy2: array of Integer; i, x, y: Integer; begin enemy1 := States.PlayerGetAllUnits(1); if Length(enemy1) > 5 then exit; enemy2 := States.PlayerGetAllUnits(2); if Length(enemy2) > 5 then exit; for i := 0 to Length(enemy1) - 1 do begin x := States.UnitPositionX(enemy1[i]); if (x > (PointOfDefenceX - 14)) and (x < (PointOfDefenceX + 14)) then exit; y := States.UnitPositionY(enemy1[i]); if (y > (PointOfDefenceY - 14)) and (y < (PointOfDefenceY + 14)) then exit; end; for i := 0 to Length(enemy2) - 1 do begin x := States.UnitPositionX(enemy1[i]); if (x >( PointOfDefenceX - 14)) and (x < (PointOfDefenceX + 14)) then exit; y := States.UnitPositionY(enemy1[i]); if (y > (PointOfDefenceY - 14)) and (y < (PointOfDefenceY + 14)) then exit; end; Actions.PlayerWin([0], false); end; procedure OnTick; begin if (States.GameTime mod 15) = 0 then check_victory_condition; end;
Not tested.
<<

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 20 Jan 2014, 16:19

Re: Help!

Thanks! I will test it for you. :mrgreen:
Edit: it's not exactly working; I don't win now when both players have less than 5 units but still have units within the specified area (that's good). But when they still have like 2 units outside the specified area, I don't win either. :/
Edit 2: wait, I might have the solution. :P
Edit 3: Meh, I didn't. :(
<<

Nissarin

User avatar

Pikeman

Posts: 185

Joined: 26 Sep 2012, 18:11

KaM Skill Level: Average

Location: Poland

Post 20 Jan 2014, 19:14

Re: Help!

In the second part there is an error:
for i := 0 to Length(enemy2) - 1 do
begin
x := States.UnitPositionX(enemy2);
if (x >( PointOfDefenceX - 14)) and (x < (PointOfDefenceX + 14)) then
exit;
y := States.UnitPositionY(enemy2);
if (y > (PointOfDefenceY - 14)) and (y < (PointOfDefenceY + 14)) then
exit;
end;


Not sure if that was causing a problem but it might if you got some 'junk' on x/y.
<<

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 20 Jan 2014, 19:35

Re: Help!

I noticed it too and fixed it already, but still didn't work. :( Current (complete) script looks like this:
  Code:
const PointOfDefenceX = 74; PointOfDefenceY = 67; var Message1Sent: Boolean; AttackIntruders: Boolean; procedure OnMissionStart; begin end; procedure check_victory_condition; var Enemy1: array of Integer; Enemy2: array of Integer; i, k, x, y, x2, y2: Integer; begin Enemy1 := States.PlayerGetAllUnits(1); if Length(Enemy1) > 5 then exit; Enemy2 := States.PlayerGetAllUnits(2); if Length(Enemy2) > 5 then exit; for i := 0 to Length(Enemy1) - 1 do begin x := States.UnitPositionX(Enemy1[i]); if (x > (PointOfDefenceX - 14)) and (x < (PointOfDefenceX + 14)) then exit; y := States.UnitPositionY(Enemy1[i]); if (y > (PointOfDefenceY - 14)) and (y < (PointOfDefenceY + 14)) then exit; end; for k := 0 to Length(Enemy2) - 1 do begin x2 := States.UnitPositionX(Enemy2[k]); if (x2 > (PointOfDefenceX - 14)) and (x2 < (PointOfDefenceX + 14)) then exit; y2 := States.UnitPositionY(Enemy2[k]); if (y2 > (PointOfDefenceY - 14)) and (y2 < (PointOfDefenceY + 14)) then exit; end; Actions.PlayerWin([0], false); end; procedure OnTick; begin if (States.GameTime = 2500) and (Message1Sent = False) then begin Actions.ShowMsg(0, 'Our faithful ally will soon attempt to break the barricade, but the enemies'' strength is far superior. We could assist them and weaken the enemy, but this will inevitably lead to the doom of our forces. Anyhow, we need a larger army to be able to completely shatter this barricade.'); Message1Sent := True; end; if (States.GameTime mod 15) = 0 then check_victory_condition; end;
If anyone who is willing to help needs more info (or the map/.dat file) let me know and I'll be happy to upload them for you. :)
Edit: before people start about it: I am certain there are not more units on the map that cause this script to 'fail' as I test with the whole map revealed and I removed all soldiers but 11 in the middle (and I double-checked the static script). The X and Y should be correct too (a 1 or 2 tile difference would not matter).
<<

Sexy S

Post 20 Jan 2014, 20:50

Re: Help!

Your first post:
  Code:
((States.UnitPositionY(UnitsEnemy2[k]) > (PointOfDefenceY - 14)) and (States.UnitPositionY(UnitsEnemy2[k]) < (PointOfDefenceY - 14))
This can never be fulfilled; note that both times you have (PointOfDefenceY - 14) with the minus sign. The second time it should be (PointOfDefenceY + 14) with a plus.

Your second post:
you put the winning condition inside the OnMissionStart, so you can only win at the beginning. Is this the way it's meant to be?

- S
<<

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 20 Jan 2014, 20:54

Re: Help!

Your first post:
  Code:
((States.UnitPositionY(UnitsEnemy2[k]) > (PointOfDefenceY - 14)) and (States.UnitPositionY(UnitsEnemy2[k]) < (PointOfDefenceY - 14))
This can never be fulfilled; note that both times you have (PointOfDefenceY - 14) with the minus sign. The second time it should be (PointOfDefenceY + 14) with a plus.

Your second post:
you put the winning condition inside the OnMissionStart, so you can only win at the beginning. Is this the way it's meant to be?

- S
Oh, not sure why it was minus both times, I probably tried some different things and forgot to replace those - with + again. I'm sure it was + before though.
About the second post: it's not inside OnMissionStart as I wrote:
  Code:
procedure OnMissionStart begin end;
Right? :P It probably looks like it is because of the allignment. Sorry about that.
<<

Nissarin

User avatar

Pikeman

Posts: 185

Joined: 26 Sep 2012, 18:11

KaM Skill Level: Average

Location: Poland

Post 20 Jan 2014, 22:06

Re: Help!

This is really strange.. I created empty map, placed some troops inside/outside the area and it seems the script works, maybe it would be better if you uploaded the map somewhere after all.
<<

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 20 Jan 2014, 22:38

Re: Help!

Ok, I added the file as an attachment to this post.

So if you kill all units except 1 archer, and you let the archer chase you to the edge of the map you still don't win although all conditions have been met? If the script works for you I must have made a big mistake somewhere!
You do not have the required permissions to view the files attached to this post.
<<

Nissarin

User avatar

Pikeman

Posts: 185

Joined: 26 Sep 2012, 18:11

KaM Skill Level: Average

Location: Poland

Post 20 Jan 2014, 23:09

Re: Help!

Well, the reason why the script doesn't work as expected is because it's not a battle map.. in other words there are other "units" besides "warriors" like serfs, etc. ;)


Update:
  Code:
const PointOfDefenceX = 74; PointOfDefenceY = 67; PointOfDefenceR = 14; var Message1Sent: Boolean; AttackIntruders: Boolean; procedure CheckVictoryCondition; var groups: array of Integer; enemy, grp, member, id, cnt, x, y: Integer; begin for enemy := 1 to 2 do begin groups := States.PlayerGetAllGroups(enemy); cnt := 0; for grp := 0 to Length(groups) - 1 do cnt := cnt + States.GroupMemberCount(groups[grp]); if cnt > 5 then exit else begin for grp := 0 to Length(groups) - 1 do begin cnt := States.GroupMemberCount(groups[grp]); for member := 0 to cnt - 1 do begin id := States.GroupMember(groups[grp], member); x := States.UnitPositionX(id); if (x > (PointOfDefenceX - PointOfDefenceR)) and (x < (PointOfDefenceX + PointOfDefenceR)) then exit; y := States.UnitPositionY(id); if (y > (PointOfDefenceY - PointOfDefenceR)) and (y < (PointOfDefenceY + PointOfDefenceR)) then exit; end; end end; end; Actions.PlayerWin([0], false); end; procedure OnTick; begin if (States.GameTime mod 15) = 0 then CheckVictoryCondition; end;
Tested using with my "empty" map.
<<

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 21 Jan 2014, 00:27

Re: Help!

Oh god. :$ :rolleyes:
Sometimes I doubt my own intelligence. :P
I didn't even consider that I was scanning for all units. The worst thing of all is that I actually did something like this before, but back then I did not forget to check if it were military units or citizens. :rolleyes:
God.

ANYWAY thank you, I will test it tomorrow. Right now it's bed time. :D
Edit: it works now, thanks. :)
<<

pawel95

Castle Guard Swordsman

Posts: 1912

Joined: 03 Oct 2008, 22:00

KaM Skill Level: Skilled

Location: "Pawel95" on Youtube.com

Post 21 Jan 2014, 09:28

Re: Help!

Well, the reason why the script doesn't work as expected is because it's not a battle map.. in other words there are other "units" besides "warriors" like serfs, etc. ;)
HAHAHAHHAHA tdl you nooob Xd he asked sado, he deleted his topic and opened a new one, and like always at programming or scripting the "easiest" things are forgotten xd
<<

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 21 Jan 2014, 09:40

Re: Help!

Yes that's how it usually is, if you try a million things and it still doesn't work, the answer is mostly right there but you just don't see it. :P Oh well...
<<

T*AnTi-V!RuZz

User avatar

Former Site Admin

Posts: 1826

Joined: 03 Jan 2007, 23:00

KaM Skill Level: Fair

Website: http://www.knightsandmerchants.net

Location: The Netherlands

Post 21 Jan 2014, 11:04

Re: Help!

Oh god. :$ :rolleyes:
Sometimes I doubt my own intelligence. :P
I didn't even consider that I was scanning for all units. The worst thing of all is that I actually did something like this before, but back then I did not forget to check if it were military units or citizens. :rolleyes:
God.

ANYWAY thank you, I will test it tomorrow. Right now it's bed time. :D
Edit: it works now, thanks. :)
I know this feeling all too well, I'm afraid :P
<<

Nissarin

User avatar

Pikeman

Posts: 185

Joined: 26 Sep 2012, 18:11

KaM Skill Level: Average

Location: Poland

Post 21 Jan 2014, 12:28

Re: Help!

Just for the record, since in KaM you can't really control what your "non combatants" do I think it's easy to "forgot" about their existence, usually when someone mentions something about "units" you would assume he is talking about some army units. In fact when I saw your map, first thing I did was to place some serfs in my "test" map just to be sure :) Maybe some note in the API description (wiki) would be nice to avoid confusion in the future.

Return to “Dynamic Scripting”

Who is online

Users browsing this forum: No registered users and 7 guests