Map Database  •  FAQ  •  RSS  •  Register  •  Login

Barbarian Scripting

<<

JulianSnow2

Woodcutter

Posts: 17

Joined: 09 Jan 2018, 11:23

Post 23 Jan 2018, 18:40

Barbarian Scripting

Hi everyone,

Since a few weeks i'm busy reading and editing scripts (mostly small adjustments) tryinf to get a better understanding of how and why some events occur during the game. But this time i'm stuck, underneath the script that I want working on my co-op map (which i'll publish later on).

procedure aSwitchToBarbarian(aUnitID: Integer; aGroupID: Integer); // Starting a procedure, which is basiclly telling the game to start 'doing something'
var aBarracks: Integer; // This makes the barracks a reference point within this script that is linked to the game, correct ?
var aDone: Boolean; // This creates a two way variable, in this case checken whether the player is AI or human, correct ?
begin // Begin describing what the script should 'do'
if States.UnitType(aUnitID) = 14 then begin // This says "If the unit type is Miltia(14) then begin..", correct ?
aBarracks := States.ClosestHouse(States.UnitOwner(aUnitID), States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), 21); // This says "Replace the Miltia (14) with Barbarian (21)", correct ?
if aBarracks > -1 then begin // Don't know what this says, I figured it said something like "If barracks is existing"
aDone := False; // This is the trigger for being AI or not, False means that an human is controlling the player

if States.PlayerIsAI(States.UnitOwner(aUnitID)) = True then Actions.HouseAddWaresTo(aBarracks, 20, 1); // This line says "When the player is AI, Add 1 x item 20 to the barracks" (which is an axe, i Figure)

if (States.HouseResourceAmount(aBarracks, 20) >= 1) AND (aDone = False) then begin // This checks if the resource amount in the barracks of item 20 (axe) is more than, or equal to 1 AND the player is AI/human
Actions.HouseTakeWaresFrom(aBarracks, 20, 1); // If the previous line is correct than this line takes 1 x item 20 from the barracks
Actions.GroupOrderLink(Actions.GiveGroup(States.UnitOwner(aUnitID), 23, States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), States.UnitDirection(aUnitID),1,1), aGroupID); // Don't know what this says, I figured this gives the 'trained' militia a certain groupID to wich he is added (training 10 miltia would each give them the same groupID, otherwise they would all spawn as individual groups). This is needed for the script to work, not sure about this.
aDone := True; // This checks if the player is AI or not (True, means an player is AI (correct?))
end;

if (States.HouseResourceAmount(aBarracks, 20) < 1) AND (aDone = False) then begin // This line tells the exact opposite for what to do if the first part is not met (above 3 lines)
Actions.HouseBarracksGiveRecruit(aBarracks);
Actions.HouseAddWaresTo(aBarracks, 20, 1);
aDone := True;
end;

Actions.UnitKill(aUnitID, True);// This will remove the militia from the game
end;
end;
end;

procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer); // This should tell the moment in the game for when to start a certain 'procedure', on warrior equip would occure when someone trains a specific unit (militia for this script)
begin
if States.UnitType (aUnitID) = 14 then begin // This should only tell the script to start when the trained unit type is '14' (thus a militia)
aSwitchToBarbarian(aUnitID, aGroupID); // This should tell the script to start the above procedure (thus replacing the militia for a barbarian)
end;
end;




I've added my comment on each scripting line for what I think about the script(Correct me if i'm wrong :P). I've cut this part from a script of a 'bonus' map. The end result should be that player 8, AI controlled (only player that can train militia, I've denied all other players to train militia, so I wouldn't have to exclude the other players from the script), can train barbarians by default.

Script without my comments:



procedure aSwitchToBarbarian(aUnitID: Integer; aGroupID: Integer);
var aBarracks: Integer;
var aDone: Boolean;
begin
if States.UnitType(aUnitID) = 14 then begin
aBarracks := States.ClosestHouse(States.UnitOwner(aUnitID), States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), 21);
if aBarracks > -1 then begin
aDone := False;

if States.PlayerIsAI(States.UnitOwner(aUnitID)) = True then Actions.HouseAddWaresTo(aBarracks, 20, 1);

if (States.HouseResourceAmount(aBarracks, 20) >= 1) AND (aDone = False) then begin
Actions.HouseTakeWaresFrom(aBarracks, 20, 1);
Actions.GroupOrderLink(Actions.GiveGroup(States.UnitOwner(aUnitID), 23, States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), States.UnitDirection(aUnitID),1,1), aGroupID);
aDone := True;
end;

if (States.HouseResourceAmount(aBarracks, 20) < 1) AND (aDone = False) then begin
Actions.HouseBarracksGiveRecruit(aBarracks);
Actions.HouseAddWaresTo(aBarracks, 20, 1);
aDone := True;
end;

Actions.UnitKill(aUnitID, True);
end;
end;
end;

procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer);
begin
if States.UnitType (aUnitID) = 14 then begin
aSwitchToBarbarian(aUnitID, aGroupID);
end;
end;


Kind Regards,
Julian Snow
<<

Esthlos

User avatar

Knight

Posts: 672

Joined: 23 Jun 2013, 16:02

KaM Skill Level: Beginner

Post 23 Jan 2018, 19:07

Re: Barbarian Scripting

procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer);
begin
    if States.UnitType (aUnitID) = 14 then begin
        aSwitchToBarbarian(aUnitID, aGroupID);
    end;
end;

OnWarriorEquipped is an event: it means that it is a function that is called by normal gameplay.
In this case, it is called whenever a warrior is created in any Barracks.

Inside of it, the game is told to call aSwitchToBarbarian on the newly created warrior.

aSwitchToBarbarian removes 1 additional Axe from the Barracks, then swaps the newly trained Militia for a Barbarian.

procedure aSwitchToBarbarian(aUnitID: Integer; aGroupID: Integer);
var aBarracks: Integer;
var aDone: Boolean;
begin
Only act if the new warrior is a Militia (actually redundant here)
    if States.UnitType(aUnitID) = 14 then begin
Find the closest Barracks, which for a new warrior will obviously be the one it spawned from
        aBarracks := States.ClosestHouse(States.UnitOwner(aUnitID), States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), 21);
        if aBarracks > -1 then begin Barracks found
            aDone := False;

AI players don't get the concept of needing 2 Axes to make a Militia, and if they only have 1 axe they will try to make a Militia forever; to work around the issue, AI players are given 1 free Axe - AI players are pretty weak anyway in Bonus maps, letting them get Barbarians without the additional cost will be fine
            if States.PlayerIsAI(States.UnitOwner(aUnitID)) = True then Actions.HouseAddWaresTo(aBarracks, 20, 1);

If there are unused Axes in the Barracks, then remove 1
            if (States.HouseResourceAmount(aBarracks, 20) >= 1) AND (aDone = False) then begin
                Actions.HouseTakeWaresFrom(aBarracks, 20, 1);
Oh, since the player paid the price give them a Barbarian; also, add the new Barbarian to the same troop the Militia is in
                Actions.GroupOrderLink(Actions.GiveGroup(States.UnitOwner(aUnitID), 23, States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), States.UnitDirection(aUnitID),1,1), aGroupID);
                aDone := True;
            end;

There are no axes in the Barracks; refund the Recruit and Axe used to make the Militia, but don't give any Barbarian to the player
            if (States.HouseResourceAmount(aBarracks, 20) < 1) AND (aDone = False) then begin
                Actions.HouseBarracksGiveRecruit(aBarracks);
                Actions.HouseAddWaresTo(aBarracks, 20, 1);
                aDone := True;
            end;

Remove the Militia
            Actions.UnitKill(aUnitID, True);
        end;
    end;
end;


This code should achieve what you're looking for, as far as I understood it:
("States.UnitOwner(aUnitID) = 7" means that this will only apply to player 8)

  Code:
procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer);
begin
   if (States.UnitOwner(aUnitID) = 7) AND (States.UnitType(aUnitID) = 14) then begin
      Actions.GroupOrderLink(Actions.GiveGroup(States.UnitOwner(aUnitID), 23, States.UnitPositionX(aUnitID), States.UnitPositionY(aUnitID), States.UnitDirection(aUnitID),1,1), aGroupID);
      Actions.UnitKill(aUnitID, True);
   end;
end;
Just when you think you know something, you have to look at it in another way, even though it may seem silly or wrong. You must try! - John Keating, "Dead Poets Society"
<<

JulianSnow2

Woodcutter

Posts: 17

Joined: 09 Jan 2018, 11:23

Post 23 Jan 2018, 22:29

Re: Barbarian Scripting

Reading this back makes it all seem so easy, however I really seem to have over thought it. Your code works :)

To make things a little more interesting one of the villages now has an AI-mercenary ally, shall 'tweak' my co-op mission later this week and upload it before the weekend (for anyone interested :P).

Thank you for reviewing my post!
<<

JulianSnow2

Woodcutter

Posts: 17

Joined: 09 Jan 2018, 11:23

Post 08 Mar 2018, 06:32

Re: Barbarian Scripting

A while ago you guys helped me with this script, but i'm almost done with my co-op map and now the game says "Script compile error: Identifer expected" at line 62:1.

That line is like this: "procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer); // AI has special units."

On other maps this line is just fine and works exactly as intended. What are possible other reasons for the game to ask for an Identifer ?
<<

JulianSnow2

Woodcutter

Posts: 17

Joined: 09 Jan 2018, 11:23

Post 08 Mar 2018, 06:39

Re: Barbarian Scripting

JulianSnow2 wrote:A while ago you guys helped me with this script, but i'm almost done with my co-op map and now the game says "Script compile error: Identifer expected" at line 62:1.

That line is like this: "procedure OnWarriorEquipped(aUnitID: Integer; aGroupID: Integer); // AI has special units."

On other maps this line is just fine and works exactly as intended. What are possible other reasons for the game to ask for an Identifer ?


Found it, forgot a "End;" at a previous line.

Return to Dynamic Scripting

Who is online

Users browsing this forum: No registered users and 4 guests