diff --git a/binaries/data/mods/public/simulation/ai/aegis/base-manager.js b/binaries/data/mods/public/simulation/ai/aegis/base-manager.js
index 0a814ba874..4cc3e7f34c 100644
--- a/binaries/data/mods/public/simulation/ai/aegis/base-manager.js
+++ b/binaries/data/mods/public/simulation/ai/aegis/base-manager.js
@@ -622,8 +622,9 @@ m.BaseManager.prototype.checkResourceLevels = function (gameState,queues) {
numFarms += queues.field.countQueuedUnits();
// let's see if we need to push new farms.
+ var maxGatherers = gameState.getTemplate(gameState.applyCiv("structures/{civ}_field")).maxGatherers();
if (numFd < 2)
- if (numFarms < Math.round(this.gatherersByType(gameState, "food").length / 4.6) || numFarms < Math.round(this.workers.length / 15.0))
+ if (numFarms < Math.round(this.gatherersByType(gameState, "food").length / (maxGatherers*0.9)) || numFarms < Math.round(this.workers.length / (maxGatherers*3))
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
// TODO: refine count to only count my base.
}
diff --git a/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js b/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js
index bbb7f8b970..043c5c43a6 100755
--- a/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js
+++ b/binaries/data/mods/public/simulation/ai/aegis/defence-helper.js
@@ -505,7 +505,7 @@ m.Army.prototype.update = function (gameState)
{
var id = this.entities[i];
var ent = gameState.getEntityById(id);
- if (!ent.position) // shouldn't be able to happen but apparently does.
+ if (!ent || !ent.position()) // shouldn't be able to happen but apparently does.
continue;
if (API3.SquareVectorDistance(ent.position(), this.position) > this.breakawaySize)
{
diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js
index 9cbacacf0e..3db569cb32 100644
--- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js
+++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js
@@ -157,6 +157,8 @@ m.GameState.prototype.townPhase = function()
m.GameState.prototype.cityPhase = function()
{
+ if (this.playerData.civ == "athen")
+ return "phase_city_athen";
return "phase_city_generic";
};
diff --git a/binaries/data/mods/public/simulation/ai/common-api/shared.js b/binaries/data/mods/public/simulation/ai/common-api/shared.js
index b4dc583de5..a01afef289 100644
--- a/binaries/data/mods/public/simulation/ai/common-api/shared.js
+++ b/binaries/data/mods/public/simulation/ai/common-api/shared.js
@@ -131,8 +131,12 @@ m.SharedScript.prototype.init = function(state) {
this._entities = {};
for (var id in state.entities)
+ {
+ // entropy generator
+ for (var p = 0; p < id; ++p)
+ Math.random();
this._entities[id] = new m.Entity(this, state.entities[id]);
-
+ }
// entity collection updated on create/destroy event.
this.entities = new m.EntityCollection(this, this._entities);
diff --git a/binaries/data/mods/public/simulation/components/AIInterface.js b/binaries/data/mods/public/simulation/components/AIInterface.js
index f7ba2f1a61..a6d9fb0775 100644
--- a/binaries/data/mods/public/simulation/components/AIInterface.js
+++ b/binaries/data/mods/public/simulation/components/AIInterface.js
@@ -3,19 +3,26 @@ function AIInterface() {}
AIInterface.prototype.Schema =
"";
+AIInterface.prototype.EventNames = [
+ "Create",
+ "Destroy",
+ "Attacked",
+ "RangeUpdate",
+ "ConstructionFinished",
+ "TrainingFinished",
+ "AIMetadata",
+ "PlayerDefeated",
+ "EntityRenamed",
+ "OwnershipChanged",
+ "Garrison",
+ "UnGarrison"
+];
+
AIInterface.prototype.Init = function()
{
this.events = {};
- this.events["Create"] = [];
- this.events["Destroy"] = [];
- this.events["Attacked"] = [];
- this.events["RangeUpdate"] = [];
- this.events["ConstructionFinished"] = [];
- this.events["TrainingFinished"] = [];
- this.events["AIMetadata"] = [];
- this.events["PlayerDefeated"] = [];
- this.events["EntityRenamed"] = [];
- this.events["OwnershipChanged"] = [];
+ for each (var i in this.EventNames)
+ this.events[i] = [];
this.changedEntities = {};
@@ -34,28 +41,13 @@ AIInterface.prototype.GetNonEntityRepresentation = function()
var state = cmpGuiInterface.GetExtendedSimulationState(-1);
// Add some extra AI-specific data
+ // add custom events and reset them for the next turn
state.events = {};
- state.events["Create"] = this.events["Create"];
- state.events["Destroy"] = this.events["Destroy"];
- state.events["Attacked"] = this.events["Attacked"];
- state.events["RangeUpdate"] = this.events["RangeUpdate"];
- state.events["ConstructionFinished"] = this.events["ConstructionFinished"];
- state.events["TrainingFinished"] = this.events["TrainingFinished"];
- state.events["AIMetadata"] = this.events["AIMetadata"];
- state.events["PlayerDefeated"] = this.events["PlayerDefeated"];
- state.events["EntityRenamed"] = this.events["EntityRenamed"];
- state.events["OwnershipChanged"] = this.events["OwnershipChanged"];
- // Reset the event list for the next turn
- this.events["Create"] = [];
- this.events["Destroy"] = [];
- this.events["Attacked"] = [];
- this.events["RangeUpdate"] = [];
- this.events["ConstructionFinished"] = [];
- this.events["TrainingFinished"] = [];
- this.events["AIMetadata"] = [];
- this.events["PlayerDefeated"] = [];
- this.events["EntityRenamed"] = [];
- this.events["OwnershipChanged"] = [];
+ for each (var i in this.EventNames)
+ {
+ state.events[i] = this.events[i];
+ this.events[i] = [];
+ }
return state;
};
@@ -90,18 +82,8 @@ AIInterface.prototype.GetFullRepresentation = function(flushEvents)
var state = this.GetNonEntityRepresentation();
if (flushEvents)
- {
- state.events["Create"] = [];
- state.events["Destroy"] = [];
- state.events["Attacked"] = [];
- state.events["RangeUpdate"] = [];
- state.events["ConstructionFinished"] = [];
- state.events["TrainingFinished"] = [];
- state.events["AIMetadata"] = [];
- state.events["PlayerDefeated"] = [];
- state.events["EntityRenamed"] = [];
- state.events["OwnershipChanged"] = [];
- }
+ for each (var i in this.EventNames)
+ state.events[i] = [];
// Add entity representations
Engine.ProfileStart("proxy representations");
diff --git a/binaries/data/mods/public/simulation/components/AIProxy.js b/binaries/data/mods/public/simulation/components/AIProxy.js
index a00f7b9fac..aca09bc928 100644
--- a/binaries/data/mods/public/simulation/components/AIProxy.js
+++ b/binaries/data/mods/public/simulation/components/AIProxy.js
@@ -34,7 +34,8 @@ AIProxy.prototype.Init = function()
{
this.changes = null;
this.needsFullGet = true;
- this.owner = -1; // for convenience now and then.
+ // cache some data across turns
+ this.owner = -1;
this.cmpAIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_AIInterface);
@@ -76,7 +77,7 @@ AIProxy.prototype.NotifyChange = function()
if (!this.changes)
{
this.changes = {};
- this.cmpAIInterface.ChangedEntity(this.entity);
+ this.cmpAIInterface.ChangedEntity(this.entity);
}
};
@@ -134,6 +135,15 @@ AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg)
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
this.changes.garrisoned = cmpGarrisonHolder.GetEntities();
+
+ // Send a message telling a unit garrisoned or ungarrisoned.
+ // I won't check if the unit is still alive so it'll be up to the AI.
+ var added = msg.added;
+ var removed = msg.removed;
+ for each (var ent in added)
+ this.cmpAIInterface.PushEvent("Garrison", {"entity" : ent, "holder": this.entity});
+ for each (var ent in removed)
+ this.cmpAIInterface.PushEvent("UnGarrison", {"entity" : ent, "holder": this.entity});
};
AIProxy.prototype.OnResourceSupplyChanged = function(msg)
diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js
index a30c76545c..5dfd56dce9 100644
--- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js
+++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js
@@ -244,7 +244,7 @@ GarrisonHolder.prototype.PerformGarrison = function(entity)
if (cmpAura && cmpAura.HasGarrisonAura())
cmpAura.ApplyGarrisonBonus(this.entity);
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
if (cmpUnitAI && cmpUnitAI.GetAlertRaiser())
@@ -310,7 +310,7 @@ GarrisonHolder.prototype.Eject = function(entity, forced)
cmpNewPosition.JumpTo(pos.x, pos.z);
// TODO: what direction should they face in?
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
return true;
};
@@ -563,7 +563,7 @@ GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg)
if (cmpHealth && cmpHealth.GetHitpoints() == 0)
{
this.entities.splice(entityIndex, 1);
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
this.UpdateGarrisonFlag();
}
else if(!IsOwnedByMutualAllyOfEntity(this.entity, this.entities[entityIndex]))
@@ -580,7 +580,7 @@ GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
if (entityIndex != -1)
{
this.entities[entityIndex] = msg.newentity;
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [msg.newentity], "removed": [msg.entity] });
}
};
@@ -628,7 +628,7 @@ GarrisonHolder.prototype.EjectOrKill = function(entities)
this.entities.splice(entityIndex, 1);
}
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : entities });
this.UpdateGarrisonFlag();
};
diff --git a/binaries/data/mods/public/simulation/components/TechnologyManager.js b/binaries/data/mods/public/simulation/components/TechnologyManager.js
index b24b816353..0cddba8e4c 100644
--- a/binaries/data/mods/public/simulation/components/TechnologyManager.js
+++ b/binaries/data/mods/public/simulation/components/TechnologyManager.js
@@ -49,8 +49,6 @@ TechnologyManager.prototype.Init = function ()
if (this.allTechs[key].autoResearch || this.allTechs[key].top)
this.autoResearchTech[key] = this.allTechs[key];
}
-
- this.UpdateAutoResearch();
};
TechnologyManager.prototype.OnUpdate = function ()
@@ -337,12 +335,12 @@ TechnologyManager.prototype.ResearchTechnology = function (tech)
this.UpdateAutoResearch();
var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
- if (!cmpPlayer || ! cmpPlayer.GetPlayerID())
+ if (!cmpPlayer || cmpPlayer.GetPlayerID() === undefined)
return;
var playerID = cmpPlayer.GetPlayerID();
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
var ents = cmpRangeManager.GetEntitiesByPlayer(playerID);
- // TODO: Handle technology broadcasting for autoresearch properly (some components might not be initialized currently)
+
for (var component in modifiedComponents)
{
Engine.PostMessage(SYSTEM_ENTITY, MT_TemplateModification, { "player": playerID, "component": component, "valueNames": modifiedComponents[component]});
diff --git a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js
index 480c88a539..c2017f8ff3 100644
--- a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js
+++ b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js
@@ -1,6 +1,6 @@
Engine.RegisterInterface("GarrisonHolder");
-// Message of the form { } (use GetEntities if you want the current details),
+// Message of the form { "added":[], "removed":[] } (and use GetEntities if you want the current details),
// sent to the current entity whenever the garrisoned units change.
Engine.RegisterMessageType("GarrisonedUnitsChanged");
diff --git a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
index 60ae42e0be..3fd0fc3125 100644
--- a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
+++ b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
@@ -206,7 +206,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
entityLimits: {"Foo": 10},
entityCounts: {"Foo": 5},
entityLimitChangers: {"Foo": {}},
- techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -235,7 +234,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
entityLimits: {"Bar": 20},
entityCounts: {"Bar": 0},
entityLimitChangers: {"Bar": {}},
- techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -271,7 +269,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
entityLimits: {"Foo": 10},
entityCounts: {"Foo": 5},
entityLimitChangers: {"Foo": {}},
- techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
@@ -316,7 +313,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
entityLimits: {"Bar": 20},
entityCounts: {"Bar": 0},
entityLimitChangers: {"Bar": {}},
- techModifications: {},
researchQueued: {},
researchStarted: {},
researchedTechs: {},
diff --git a/binaries/data/mods/public/simulation/helpers/Player.js b/binaries/data/mods/public/simulation/helpers/Player.js
index 6dc73b176d..b679178c76 100644
--- a/binaries/data/mods/public/simulation/helpers/Player.js
+++ b/binaries/data/mods/public/simulation/helpers/Player.js
@@ -54,6 +54,11 @@ function LoadPlayerSettings(settings, newPlayers)
// Add player to player manager
cmpPlayerManager.AddPlayer(entID);
+
+ // Properly autoresearch techs on init.
+ var cmpTechManager = Engine.QueryInterface(entID, IID_TechnologyManager);
+ if (cmpTechManager !== undefined)
+ cmpTechManager.UpdateAutoResearch();
}
}