Map Database  •  FAQ  •  RSS  •  Login

Error in script, please help!

<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 07 Nov 2017, 20:05

Error in script, please help!

Hello everyone,

I have completed my new map, and started primary testing on server with real players. Everything was going fine, until I got an error. Sadly i cannot provide replay, i accidentally overwrote it.

The error is: EAssertionFailed: "We checked that Group is not dead, hence we should have a valid Unit."

When does this issue present itself? What does this sentence mean? I cannot figure it out...
<<

grayter

Barbarian

Posts: 107

Joined: 18 Aug 2014, 12:06

KaM Skill Level: Skilled

Location: Poland

Post 07 Nov 2017, 21:18

Re: Error in script, please help!

Please attach your script file, I'll check if there are some commands which cause the problem. Are you using r6720?
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 07 Nov 2017, 22:07

Re: Error in script, please help!

It is more than a 1.5k lines, I do not recommend you start looking into it. I own the code, and if I know what the message means I will be able to sort it out.

What I need is the meaning of this message I posted, but suit yourself if you want to read it
  Code:
{ Mod description: - Certain Productions are increased, in order to compensate for the smaller building space Tree Trunks: +25% Stone: +50% Iron: +50% Wine: +50% Corn: +50% Fish: +50% - Various Buildings appear every 15 minutes at a random location out of 3 possible ones. Destroying these buildings will grant an extra power to the destroyer. Plague!: Each enemy player lose 1 unit every 1 sec for 2 minutes. (Total 120 units lost over the duration.) Abundance!: Each player in team is granted 100 wine barrels and fish, 75 breads and 50 sausages. Also, every unit is put at full health. Inns become fully stocked. God's Hand!: Enemy team loses 100% of all units of a single citizen and soldier unit type each. (75% for Militia, Bowmen, Serves, Recruits and Barbarians). Conflagration!: Each enemy player lose 15% of their total buildings in a fire. Weapon Fair in Town!: Each player in team is given the greater value between 20 and 40% of currently in stock for each weapon type in every Barrack. Real Peasants' Rebellion!: [Enemy count] * 120 Rebels spawn as allies. Rebels are granted Retribution bonus and are ordered to attack closest enemy town. } // New Bonuses + Schoolhouse, Statistic, Caravan and Mercenary script + Towers limit // Made by Toxic // Extras by Erdesz Balazs // DECLARATION: type aPLAYER = record Bonus: (btNone, btSurvivalists, btRich, btMasterCrafters, btToughPeople, btSnipers, btRetribution); Buildings: record Schools: array of Integer; Barracks: array of Integer; Markets: array of Integer; Merc: array of Integer; // Special counter in Mercenary script end; SpecialKills: Integer; // Kills caused by bonuses (Retribution, Snipers) Feeding: LongInt; // Survialist feed counter (it is faster 1 global feeding every cca 20 min than scan every tick if unit have hunger) TowersCount: Byte; // Towers count for TOWERS_LIMIT WeaponsCount: array of Integer; end; var PLAYER: array of aPLAYER; aBuildOrder: array[0..29] of array of Byte; BonusChooseByHouses: array of Byte; TradeRatio: array[0..27] of array [0..27] of Byte; TradeSide: array[0..27] of array [0..27] of Boolean; // CONSTANTS const TOWERS_LIMIT = 10; // Towers limit UPDATE_OVERLAY_DELAY = 10; // Statistics upload delay MERC_LINK_GROUPS_RAD = 20; // Radius for link groups after spawn in rally point (Mercenary script) MERCS_SPAWN_COUNT = 10; // Prices of 10 units from Mercenary script REBEL_PRICE = 2; ROGUE_PRICE = 2; VAGABOND_PRICE = 3; WARRIOR_PRICE = 5; REBELS = REBEL_PRICE*MERCS_SPAWN_COUNT; ROGUES = ROGUE_PRICE*MERCS_SPAWN_COUNT; VAGABONDS = VAGABOND_PRICE*MERCS_SPAWN_COUNT; WARRIORS = WARRIOR_PRICE*MERCS_SPAWN_COUNT; type tile = record X: integer; Y: integer; TileType: integer; TileDirection: integer; end; type ware = record ID: integer; AmountAdd: integer; TrackIncrease: integer; Amount: Integer; end; var h, i, j, k, l, m, n: integer; var t: array[0..7] of array [0..5] of ware; //tracker for ware production var Alliance: array[0..7] of array [0..9] of boolean; var PlayerUnits: array[0..7] of array of integer; var PlayerInns: array[0..7] of array of integer; var FoodTypes: array[0..3] of integer; var ExtraStart: integer; var ExtraDuration: integer; var ExtraEnd: integer; var ExtraInterval: integer; var ExtraActive: array [0..5] of boolean; var ExtraRecipient: Integer; var ExtraDestriptionRemoveAfter: integer; var NextExtra: integer; var RandomQuestHouses: array[0..5] of integer; var RandomQuestPlace: array[0..2] of array [0..1] of integer; var RandomQuestLoc: integer; var RandomQuestType: integer; var UnitTracker: array[0..7] of array of integer; var Extra_RandomDeath_Multiplier: integer; var Extra_RandomDeath_Unit: integer; var Extra_RandomSoldierTypeToKill: integer; var PortionToKill: integer; var Extra_RandomCitizenTypeToKill: integer; var PortionToDestroy: integer; var HousesToDestroy: array of integer; var BuildingToDestroy: integer; var UnitTypeToDie: array[0..1] of integer; var RebelSpawnLoc: array[0..5] of array[0..1] of integer; var RebelNumber: integer; var RebelsToSpawn: integer; var ExtraBuildingTiles: array[0..2] of array[0..4] of array[0..3] of tile; var UnitsMustBeRemovedFirst: boolean; var AlreadyRemovedUnits: boolean; procedure Initialize; begin NextExtra:= States.PeaceTime + 1; RebelsToSpawn:= 120; for i:=0 to 7 do begin //FILL THE WARE TRACKER t[i][0].ID:= 0; //Tree Trunks t[i][0].AmountAdd:= 1; t[i][0].Amount:= 4; t[i][0].TrackIncrease:= 5; t[i][1].ID:= 1; //Stone t[i][1].AmountAdd:= 1; t[i][1].Amount:= 2; t[i][1].TrackIncrease:= 3; t[i][2].ID:= 6; //Iron t[i][2].AmountAdd:= 1; t[i][2].Amount:= 2; t[i][2].TrackIncrease:= 3; t[i][3].ID:= 8; //Wine Barrel t[i][3].AmountAdd:= 1; t[i][3].Amount:= 2; t[i][3].TrackIncrease:= 3; t[i][4].ID:= 9; //Corn t[i][4].AmountAdd:= 1; t[i][4].Amount:= 2; t[i][4].TrackIncrease:= 3; t[i][5].ID:= 27; //Fish t[i][5].AmountAdd:= 1; t[i][5].Amount:= 2; t[i][5].TrackIncrease:= 3; for j:=0 to 7 do begin //CREATE ALLIANCE MATRIX Alliance[i][j]:=States.PlayerAllianceCheck(i, j); end; Alliance[i][8]:= false; Alliance[i][9]:= true; end; FoodTypes[0]:= 8; FoodTypes[1]:= 10; FoodTypes[2]:= 13; FoodTypes[3]:= 27; ExtraDuration:= 1200; ExtraInterval:= 9000; ExtraDestriptionRemoveAfter:= 600; for i:=0 to High(ExtraActive) do begin ExtraActive[i]:= false; end; RandomQuestHouses[0]:= 11; //Storehouse - Plague! RandomQuestHouses[1]:= 27; //Inn - Abundance! RandomQuestHouses[2]:= 21; //Barrack - God's Hand! RandomQuestHouses[3]:= 12; //Stables - Conflagration! RandomQuestHouses[4]:= 29; //Market Hall - Weapon Fair in Town! RandomQuestHouses[5]:= 13; //Schholhouse - Real Peasants' Rebellion! {RandomQuestHouses[0]:= 11; //Storehouse - Plague! RandomQuestHouses[1]:= 27; //Inn - Abundance! RandomQuestHouses[2]:= 21; //Barrack - God's Hand! RandomQuestHouses[3]:= 12; //Stables - Conflagration! RandomQuestHouses[4]:= 29; //Market Hall - Weapon Fair in Town! RandomQuestHouses[5]:= 18; //Town Hall - Real Peasants' Rebellion!} RandomQuestPlace[0][0]:= 55; //pos0_X RandomQuestPlace[0][1]:= 126; //pos0_Y RandomQuestPlace[1][0]:= 123; //pos1_X RandomQuestPlace[1][1]:= 126; //pos1_Y RandomQuestPlace[2][0]:= 192; //pos2_X RandomQuestPlace[2][1]:= 126; //pos2_Y RebelSpawnLoc[0][0]:= 38; RebelSpawnLoc[0][1]:= 126; RebelSpawnLoc[1][0]:= 72; RebelSpawnLoc[1][1]:= 126; RebelSpawnLoc[2][0]:= 105; RebelSpawnLoc[2][1]:= 126; RebelSpawnLoc[3][0]:= 141; RebelSpawnLoc[3][1]:= 126; RebelSpawnLoc[4][0]:= 174; RebelSpawnLoc[4][1]:= 126; RebelSpawnLoc[5][0]:= 208; RebelSpawnLoc[5][1]:= 126; for h:=0 to High(RandomQuestPlace) do begin for i:= 0 to High(ExtraBuildingTiles[h]) do begin for j:= 0 to High(ExtraBuildingTiles[h][i]) do begin ExtraBuildingTiles[h][i][j].X:= RandomQuestPlace[h][0] + (i - 2); ExtraBuildingTiles[h][i][j].Y:= RandomQuestPlace[h][1] + (j - 3); ExtraBuildingTiles[h][i][j].TileType:= States.MapTileType(ExtraBuildingTiles[h][i][j].X, ExtraBuildingTiles[h][i][j].Y); ExtraBuildingTiles[h][i][j].TileDirection:= States.MapTileRotation(ExtraBuildingTiles[h][i][j].X, ExtraBuildingTiles[h][i][j].Y); end; end; end; UnitsMustBeRemovedFirst:= false; PortionToKill:= 75 //x% will die if it's spammable unit type (Militia, Barbarian, Bowmen, XBowmen, Serf, Recruit) PortionToDestroy:= 15 //x% of all buildings are destroyed. end; function Abs(const A: Integer): Integer; begin if A < 0 then RESULT := -A else RESULT := A; end; // HOUSES management procedure AddHouse(const ID: Integer; out Houses: array of Integer); begin SetLength(Houses, Length(Houses)+1); Houses[High(Houses)] := ID; end; procedure RemoveHouse(const ID: Integer; out Houses: array of Integer); var i: Integer; begin for i := 0 to High(Houses) do if (Houses[i] = ID) or (States.HouseOwner(Houses[i]) > 7) then break; Houses[i] := Houses[High(Houses)]; SetLength(Houses, High(Houses)); end; procedure RemoveMarket(const ID: Integer; out Market, Merc: array of Integer); var i: Integer; begin for i := 0 to High(Market) do if (Market[i] = ID) then break; Market[i] := Market[High(Market)]; Merc[i] := Merc[High(Merc)]; SetLength(Market, High(Market)); SetLength(Merc, High(Merc)); end; // SCHOOLHOUSE script procedure Recruits(const PL: Integer); var i: Integer; begin for i := 0 to High(PLAYER[PL].Buildings.Schools) do if States.HouseRepair(PLAYER[PL].Buildings.Schools[i]) AND (States.HouseResourceAmount(PLAYER[PL].Buildings.Schools[i], 7) > 0) AND (States.HouseSchoolQueue(PLAYER[PL].Buildings.Schools[i], 0) = - 1) then Actions.HouseSchoolQueueAdd(PLAYER[PL].Buildings.Schools[i], 13, 1); end; // MERCENARY units procedure Mercenary(const PL, ID, addGold, mercCost, mercType, groupType: Integer); var i, X, Y, IDNew, IDClosest: Integer; begin for i := 0 to High(PLAYER[PL].Buildings.Merc) do if ID = PLAYER[PL].Buildings.Markets[i] then break; PLAYER[PL].Buildings.Merc[i] := PLAYER[PL].Buildings.Merc[i] + addGold; if PLAYER[PL].Buildings.Merc[i] >= mercCost then begin PLAYER[PL].Buildings.Merc[i] := PLAYER[PL].Buildings.Merc[i] - mercCost; if length(PLAYER[PL].Buildings.Barracks) <> 0 then begin X := States.HouseBarracksRallyPointX(PLAYER[PL].Buildings.Barracks[0]); Y := States.HouseBarracksRallyPointY(PLAYER[PL].Buildings.Barracks[0]); end else begin X := States.HousePositionX(ID); Y := States.HousePositionY(ID); end; IDClosest := States.ClosestGroup(PL, X, Y, groupType); IDNew := Actions.GiveGroup(PL, mercType, States.HousePositionX(ID), States.HousePositionY(ID), 0, MERCS_SPAWN_COUNT, 5); if (IDClosest > 0) AND ( (Abs(X-States.UnitPositionX(States.GroupMember(IDClosest,0)))+Abs(Y-States.UnitPositionY(States.GroupMember(IDClosest,0)))) < MERC_LINK_GROUPS_RAD ) then Actions.GroupOrderLink(IDNew, IDClosest) else Actions.GroupOrderWalk(IDNew,X,Y,0); end; end; // CARAVAN script procedure TradeCalculation();// Rich player trades cca 10 000x per a game so we calculate ratio once and save this value var i,j: Byte; ratio: Double; begin for i := 0 to 27 do begin for j := 0 to 27 do begin ratio := States.MarketValue(i) / (States.MarketValue(j)*States.MarketLossFactor()); if ratio < 1 then begin TradeRatio[i][j] := Round(1/ratio); TradeSide[i][j] := True; end else begin TradeRatio[i][j] := Round(ratio); TradeSide[i][j] := False; end; end; end; end; procedure GiveWares(const PL, Ware, Count: Integer); begin Actions.GiveWares(PL,Ware,Count); if (PLAYER[PL].Bonus = btMasterCrafters) AND (Ware >=16) AND (Ware <= 26) then // Master crafters fix PLAYER[PL].WeaponsCount[Ware-16] := PLAYER[PL].WeaponsCount[Ware-16] + Count; end; procedure TakeWares(const PL, ID, Ware, Count: Integer); begin Actions.HouseTakeWaresFrom(ID,Ware,Count); if (PLAYER[PL].Bonus = btMasterCrafters) AND (Ware >=16) AND (Ware <= 26) then // Master crafters fix PLAYER[PL].WeaponsCount[Ware-16] := PLAYER[PL].WeaponsCount[Ware-16] - Count; end; procedure Caravan(const ID, aFrom, aTo: Integer); var recipient, PL: Integer; begin PL := States.HouseOwner(ID); if (PLAYER[PL].Bonus = btMasterCrafters) AND (aTo >=16) AND (aTo <= 26) then Inc(PLAYER[PL].WeaponsCount[aTo-16]); if aFrom < aTo then recipient := aTo-1 else recipient := aTo; if (recipient < 8) AND (PL <> recipient) AND (States.PlayerAllianceCheck(PL, recipient)) then begin if TradeSide[aFrom][aTo] then begin GiveWares(recipient, aFrom, TradeRatio[aFrom][aTo]); TakeWares(PL, ID, aFrom, 1); end else begin GiveWares(recipient, aFrom, 1); TakeWares(PL, ID, aFrom, TradeRatio[aFrom][aTo]); end; end // Mercenary hire else if (aTo = 22) AND (aFrom = 7) then begin Mercenary(PL, ID, 4, REBELS, 24, 1); // Lance -> Rebel TakeWares(PL, ID, aTo, 1); end else if (aTo = 24) AND (aFrom = 7) then begin Mercenary(PL, ID, 4, ROGUES, 25, 2); // Longbow -> Rogue TakeWares(PL, ID, aTo, 1); end else if (aTo = 26) AND (aFrom = 7) then begin Mercenary(PL, ID, 8, VAGABONDS, 27, 3); // Horse -> Vagabond TakeWares(PL, ID, aTo, 1); end else if (aTo = 20) AND (aFrom = 7) then begin Mercenary(PL, ID, 4, WARRIORS, 26, 0); // Handaxe -> Warrior TakeWares(PL, ID, aTo, 1); end else begin //Actions.HouseRepairEnable(ID,False); Actions.MarketSetTrade(ID, aFrom, aTo, 0); Actions.PlayWAV(PL, 'wCant', 1); end; end; // Weapons from destroyed barracks procedure GiveBarracksWeapons(const aHouse, PL: Integer); var i: Integer; begin for i := 16 to 26 do begin Actions.GiveWeapons(PL,i,States.HouseResourceAmount(aHouse,i)); if PLAYER[PL].Bonus = btMasterCrafters then PLAYER[PL].WeaponsCount[i-16] := PLAYER[PL].WeaponsCount[i-16] + States.HouseResourceAmount(aHouse,i); end; end; // BONUSES script procedure GiveWeapons(const weapons: Array of Byte; const PL: Integer); var i: Integer; begin if (States.StatHouseTypeCount(PL, 21) > 0) then for i := 0 to High(weapons) do Actions.GiveWeapons(PL, weapons[i], 1); end; procedure GiveReward(const ware, PL, Count: Integer); begin if (States.StatHouseTypeCount(PL, 11) > 0) then Actions.GiveWares(PL, ware, Count); end; // Survivalists procedure Survivalist(const PL: Integer); var aiUnits: array of Integer; var i: Integer; begin if States.GameTime div PLAYER[PL].Feeding > 1 then begin PLAYER[PL].Feeding := PLAYER[PL].Feeding + 5000; // feeding each cca 17 min aiUnits := States.PlayerGetAllUnits(PL); for i := 0 to High(aiUnits) do Actions.UnitHungerSet(aiUnits[i], States.UnitMaxHunger); end; end; // Rich - schoolhouse gold procedure GiveGold(const PL: Integer); var i: Integer; begin for i := 0 to High(PLAYER[PL].Buildings.Schools) do if States.HouseResourceAmount(PLAYER[PL].Buildings.Schools[i], 7) < 5 then Actions.HouseAddWaresTo(PLAYER[PL].Buildings.Schools[i], 7, 1); end; procedure CloseSchool(const ID: Integer); begin Actions.HouseDeliveryBlock(ID, True); if States.HouseResourceAmount(ID, 7) < 5 then Actions.HouseAddWaresTo(ID, 7, 5-States.HouseResourceAmount(ID, 7)); end; // Rich - trade procedure DoubleTrade(const aMarket, aFromWare, aToWare: Integer); begin if TradeSide[aFromWare][aToWare] then Actions.HouseAddWaresTo(aMarket, aToWare,1) else Actions.HouseAddWaresTo(aMarket, aToWare, TradeRatio[aFromWare][aToWare]); end; // Master crafters - add weapons to Barracks and faster building procedure MasterCrafter(const PL: Integer); var i, j: Integer; aiHouses: array of Integer; begin if (Length(PLAYER[PL].Buildings.Barracks) > 0) then for i := 0 to High(PLAYER[PL].WeaponsCount) do if (PLAYER[PL].WeaponsCount[i] - States.StatResourceProducedCount(PL, i+16)) <= 0 then begin PLAYER[PL].WeaponsCount[i] := PLAYER[PL].WeaponsCount[i] + 3; Actions.GiveWeapons(PL,i+16,1); end; aiHouses := States.PlayerGetAllHouses(PL); for i := 0 to High(aiHouses) do if not States.HouseIsComplete(aiHouses[i]) then if (States.HouseBuildingProgress(aiHouses[i]) mod 50 > 0) AND (States.HouseBuildingProgress(aiHouses[i]) mod 50 <= 50) then for j := 0 to 10 do Actions.HouseAddBuildingProgress(aiHouses[i]); end; // Tough People - switch militia -> barbarian procedure SwitchToBarbarian(const UnitID, GroupID: Integer); var aBarracks: Integer; begin if States.UnitType(UnitID) = 14 then begin aBarracks := States.ClosestHouse(States.UnitOwner(UnitID), States.UnitPositionX(UnitID), States.UnitPositionY(UnitID), 21); if aBarracks > -1 then begin if States.PlayerIsAI(States.UnitOwner(UnitID)) = True then Actions.HouseAddWaresTo(aBarracks, 20, 1); // Help to AI if (States.HouseResourceAmount(aBarracks, 20) >= 1) then begin Actions.HouseTakeWaresFrom(aBarracks, 20, 1); Actions.GroupOrderLink(Actions.GiveGroup(States.UnitOwner(UnitID), 23, States.UnitPositionX(UnitID), States.UnitPositionY(UnitID), States.UnitDirection(UnitID),1,1), GroupID); end else begin Actions.HouseBarracksGiveRecruit(aBarracks); Actions.HouseAddWaresTo(aBarracks, 20, 1); end; Actions.UnitKill(UnitID, True); end; end; end; // Tough People - rewards procedure Reward(const UnitID, KillerOwner: Integer); begin case States.UnitType(UnitID) of 15: GiveWeapons([16,18],KillerOwner); //Axe Fighter 16: GiveWeapons([17,19,21],KillerOwner); //Sword Fighter 17: GiveWeapons([18,24],KillerOwner); //Bowman 18: GiveWeapons([19,25],KillerOwner); //Crossbowman 19: GiveWeapons([18,22],KillerOwner); //Lance carrier 20: GiveWeapons([19,23],KillerOwner); //Pikeman 21: GiveWeapons([16,18,26],KillerOwner); //Scout 22: GiveWeapons([17,19,21,26],KillerOwner); //Knight end; end; // Snipers - kill defender if attacker is long range unit procedure Sniper(const UnitID, AttackerID: Integer); begin if (States.UnitType(AttackerID) = 17 ) OR (States.UnitType(AttackerID) = 18 ) then if States.KamRandom() < 0.04 then begin if (States.UnitType(UnitID) > 13) AND (States.UnitType(UnitID) < 28) then PLAYER[States.UnitOwner(AttackerID)].SpecialKills := PLAYER[States.UnitOwner(AttackerID)].SpecialKills + 1; Actions.UnitKill(UnitID, False); end; end; // Retribution - kill attacker procedure Retribute(const UnitID, AttackerID: Integer); begin if (States.KamRandom() < 0.04) and (States.UnitType(UnitID) > 13) and (States.UnitType(UnitID) < 28) then begin PLAYER[States.UnitOwner(UnitID)].SpecialKills := PLAYER[States.UnitOwner(UnitID)].SpecialKills + 1; Actions.UnitKill(AttackerID, False); end; end; // Building order procedures: procedure CheckBuildOrder(const aHouse: Integer); var i: Integer; begin if Length(aBuildOrder[States.HouseType(aHouse)]) > 0 then for i := 0 to High(aBuildOrder[States.HouseType(aHouse)]) do if not (States.HouseUnlocked(States.HouseOwner(aHouse), aBuildOrder[States.HouseType(aHouse)][i])) then begin Actions.HouseAllow(States.HouseOwner(aHouse), aBuildOrder[States.HouseType(aHouse)][i], True); Actions.HouseUnlock(States.HouseOwner(aHouse), aBuildOrder[States.HouseType(aHouse)][i]); end; end; procedure unlockAllBuildings(const PL: Integer); var i: Integer; var aiHouses: array of Integer; begin aiHouses := States.PlayerGetAllHouses(PL); for i := 0 to 29 do if (i <> 26) and (i <> 27) then begin Actions.HouseUnlock(PL, i); Actions.HouseAllow(PL, i, True); end; if (PLAYER[PL].Bonus <> btSurvivalists) then begin Actions.HouseAllow(PL, 27, True); Actions.HouseUnlock(PL, 27); end; end; procedure SetBuildOrder(const PL: Integer); var i: Integer; var aiHouses: array of Integer; begin for i := 0 to 29 do if (i <> 26) then Actions.HouseAllow(PL, i, False); if (PLAYER[PL].Bonus = btSurvivalists) or (PLAYER[PL].Bonus = btMasterCrafters) then unlockAllBuildings(PL) else begin aiHouses := States.PlayerGetAllHouses(PL); for i := 0 to High(aiHouses) do CheckBuildOrder(aiHouses[i]); end; end; //Choose a bonus procedure ChoseMasterCrafters(const PL: Integer); var i: Integer; begin PLAYER[PL].Bonus := btMasterCrafters; Actions.ShowMSG(PL, '<$1>'); SetLength(PLAYER[PL].WeaponsCount, 11); for i := 0 to High(PLAYER[PL].WeaponsCount) do PLAYER[PL].WeaponsCount[i] := 1; end; procedure ChoseRich(const PL: Integer); var i: Integer; aiHouses: array of Integer; begin PLAYER[PL].Bonus := btRich; Actions.ShowMSG(PL, '<$3>'); for i := 0 to High(PLAYER[PL].Buildings.Schools) do CloseSchool(PLAYER[PL].Buildings.Schools[i]); aiHouses := States.PlayerGetAllHouses(PL); end; procedure ChoseSurvivalists(const PL: Integer); begin PLAYER[PL].Bonus := btSurvivalists; Actions.ShowMSG(PL, '<$7>'); PLAYER[PL].Feeding := 1; end; procedure ChoseToughPeople(const PL: Integer); begin PLAYER[PL].Bonus := btToughPeople; Actions.ShowMSG(PL, '<$2>'); end; procedure ChoseSnipers(const PL: Integer); begin PLAYER[PL].Bonus := btSnipers; Actions.ShowMSG(PL, '<$4>'); PLAYER[PL].SpecialKills := 0; end; procedure ChoseRetribution(const PL: Integer); begin PLAYER[PL].Bonus := btRetribution; Actions.ShowMSG(PL, '<$5>'); PLAYER[PL].SpecialKills := 0; end; procedure ChooseBonus(const PL, aType, aX, aY: Integer); begin case aType of BonusChooseByHouses[0]: ChoseSurvivalists(PL); BonusChooseByHouses[1]: ChoseRich(PL); BonusChooseByHouses[2]: ChoseMasterCrafters(PL); BonusChooseByHouses[3]: ChoseToughPeople(PL); BonusChooseByHouses[4]: ChoseSnipers(PL); BonusChooseByHouses[5]: ChoseRetribution(PL); end; SetBuildOrder(PL); Actions.PlanRemove(PL, aX, aY); end; function CountEnemiesToPlayer(Player: integer) : integer; begin j:=0; For i:=0 to 7 do begin if (Alliance[Player][i] = false) and (States.PlayerEnabled(i) = true) then inc(j); end; Result:= j; end; //Update Overlay procedure UpdateOverlay(); var i, j, PL, recipient, aFrom, aTo, count, value: Integer; str: String; begin Actions.OverlayTextSet(-1, ''); // PLAYERS for PL := 0 to 7 do if States.PlayerEnabled(PL) then begin // BONUSES case PLAYER[PL].Bonus of btSurvivalists: str := '<$8>'; btRich: str := '<$9>'; btMasterCrafters: str := '<$10>'; btToughPeople: str := '<$11>'; btSnipers: str := '<$12>'+IntToStr(PLAYER[PL].SpecialKills)+'[].'; btRetribution: str := '<$13>'+IntToStr(PLAYER[PL].SpecialKills)+'[].'; else str := ''; end; // STATISTICS value := 0; for i := 14 to 26 do value := value + States.StatUnitKilledCount(PL,i); for j := 0 to 7 do if States.PlayerEnabled(j) then begin if ((PL = j) OR States.PlayerAllianceCheck(PL, j)) and (PL < 9) then begin // BONUSES & STATISTICS Actions.OverlayTextAppendFormatted(j, '<$14>'+str+'<$15>', [States.PlayerColorText(PL), States.PlayerName(PL), value, States.StatArmyCount(PL)]); end; end; if (States.GameTime - ExtraStart < 600) And (ExtraStart > 2) then begin case RandomQuestType of 0: Actions.OverlayTextAppendFormatted(PL, '|<$27>|', [States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient)]); 1: Actions.OverlayTextAppendFormatted(PL, '|<$28>|', [States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient)]); 2: Actions.OverlayTextAppendFormatted(PL, '|<$29>|', [States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient), States.UnitTypeName(UnitTypeToDie[0]), States.UnitTypeName(UnitTypeToDie[1])]); 3: Actions.OverlayTextAppendFormatted(PL, '|<$30>|', [States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient), PortionToDestroy]); 4: Actions.OverlayTextAppendFormatted(PL, '|<$31>|', [States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient)]); 5: Actions.OverlayTextAppendFormatted(PL, '|<$32>|', [RebelNumber, States.PlayerColorText(ExtraRecipient), States.PlayerName(ExtraRecipient)]); end; end; if NextExtra - States.GameTime > 0 then begin Actions.OverlayTextAppendFormatted(PL, '|<$26>|', [((NextExtra - States.GameTime) div 600), (((NextExtra - States.GameTime) mod 600) div 100), (((NextExtra - States.GameTime) mod 600) mod 100) div 10]); end; // MARKETS value := 0; for i := 0 to High(PLAYER[PL].Buildings.Markets) do if States.HouseRepair(PLAYER[PL].Buildings.Markets[i]) then begin count := States.MarketOrderAmount(PLAYER[PL].Buildings.Markets[i]); if count > 0 then begin aFrom := States.MarketFromWare(PLAYER[PL].Buildings.Markets[i]); aTo := States.MarketToWare(PLAYER[PL].Buildings.Markets[i]); // MERCENARY - check peace time if (aFrom = 7) AND ( (aTo = 20) OR (aTo = 22) OR (aTo = 24) OR (aTo = 26) ) then begin if States.GameTime < States.PeaceTime then begin Actions.MarketSetTrade(PLAYER[PL].Buildings.Markets[i], aFrom, aTo, 0); Actions.ShowMsg(PL, '<$18>'); Actions.PlayWAV(PL, 'wCant', 1); end; end // CARAVAN else begin if TradeSide[aFrom][aTo] then count := count*TradeRatio[aFrom][aTo]; if aFrom < aTo then recipient := aTo-1 else recipient := aTo; value := value+1; if (recipient < 8) AND (States.PlayerEnabled(recipient)) AND (States.PlayerAllianceCheck(PL, recipient)) then begin for j := 0 to 7 do if States.PlayerEnabled(j) AND States.PlayerAllianceCheck(j, PL) then begin//AND States.PlayerAllianceCheck(j, recipient) if (value = 1) then Actions.OverlayTextAppend(j,'|'); Actions.OverlayTextAppendFormatted(j, '<$16>', [count,States.WareTypeName(aFrom),States.PlayerColorText(recipient),States.PlayerName(recipient)]) end; end else begin Actions.MarketSetTrade(PLAYER[PL].Buildings.Markets[i], aFrom, aTo, 0); Actions.PlayWAV(PL, 'wCant', 1); end; end; end; end; end; end; procedure MultiplyWares(WareType, player: integer); begin if (t[player][WareType].Amount - States.StatResourceProducedCount(player,t[player][WareType].ID)) <= 0 then begin t[player][WareType].Amount := t[player][WareType].Amount + t[player][WareType].TrackIncrease; Actions.GiveWares(player, t[player][WareType].ID, t[player][WareType].AmountAdd); MultiplyWares(WareType, player); end; end; function Max(integy, intketto: integer) : integer; begin if integy > intketto then Result:= integy else Result:= intketto; end; procedure GiveWeaponFair(Barrack: integer); begin For i:=16 to 26 do begin Actions.HouseAddWaresTo(Barrack, i, Max(20, States.HouseResourceAmount(Barrack, i) * 40 div 100)); end; end; procedure AddInn(out Inns: array of Integer; const Inn: Integer); begin SetLength(Inns, Length(Inns) + 1); Inns[High(Inns)]:= Inn; end; procedure RemoveInn(out Inns: array of Integer; const Inn: Integer); begin m:= 0; while (Inns[m] <> Inn) do begin Inc(m); end; for n:= (m + 1) to High(Inns) do begin Inns[n-1]:= Inns[n]; end; SetLength(Inns, Length(Inns) - 1) end; procedure FillEveryInn(const Inns: array of Integer); begin for m:=0 to High(Inns) do begin t[States.HouseOwner(Inns[m])][3].Amount:= t[States.HouseOwner(Inns[m])][3].Amount + 5 - States.HouseResourceAmount(Inns[m], 0); t[States.HouseOwner(Inns[m])][5].Amount:= t[States.HouseOwner(Inns[m])][5].Amount + 5 - States.HouseResourceAmount(Inns[m], 27); for n:=0 to High(FoodTypes) do begin Actions.HouseAddWaresTo(Inns[m], FoodTypes[n], 5 - States.HouseResourceAmount(Inns[m], n)); end; end; end; procedure FeedEveryUnit(Units: array of integer); begin for n:=0 to High(Units) do begin Actions.UnitHungerSet(Units[n], States.UnitMaxHunger); end; end; procedure AddExtraFoodToStore(Player: Integer); begin Actions.GiveWares(Player, FoodTypes[0], 100); Actions.GiveWares(Player, FoodTypes[1], 75); Actions.GiveWares(Player, FoodTypes[2], 50); Actions.GiveWares(Player, FoodTypes[3], 100); t[Player][3].Amount:= t[Player][3].Amount + 100; t[Player][5].Amount:= t[Player][5].Amount + 100; end; procedure Extra_RandomDeath(Beneficiary, Attacked: Integer); begin //IF PLAYER IS ENEMY, IT WILL LOSE A RANDOM UNIT THIS TICK if Alliance[Beneficiary][Attacked] = false and (States.PlayerEnabled(Attacked) = true) and (States.PlayerDefeated(Attacked) = false) then begin UnitTracker[Attacked]:= States.PlayerGetAllUnits(Attacked); if High(UnitTracker[Attacked]) = -1 then exit; Extra_RandomDeath_Unit:= States.KamRandomI(High(UnitTracker[Attacked])+1); Actions.UnitKill(UnitTracker[Attacked][Extra_RandomDeath_Unit], false); end; end; procedure KillRandomType(UnitType, Player: integer); var Units: array of integer; var NumberOfUnitTypeUnits, UnitsAlreadyKilled: integer; begin Units:= States.PlayerGetAllUnits(Player); NumberOfUnitTypeUnits:= 0; UnitsAlreadyKilled:= 0; For m:=0 to High(Units) do begin if States.UnitType(Units[m]) = UnitType then inc(NumberOfUnitTypeUnits); end; For m:=0 to High(Units) do begin case UnitType of 0, 13, 14, 17, 18, 23: begin if (States.UnitType(Units[m]) = UnitType) and (UnitsAlreadyKilled < ((NumberOfUnitTypeUnits * PortionToKill) div 100)) then begin Actions.UnitKill(Units[m], false); inc(UnitsAlreadyKilled); end; end; else begin if (States.UnitType(Units[m]) = UnitType) then begin Actions.UnitKill(Units[m], false); inc(UnitsAlreadyKilled); end; end; end; end; end; procedure RemoveCheaterField(aPlayer, aX, aY: integer); begin for i:=0 to High(RandomQuestPlace) do begin case i of 0, 2: begin if (Abs(aX - RandomQuestPlace[i][0]) <= 20) And (Abs(aY - RandomQuestPlace[i][1]) <= 20) then begin Actions.PlanRemove(aPlayer, aX, aY); if States.PlayerIsAI(aPlayer) then Actions.AIAutoBuild(aPlayer, false); end; end; 1: begin if (((aX - RandomQuestPlace[i][0]) >= -27) And ((aX - RandomQuestPlace[i][0]) <= 25)) And (((aY - RandomQuestPlace[i][1] >= -13) And ((aY - RandomQuestPlace[i][1]) <= 12))) then begin Actions.PlanRemove(aPlayer, aX, aY); if States.PlayerIsAI(aPlayer) then Actions.AIAutoBuild(aPlayer, false); end; end; end; end; end; // EVENTS procedure OnPlanFieldPlaced(aPlayer, aX, aY: Integer); begin RemoveCheaterField(aPlayer, aX, aY); end; procedure OnPlanRoadPlaced(aPlayer, aX, aY: Integer); begin RemoveCheaterField(aPlayer, aX, aY); end; procedure OnPlanWinefieldPlaced(aPlayer, aX, aY: Integer); begin RemoveCheaterField(aPlayer, aX, aY); end; procedure OnHousePlanPlaced(PL, aX, aY, THouseType: Integer); begin if PLAYER[PL].Bonus = btNone then ChooseBonus(PL, THouseType, aX, aY) // if ((States.StatHouseTypeCount(PL, 17)+States.StatHouseTypePlansCount(PL, 17)) > TOWERS_LIMIT) then // - THIS DOES NOT WORK!!! StatHouseTypeCount takes ONLY COMPLETED HOUSES and StatHouseTypePlansCount takes ONLY UNTOUCHED PLANS so there still are plans with uncompleted houses else if THouseType = 17 then if PLAYER[PL].TowersCount < TOWERS_LIMIT then Inc(PLAYER[PL].TowersCount) else begin Actions.ShowMSG(PL, '<$17> '+IntToStr(TOWERS_LIMIT)+'!'); Actions.PlanRemove(PL, aX, aY); end; RemoveCheaterField(PL, aX, aY); end; procedure OnHousePlanRemoved(PL: Integer; aX: Integer; aY: Integer; THouseType: Integer); begin if THouseType = 17 then Dec(PLAYER[PL].TowersCount); end; procedure OnHouseBuilt(aHouse: Integer); begin if not States.PlayerIsAI(States.HouseOwner(aHouse)) and not (PLAYER[States.HouseOwner(aHouse)].Bonus = btSurvivalists) and not (PLAYER[States.HouseOwner(aHouse)].Bonus = btMasterCrafters) then CheckBuildOrder(aHouse); if (States.HouseType(aHouse) = 13) then begin AddHouse(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Schools); CloseSchool(aHouse); end else if (States.HouseType(aHouse) = 21) then AddHouse(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Barracks) else if (States.HouseType(aHouse) = 29) then begin AddHouse(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Markets); AddHouse(0, PLAYER[States.HouseOwner(aHouse)].Buildings.Merc); end; if (States.HouseType(aHouse) = 27) and (States.HouseOwner(aHouse) < 8) then begin AddInn(PlayerInns[States.HouseOwner(aHouse)], aHouse); end; end; procedure OnHouseDestroyed(aHouse, aDestroyerIndex: Integer); begin if States.HouseIsComplete(aHouse) and (States.HouseOwner(aHouse) < 8) then begin if (States.HouseType(aHouse) = 13) then RemoveHouse(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Schools) else if (States.HouseType(aHouse) = 21) then begin RemoveHouse(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Barracks); if States.HouseOwner(aHouse) <> aDestroyerIndex then GiveBarracksWeapons(aHouse, aDestroyerIndex); end else if (States.HouseType(aHouse) = 29) then RemoveMarket(aHouse, PLAYER[States.HouseOwner(aHouse)].Buildings.Markets, PLAYER[States.HouseOwner(aHouse)].Buildings.Merc); end; if (States.HouseType(aHouse) = 17) then Dec(PLAYER[States.HouseOwner(aHouse)].TowersCount); if (States.HouseOwner(aHouse) = 8) then begin ExtraRecipient:= aDestroyerIndex; ExtraStart:= States.GameTime; ExtraEnd:= ExtraStart + ExtraDuration; RebelNumber:= CountEnemiesToPlayer(ExtraRecipient) * RebelsToSpawn; for m:= 0 to High(RandomQuestHouses) do begin if States.HouseType(aHouse) = RandomQuestHouses[m] then begin ExtraActive[m]:= true; AlreadyRemovedUnits:=false; end; end; end; if (States.HouseType(aHouse) = 27) and (States.HouseOwner(aHouse) < 8) then begin if States.HouseIsComplete(aHouse) then RemoveInn(PlayerInns[States.HouseOwner(aHouse)], aHouse); end; end; procedure OnMarketTrade(aMarket, aFrom, TWareType: Integer); begin if States.HouseRepair(aMarket) then Caravan(aMarket, aFrom, TWareType) else if PLAYER[States.HouseOwner(aMarket)].Bonus = btRich then DoubleTrade(aMarket, aFrom, TWareType); end; procedure OnUnitTrained(UnitID: Integer); var PL: Integer; begin PL := States.UnitOwner(UnitID); if (PL <> -1) then GiveGold(PL); end; procedure OnWarriorEquipped(UnitID, aGroupID: Integer); begin if PLAYER[States.UnitOwner(UnitID)].Bonus = btToughPeople then SwitchToBarbarian(UnitID, aGroupID); end; procedure OnUnitAttacked(UnitID, AttackerID: Integer); begin if (AttackerID > -1) AND (UnitID > -1) then if (not States.UnitDead(AttackerID)) AND (not States.UnitDead(UnitID)) then begin if States.UnitOwner(AttackerID) > -1 then if PLAYER[States.UnitOwner(AttackerID)].Bonus = btSnipers then Sniper(UnitID, AttackerID); if States.UnitOwner(UnitID) > -1 then if PLAYER[States.UnitOwner(UnitID)].Bonus = btRetribution then Retribute(UnitID, AttackerID); end; end; { procedure OnUnitWounded(aUnit, aAttacker: Integer); begin end; } procedure OnUnitDied(UnitID, aKillerOwner: Integer); begin if (aKillerOwner > -1) AND (aKillerOwner < 8) AND (PLAYER[aKillerOwner].Bonus = btToughPeople) AND (States.KaMRandom()<0.3) then Reward(UnitID, aKillerOwner); end; procedure OnMissionStart; var PL, i: Integer; aiHouses: array of Integer; text: String; begin Initialize(); Actions.ShowMSG(-1, '<$25>'); aBuildOrder[0] := [3, 4, 5, 6, 8, 19, 21, 28, 29];aBuildOrder[1] := [2, 10, 23];aBuildOrder[2] := [];aBuildOrder[3] := [];aBuildOrder[4] := [1];aBuildOrder[5] := [15];aBuildOrder[6] := [];aBuildOrder[7] := [];aBuildOrder[8] := [12, 16, 22];aBuildOrder[9] := [0];aBuildOrder[10] := [];aBuildOrder[11] := [11, 13];aBuildOrder[12] := [];aBuildOrder[13] := [14, 27];aBuildOrder[14] := [9, 17];aBuildOrder[15] := [18];aBuildOrder[16] := [24, 25];aBuildOrder[17] := [];aBuildOrder[18] := [];aBuildOrder[19] := [];aBuildOrder[20] := [];aBuildOrder[21] := [];aBuildOrder[22] := [7];aBuildOrder[23] := [];aBuildOrder[24] := [];aBuildOrder[25] := [20];aBuildOrder[26] := [];aBuildOrder[27] := [14];aBuildOrder[28] := [];aBuildOrder[29] := []; BonusChooseByHouses := [27, 15, 1, 21, 17, 29]; //[Inn, Metallurgist's, Iron Smithy, Barracks, Watchtower, Market] TradeCalculation(); SetLength(PLAYER, 10); for PL := 0 to 7 do if States.PlayerEnabled(PL) then begin // Schoolhouse + Castle + Towers count aiHouses := States.PlayerGetAllHouses(PL); PLAYER[PL].TowersCount := 0; for i := 0 to High(aiHouses) do begin if (States.HouseType(aiHouses[i]) = 13) and States.HouseIsComplete(aiHouses[i]) then AddHouse(aiHouses[i], PLAYER[PL].Buildings.Schools) else if (States.HouseType(aiHouses[i]) = 21) and States.HouseIsComplete(aiHouses[i]) then AddHouse(aiHouses[i], PLAYER[PL].Buildings.Barracks) else if (States.HouseType(aiHouses[i]) = 29) and States.HouseIsComplete(aiHouses[i]) then begin AddHouse(aiHouses[i], PLAYER[PL].Buildings.Markets); AddHouse(0, PLAYER[PL].Buildings.Merc); end else if (States.HouseType(aiHouses[i]) = 17) then PLAYER[PL].TowersCount := PLAYER[PL].TowersCount + 1; end; // Building order (Bonuses) for i := 0 to 29 do if (i <> 26) then Actions.HouseAllow(PL, i, False); for i := Low(BonusChooseByHouses) to High(BonusChooseByHouses) do begin Actions.HouseAllow(PL, BonusChooseByHouses[i], True); Actions.HouseUnlock(PL, BonusChooseByHouses[i]); end; // AI Bonus if States.PlayerIsAI(PL) then begin case States.KamRandomI(4) of 0: ChoseRetribution(PL); 1: ChoseSnipers(PL); 2: ChoseMasterCrafters(PL); 3: ChoseToughPeople(PL); end; // AI configuration unlockAllBuildings(PL); // AI works only with specific unlock order (or with everything on) Actions.AIEquipRate(PL,0,0); Actions.AIEquipRate(PL,1,0); Actions.AIWorkerLimit(PL, 35); //Actions.AISerfsPerHouse(PL, 1.5);// KaM does not recognize this action :( Actions.AISoldiersLimit(PL,-1); end else PLAYER[PL].Bonus := btNone; text := text + '[$'+ States.PlayerColorText(PL)+']'+States.PlayerName(PL)+'[] = [$B9B9FF]'+States.WareTypeName(PL)+'|'; end; ChoseRetribution(9); Actions.ShowMSG(-1, '<$0>'); // Welcome message Actions.ShowMSG(-1, text); // Players representation end; procedure OnTick; var PL: Integer; begin //PRODUCTION ENHANCEMENT i:= States.GameTime mod 640 if (i mod 10 = 0) and ((i mod 80) div 10 < 6) then MultiplyWares((i mod 80) div 10, i div 80); //EXTRA BUILDING PLACEMENT if States.GameTime = NextExtra then begin {for h:=0 to 2 do begin for i:=0 to 4 do begin for j:=0 to 3 do begin if States.UnitAt(ExtraBuildingTiles[h][i][j].X, ExtraBuildingTiles[h][i][j].Y) <> -1 then begin Actions.GroupKillAll(States.UnitsGroup(States.UnitAt(ExtraBuildingTiles[h][i][j].X, ExtraBuildingTiles[h][i][j].Y)), false); UnitsMustBeRemovedFirst:= true; end; end; end; end;} if AlreadyRemovedUnits = false then begin for h:=0 to 2 do begin for i:= -5 to 5 do begin for j:= -7 to 7 do begin m:= RandomQuestPlace[h][0] + i; n:= RandomQuestPlace[h][1] + j; if States.UnitAt(m, n) <> -1 then begin Actions.UnitKill(States.UnitAt(m, n), false); UnitsMustBeRemovedFirst:= true; end; end; end; end; end; if UnitsMustBeRemovedFirst then begin NextExtra:= NextExtra + 20; UnitsMustBeRemovedFirst:= false; AlreadyRemovedUnits:=true; Exit; end; RandomQuestLoc:= States.KaMRandomI(High(RandomQuestPlace)+1); RandomQuestType:= States.KaMRandomI(High(RandomQuestHouses)+1); j:= Actions.GiveHouse(8, RandomQuestHouses[RandomQuestType], RandomQuestPlace[RandomQuestLoc][0], RandomQuestPlace[RandomQuestLoc][1]); end; // Statistics if (States.GameTime mod UPDATE_OVERLAY_DELAY) = 0 then UpdateOverlay(); i:= States.GameTime mod 10 if (i < 8) then begin if States.PlayerEnabled(i) then begin // Schoolhouse if not States.PlayerIsAI(i) then Recruits(i); // Bonuses if PLAYER[i].Bonus = btSurvivalists then Survivalist(i) else if PLAYER[i].Bonus = btMasterCrafters then MasterCrafter(i); for j:=0 to 5 do MultiplyWares(j, i); end; //EXTRAS if ExtraActive[0] = true then begin //0 is Plague! Extra_RandomDeath(ExtraRecipient, i); if States.GameTime > ExtraEnd then begin ExtraActive[0]:= false; NextExtra:= States.GameTime + ExtraInterval - ExtraDuration; end; end; if ExtraActive[1] = true then begin //1 is Abundance! for j:=0 to 7 do begin if Alliance[ExtraRecipient][j] = true then begin FeedEveryUnit(States.PlayerGetAllUnits(j)); FillEveryInn(PlayerInns[j]); AddExtraFoodToStore(j); end; end; ExtraActive[1]:= false; NextExtra:= States.GameTime + ExtraInterval; end; if ExtraActive[2] = true then begin //2 is God's Hand! UnitTypeToDie[0]:= States.KamRandomI(24); repeat UnitTypeToDie[1]:= States.KamRandomI(24); until UnitTypeToDie[0] <> UnitTypeToDie[1]; for j:=0 to 7 do begin if Alliance[ExtraRecipient][j] = false then begin KillRandomType(UnitTypeToDie[0], j); KillRandomType(UnitTypeToDie[1], j); end; end; ExtraActive[2]:= false; NextExtra:= ExtraStart + ExtraInterval; end; if ExtraActive[3] = true then begin //3 is Conflagration! for j:= 0 to 7 do begin if Alliance[ExtraRecipient][j] = false then begin HousesToDestroy:= States.PlayerGetAllHouses(j); for k:=1 to (((High(HousesToDestroy)) * PortionToDestroy) div 100) do begin BuildingToDestroy:= States.KaMRandomI(High(HousesToDestroy)+1); case States.HouseType(HousesToDestroy[BuildingToDestroy]) of 11, 13, 18, 21, 27, 29: Dec(k); else Actions.HouseDestroy(HousesToDestroy[BuildingToDestroy], false); end; end; end; end; ExtraActive[3]:= false; NextExtra:= States.GameTime + ExtraInterval; end; if ExtraActive[4] = true then begin //4 is Weapon Fair in Town! for j:=0 to 7 do begin if Alliance[ExtraRecipient][j] = true then begin for k:=0 to High(PLAYER[j].Buildings.Barracks) do begin GiveWeaponFair(PLAYER[j].Buildings.Barracks[k]); end; end; end; ExtraActive[4]:= false; NextExtra:= States.GameTime + ExtraInterval; end; if ExtraActive[5] = true then begin //5 is REAL Peasants' Rebellion! for j:=0 to 7 do begin if Alliance[ExtraRecipient][j] = false then Actions.PlayerAllianceChange(9, j, true, false) else Actions.PlayerAllianceChange(9, j, true, true); end; Actions.PlayerAllianceChange(8, 9, true, true); for j:=0 to High(RebelSpawnLoc) do begin Actions.GiveGroup(9, 24, RebelSpawnLoc[j][0], RebelSpawnLoc[j][1], 4, (RebelNumber div Length(RebelSpawnLoc)), 8); end; ExtraActive[5]:= false; NextExtra:= States.GameTime + ExtraInterval; end; end; end;
<<

grayter

Barbarian

Posts: 107

Joined: 18 Aug 2014, 12:06

KaM Skill Level: Skilled

Location: Poland

Post 08 Nov 2017, 07:09

Re: Error in script, please help!

I think this message appears, because you try to do something with group which is dead. I suggest you to check States.GroupDead in each case. You need to reproduce the problem, because code analysis is hard indeed. Try to find exact moment when problem appears. Maybe you will be able to localize problem in some function/procedure. It will be easier that way.
<<

Rey

User avatar

KaM Remake Developer

Posts: 217

Joined: 12 Oct 2016, 07:41

KaM Skill Level: Fair

Location: Moscow

Post 08 Nov 2017, 07:48

Re: Error in script, please help!

I checked source code - error happens in next block:
https://github.com/Kromster80/kam_remak ... s.pas#L862

It happens, when "//Enemy was killed, but target Group still exists", then we try to find another enemy from the same group, but there are no valid (not dead or dying) group members. Sounds like a bug for me. That should never happen.
If you could track the situation, when it happens, then I will be able to fix it.
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 08 Nov 2017, 12:44

Re: Error in script, please help!

Thank you!

I believe this issue is probably caused by a fact that I have a code which kills random enemy unit every second during a set period.

What I think happens is that there are 2 units in the group: one that was just killed by a unit, ordered to attack it. So group still exists, meaning next target will be selected. But - in the meantime - my script kills this unit, causing a crash. No?
What do you think?

If you want to find this script part search for the term “plague” under ontick.

I will have access to the crash replay this evening, so I will try to reproduce or observe the moment it happens.

Appreciate your help guys!
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 09 Nov 2017, 18:40

Re: Error in script, please help!

Sadly this was not the case. Noone was tough people that game.

I was able to get my hands on the replay.

Although, I cannot reproduce the error, nor can i get the replay to display what's happening. I get a warning message instead of the regular bug window.

But now I fully understand the source code: A unit had an attack order an another unit. This unit died while being targeted. Then code was looking for another foe, and this is where I get the error.
<<

Rey

User avatar

KaM Remake Developer

Posts: 217

Joined: 12 Oct 2016, 07:41

KaM Skill Level: Fair

Location: Moscow

Post 09 Nov 2017, 20:03

Re: Error in script, please help!

So it seems to be a quite rare error.
I can simply fix it removing Assert clause and just ignore that situation.
Ofc its better to figure it out why it happens exactly, but considering that it appears very rary I think this solution is good enought
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 09 Nov 2017, 21:15

Re: Error in script, please help!

If you want the replay, here you go.

By the way how do you modify source code?
You do not have the required permissions to view the files attached to this post.
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 10 Nov 2017, 21:39

Re: Error in script, please help!

The error happened again. So tomorrow I will try to look into it again.

I have a suggestion.

You should not remove the assert part. I think if the assert condition returns false, it should restart from the 'if'. So it checks again:

------------------------------------------------------------------------------

if (OrderTargetUnit = nil) and (OrderTargetGroup <> nil) then
begin
//Old enemy has died, change target to his comrades
U := OrderTargetGroup.GetNearestMember(Members[0].GetPosition);
Assert(U <> nil, 'We checked that Group is not dead, hence we should have a valid Unit'); (here, it goes back to the start)
OrderAttackUnit(U, False);
end;

------------------------------------------------------------------------------


What do you think?
<<

Erdesz Balazs

Serf

Posts: 7

Joined: 07 Nov 2017, 19:43

KaM Skill Level: Skilled

Post 11 Nov 2017, 17:20

Re: Error in script, please help!

I had time to investigate. I have the EXACT reason for the error.

My script kills random units every second. And, during this, it can kill units that haven't yet spawned to the playground. (For example, it can kill units that have already been trained but haven't left the barrack yet.)

Then when this group's units would vanish completely (e.g. last unit is killed), I get the error.





So the issue is: When these units die inside the barrack, they are most probably not removed from the group they were supposed to be part of. And then the game tries to look for a new target in the group, but the group is nonexistent anymore.
<<

Rey

User avatar

KaM Remake Developer

Posts: 217

Joined: 12 Oct 2016, 07:41

KaM Skill Level: Fair

Location: Moscow

Post 12 Nov 2017, 07:43

Re: Error in script, please help!

Thank you very much for your investigation!

I will look into it and try to fix it then ;)
<<

Rey

User avatar

KaM Remake Developer

Posts: 217

Joined: 12 Oct 2016, 07:41

KaM Skill Level: Fair

Location: Moscow

Post 17 Nov 2017, 19:58

Re: Error in script, please help!

So the issue is: When these units die inside the barrack, they are most probably not removed from the group they were supposed to be part of. And then the game tries to look for a new target in the group, but the group is nonexistent anymore.
I checked the source code - and it looks like your theory is not correct, because soldier is not assigned to any group when he is inside Barracks. Group assign happens only when soldier went outside from Barracks.
I'll fix this error in a very simple way, as I said earlier.

Return to “Dynamic Scripting”

Who is online

Users browsing this forum: Ahrefs [Bot] and 9 guests