Page 11 of 26
Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 13:41
by pawel95
Btw guys, have you played the campaign of vas? There is a mission: Mission 06. This mission works with thaaaaaaaaaaaaaaaaaaaaaaaaat many Scripts, like AI building at certain places, transforming units, "ship ariving(with storehouse placement)", Patrol of horses.....
So you shouldnt just copy any lines, but maybe it would help you(specialy Islar) to understand the commands and implement such similar command in your own mission

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 14:14
by Lewin
@sado: Pseudo code (I won't write it so you can write it yourself):
procedure OnUnitTrained(Unit):
School := States.HouseAt(UnitPositionX(Unit), UnitPositionY(Unit) - 1); //1 tile above so it definitely hits the school, they might have started to walk out already
if School <> -1 then //School could have been destroyed at that exact moment or something, better to be safe
AddWareTo(School)
Regarding using other people's scripts, if you get explicit permission from the author then they can allow you to copy lines from their scripts, but you should probably cite it somewhere (have a comment saying "this was taken from Lewin's script with permission" or at the top of your file "part of this script taken from Lewin's work with permission" something similar. It goes without saying that any examples I post here (like the stuff above) you are free to use, unless it was modified from someone else's work. Taking someone's idea without permission is a bit of a grey area because ideas can be more generic, for example if someone made another script with exploding units after seeing that guy doing it here (without asking his permission) then it's hard to say if that's wrong or not, because it's just the idea. It would certainly be polite to cite in a comment "idea from Lewin" or whoever it was.
Looking at other people's scripts to learn things is definitely a good idea, but be aware that many of those people are also still learning and might make minor mistakes (a few places in his scripts Vas has "if something = true then", which could be replaced by "if something then"). Also people have different coding standards (indentation, formatting, commenting, etc.) which could teach you bad habits (I've tried to use good formatting in the scripts I wrote such as Annie and Coastal Encounter Scored)
Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 14:30
by Tef
Can anyone think of a better way to make infinite gold without having to deal with serfs, food, inn etc.?
Depends on other assumptions and realism you want to have. Examples
- if you have the assumption the AI will/may not build demolished schools, you could use PlayerGetAllHouses only at the start of a mission, filter all the schools out and store them in a AllSchools array. Then, OnUnitTrained, search in this AllSchools array if the schools still exist and which one needs more gold.
- HouseAt(x,y) = school, as suggested by Lewin is another approach. However, making the cpu search 256x256 tiles on large maps is also some cpu work, I guess?
- since schools with infinite gold is non-realistic, you might as well skip the gold-adding to schools and just plop in new recruits in front of the school in a given interval, as long as the school exists.
- to remove some more realism: forget schools! Just draw a mountain with a magical cliff near the barracks. Then plop recruits in a interval in that cliff. Look, there you have your mad recruit savages from the magic mountain all wanting to fight you!

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 14:39
by Lewin
- HouseAt(x,y) = school, as suggested by Lewin is another approach. However, making the cpu search 256x256 tiles on large maps is also some cpu work, I guess?
My script doesn't search the entire map because it knows where the school will be: It's just above the newly trained unit. That's assuming you only want to add gold to the school when a unit is trained, which should be the only requirement for infinite gold, since that's the time when the gold gets removed irreversibly (if you cancel the gold can be returned before the training is complete, but once OnUnitTrained happens it can't be cancelled)
Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 14:47
by Tef
@ lewin: apologies. I was reading too quickly. Your solution now sounds like a pretty good idea!

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 15:18
by sado1
- since schools with infinite gold is non-realistic, you might as well skip the gold-adding to schools and just plop in new recruits in front of the school in a given interval, as long as the school exists.
- to remove some more realism: forget schools! Just draw a mountain with a magical cliff near the barracks. Then plop recruits in a interval in that cliff. Look, there you have your mad recruit savages from the magic mountain all wanting to fight you!

if I make too many recruits at once there might be a problem with getting the troops out of the barracks. If I get too many recruits as a whole, then they'll start coming out of the barracks because they're hungry, which might make quite a traffic jam. So, I think I'll just stick to Lewin's advice. I can't directly control the number of recruits yet (thats what I needed GiveRecruit for), but this solution is good enough. Thanks Lewin!
By the way (sorry for being a bit offtopic)... it's possible that I will want to lazily and shamelessly copy the Battle of Octumn script for my winning conditions. Was it done by Ben or Lewin? Either way, do I have your permission to use it?
Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 15:48
by Lewin
By the way (sorry for being a bit offtopic)... it's possible that I will want to lazily and shamelessly copy the Battle of Octumn script for my winning conditions. Was it done by Ben or Lewin? Either way, do I have your permission to use it?
It was done by me, and I give you permission to use it if you cite that it's written by me in a comment

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 17:41
by Islar
Hi
i have this from the tutorial
http://code.google.com/p/castlesand/wik ... icTutorial and i want it to use it to make the AI build a quarry after finishing a school. But i get an error saying ''Invalid number of parameters''
- Code:
procedure OnHouseBuilt(aHouseID: Integer);
begin
if States.HouseOwner(aHouseID) <> 3 then
Exit;
if (States.HouseType(aHouseID) = 13) then
begin
Actions.PlanAddHouse(14, 39, 94);
Actions.PlanAddRoad(39, 95);
Actions.PlanAddRoad(38, 95);
Actions.PlanAddRoad(37, 95);
end;
end;
I only know how to use Ontick with if states.gametime = ... and OnMissionStart with some actions

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 18:26
by Lewin
You're missing the player index in the PlanAdd commands. Put the player index as the first parameter of those commands (so for player 3 put: "Actions.PlanAddRoad(3, 39, 95);") and then it should work.
Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 19:00
by Islar
You're missing the player index in the PlanAdd commands. Put the player index as the first parameter of those commands (so for player 3 put: "Actions.PlanAddRoad(3, 39, 95);") and then it should work.
thank you. If i want to build a woodcutter house after building a two quarries, how do i make that? i don't want the AI to start building the woodcutter house when one of the two quarries is not finished.

Re: Dynamic Script Usage
PostPosted: 11 Jun 2013, 19:46
by Lewin
The easiest way would be to have a global variable boolean (true or false) to say whether you've placed the woodcutter yet. Put this at the top of your script (outside of any procedures):
var PlacedWoodcutter: Boolean;
Then in OnMissionStart put this line:
PlacedWoodcutter := False;
Then in OnHouseBuilt add this:
- Code:
if (States.HouseType(aHouseID) = 14) and not PlacedWoodcutter then
begin
PlacedWoodcutter := True;
//Your code to place woodcutters goes here
end;
"not PlacedWoodcutter" is just a neat was to write "(PlacedWoodcutter = False)"
How it works:
1. At the start of the mission, PlacedWoodcutter is set to false
2. When we notice the AI finishes a quarry, we check PlacedWoodcutter
3. If PlacedWoodcutter = True, we do nothing
4. If PlacedWoodcutter = False, we place the woodcutter and set PlacedWoodcutter to True, so when the next quarry is built, it will not place the woodcutter again.
And that's how you use global variables. They will store values for you which you can use from any place.
Re: Dynamic Script Usage
PostPosted: 12 Jun 2013, 14:45
by Shadaoe
I don't manage to get Actions.UnitOrderWalk to work :
First I store many things in a 2 dimension array thanks to a procedure called on mission start. Here is an exemple for 1 unit :
- Code:
RANDOMWALKERS[0][0] := States.UnitAt(166, 4); //get the unit ID
RANDOMWALKERS[0][1] := 163; //x minimum
RANDOMWALKERS[0][2] := 174; //x maximum
RANDOMWALKERS[0][3] := 2; //y minimum
RANDOMWALKERS[0][4] := 10; //y maximum
RANDOMWALKERS[0][5] := 2; //Don't pay attention to this (number of 5 seconds between random walks(ex : 2 = 10 seconds))
Then every 5 seconds I call a procedure doing this (I cut the unnecessary part, there are many other things to make the process more natural in game) :
- Code:
for i:= 0 to temporaryNumber-1 do
begin
Actions.UnitOrderWalk(RANDOMWALKERS[i][0], RANDOMWALKERS[i][1]+States.KaMRandomI(RANDOMWALKERS[i][2] - RANDOMWALKERS[i][1]), RANDOMWALKERS[i][3]+States.KaMRandomI(RANDOMWALKERS[i][4] - RANDOMWALKERS[i][3]));
end;
It always returns false, however all the units are idle and the terrain is walkable, maybe I didn't understand how UnitOrderWalk works ?
I even tested with a constant x and a constant y to check but no one moves

Thanks in advance.
Re: Dynamic Script Usage
PostPosted: 12 Jun 2013, 15:41
by Lewin
Please use a record instead of that two dimensional array, it's much neater:
- Code:
type TRandomWalker = record
UnitID: Integer;
xMin, xMax, yMin, yMax: Integer;
SecsBetweenWalks: Integer;
end;
//Not sure what kind of array you want here
var RANDOMWALKERS: array[0..9] of TRandomWalker;
//Your code:
RANDOMWALKERS[0].UnitID := States.UnitAt(166, 4);
RANDOMWALKERS[0].xMin := 163;
RANDOMWALKERS[0].xMax := 174;
RANDOMWALKERS[0].yMin := 2;
RANDOMWALKERS[0].yMax := 10;
RANDOMWALKERS[0].SecsBetweenWalks := 2; //Don't pay attention to this (number of 5 seconds between random walks(ex : 2 = 10 seconds))
Get the idea?
As to why it's not working, that's hard to say without seeing more of the context. What kind of unit is it? Animals can never be ordered to walk by the way. You should check the latest log file to see if your script is generating errors. If it's not, maybe send me a complete example so I can test it.
Re: Dynamic Script Usage
PostPosted: 12 Jun 2013, 16:05
by Shadaoe
Please use a record instead of that two dimensional array, it's much neater:
It looks much better indeed, I'm still unfamiliar with pascal concepts so I use the simple things, will change that.
As to why it's not working, that's hard to say without seeing more of the context. What kind of unit is it? Animals can never be ordered to walk by the way. You should check the latest log file to see if your script is generating errors. If it's not, maybe send me a complete example so I can test it.
I tried on both civilian units (serf and laborer) and a military unit and none work, I could send you the map and script but it would spoil you my contest mission :p I'll try to do a sample map and send it to you

Re: Dynamic Script Usage
PostPosted: 12 Jun 2013, 17:36
by Islar
Then in OnMissionStart put this line:
PlacedWoodcutter := False;
do you mean like this?
- Code:
procedure OnMissionStart; PlacedWoodcutter := False;
begin
or like this?
- Code:
procedure OnMissionStart;
PlacedWoodcutter := False;
begin
because by both of those i get an error with (4:1); begin expected. And i think (4:1); means 3 or 4 row? because that were i put this.