Actually remove trailing whitespace for non-header files as well.
This was SVN commit r18989.
This commit is contained in:
parent
944ba16eb4
commit
6149dd3841
@ -11,4 +11,4 @@
|
||||
<Path>audio/interface/ui</Path>
|
||||
<Sound>ui_button_click.ogg</Sound>
|
||||
<Sound>ui_button_longclick.ogg</Sound>
|
||||
</SoundGroup>
|
||||
</SoundGroup>
|
||||
|
@ -116,11 +116,11 @@ function translateMessageObject(object)
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates any string value in the specified JavaScript object
|
||||
* Translates any string value in the specified JavaScript object
|
||||
* that is associated with a key included in the specified keys array.
|
||||
*
|
||||
* it accepts an object in the form of
|
||||
*
|
||||
*
|
||||
* {
|
||||
* translatedString1: "my first message",
|
||||
* unTranslatedString1: "some English string",
|
||||
@ -139,7 +139,7 @@ function translateMessageObject(object)
|
||||
* }
|
||||
*
|
||||
* Together with a keys list to translate the strings and objects
|
||||
* ["translatedString1", "translatedString2", "translatedObject1",
|
||||
* ["translatedString1", "translatedString2", "translatedObject1",
|
||||
* "translatedObject2"]
|
||||
*
|
||||
* The result will be (f.e. in Dutch)
|
||||
@ -151,11 +151,11 @@ function translateMessageObject(object)
|
||||
* unTranslatedString2: "some English string"
|
||||
* },
|
||||
* translatedObject1: "mijn derde bericht",
|
||||
* translatedObject2: "lijst, van, teksten",
|
||||
* translatedObject2: "lijst, van, teksten",
|
||||
* }
|
||||
*
|
||||
* So you see that the keys array can also contain lower-level keys,
|
||||
* And that you can include objects in the keys array to translate
|
||||
* And that you can include objects in the keys array to translate
|
||||
* them with a context, or to join a list of translations.
|
||||
*
|
||||
* Also, the keys array may be an object where properties are keys to translate
|
||||
|
@ -223,4 +223,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
})
|
||||
}
|
||||
}
|
||||
})(typeof window === "undefined" ? this : window);
|
||||
})(typeof window === "undefined" ? this : window);
|
||||
|
@ -7,10 +7,10 @@
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
|
@ -5,7 +5,7 @@
|
||||
<ConeGain>1</ConeGain>
|
||||
<Looping>0</Looping>
|
||||
<RandOrder>1</RandOrder>
|
||||
<Distanceless>1</Distanceless>
|
||||
<Distanceless>1</Distanceless>
|
||||
<RandGain>1</RandGain>
|
||||
<GainUpper>0.8</GainUpper>
|
||||
<GainLower>0.7</GainLower>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<ConeGain>1</ConeGain>
|
||||
<Looping>0</Looping>
|
||||
<RandOrder>1</RandOrder>
|
||||
<Distanceless>1</Distanceless>
|
||||
<Distanceless>1</Distanceless>
|
||||
<RandGain>1</RandGain>
|
||||
<GainUpper>0.8</GainUpper>
|
||||
<GainLower>0.7</GainLower>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<ConeGain>1</ConeGain>
|
||||
<Looping>0</Looping>
|
||||
<RandOrder>1</RandOrder>
|
||||
<Distanceless>1</Distanceless>
|
||||
<Distanceless>1</Distanceless>
|
||||
<RandGain>1</RandGain>
|
||||
<GainUpper>0.8</GainUpper>
|
||||
<GainLower>0.7</GainLower>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Safe, platform consistent implementations of some Math functions
|
||||
*
|
||||
*
|
||||
* These functions are implemented in JS to avoid observed differences
|
||||
* between results of different floating point libraries, see
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=531915
|
||||
@ -27,11 +27,11 @@ Math.cos = function(a)
|
||||
|
||||
// if a > pi/2 send a to pi-a, otherwise just send a to -a which has no effect
|
||||
// Using the symmetry cos(x) = -cos(pi-x) to bring a to the 0 to pi/2 range.
|
||||
a = b*Math.PI - a;
|
||||
a = b*Math.PI - a;
|
||||
|
||||
var c = 1 - 2*b; // sign of the output
|
||||
|
||||
// Taylor expansion about 0 with a correction term in the quadratic to make cos(pi/2)=0
|
||||
// Taylor expansion about 0 with a correction term in the quadratic to make cos(pi/2)=0
|
||||
return c * (1 - a*a*(0.5000000025619951 - a*a*(1/24 - a*a*(1/720 - a*a*(1/40320 - a*a*(1/3628800 - a*a/479001600))))));
|
||||
};
|
||||
|
||||
@ -74,7 +74,7 @@ Math.atan = function(a)
|
||||
tanPiBy6Shift = Math.PI/6;
|
||||
a = (a - tanPiBy6) / (1 + tanPiBy6*a);
|
||||
}
|
||||
// Now a will be in the range [-tan(pi/12), tan(pi/12)]
|
||||
// Now a will be in the range [-tan(pi/12), tan(pi/12)]
|
||||
|
||||
// Use the taylor expansion around 0 with a correction to the linear term to match the pi/12 boundary
|
||||
// atan(x) = x - x^3/3 + x^5/5 - ...
|
||||
@ -198,7 +198,7 @@ Math.exp = function(x)
|
||||
for (var i = 22; i > 0; i--)
|
||||
dPart = 1+x*dPart/i;
|
||||
|
||||
// total precision ~=~ 17 decimal digits
|
||||
// total precision ~=~ 17 decimal digits
|
||||
return iPart*dPart;
|
||||
};
|
||||
|
||||
@ -222,7 +222,7 @@ Math.log = function(x)
|
||||
// start with calculating the binary logarithm
|
||||
// based on http://en.wikipedia.org/wiki/Binary_logarithm#Real_number
|
||||
|
||||
// calculate to 50 fractional bits -> error ~=~ 10^-16
|
||||
// calculate to 50 fractional bits -> error ~=~ 10^-16
|
||||
var precisionBits = 50;
|
||||
|
||||
// calculate integer log, rounded down
|
||||
|
@ -4,7 +4,7 @@
|
||||
* any global state, but each context should do its own caching as needed.
|
||||
* Also it cannot directly access the simulation and requires data passed to it.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Returns modified property value modified by the applicable tech
|
||||
* modifications.
|
||||
|
@ -133,7 +133,7 @@ Vector2D.prototype.distanceTo = function(v)
|
||||
|
||||
// Static 2D functions
|
||||
//
|
||||
// Static functions that return a new vector object.
|
||||
// Static functions that return a new vector object.
|
||||
// Note that object creation is slow in JS, so use them only when necessary
|
||||
|
||||
Vector2D.clone = function(v)
|
||||
@ -243,7 +243,7 @@ Vector3D.prototype.normalize = function()
|
||||
var mag = this.length();
|
||||
if (!mag)
|
||||
return this;
|
||||
|
||||
|
||||
return this.div(mag);
|
||||
};
|
||||
|
||||
@ -308,7 +308,7 @@ Vector3D.prototype.horizDistanceTo = function(v)
|
||||
|
||||
// Static 3D functions
|
||||
//
|
||||
// Static functions that return a new vector object.
|
||||
// Static functions that return a new vector object.
|
||||
// Note that object creation is slow in JS, so use them only when really necessary
|
||||
|
||||
Vector3D.clone = function(v)
|
||||
|
BIN
binaries/data/mods/public/maps/scenarios/Eire and Albion.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Eire and Albion.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Fast Oasis.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Fast Oasis.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Fractal).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Fractal).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Greece).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Greece).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Greece-Small).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Height Map Import - Demo (Greece-Small).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Introductory Tutorial.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Introductory Tutorial.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Polynesia.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Polynesia.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Saharan Oases.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Saharan Oases.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Sahel.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Sahel.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Sandbox - Mauryans.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Sandbox - Mauryans.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Sandbox - Romans.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Sandbox - Romans.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/reservoir.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/reservoir.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Acropolis Bay (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Acropolis Bay (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Alpine_Valleys_(2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Alpine_Valleys_(2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Bactria (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Bactria (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Belgian Bog (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Belgian Bog (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Caspian Sea (2v2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Caspian Sea (2v2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Corinthian Isthmus (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Corinthian Isthmus (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Death Canyon (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Death Canyon (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Deccan Plateau (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Deccan Plateau (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Dueling Cliffs (3v3).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Dueling Cliffs (3v3).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Gambia River (3).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Gambia River (3).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Golden Oasis (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Golden Oasis (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Libyan Oases (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Libyan Oases (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Lorraine Plain (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Lorraine Plain (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Neareastern Badlands (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Neareastern Badlands (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Neareastern Badlands (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Neareastern Badlands (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Northern Island (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Northern Island (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Persian Highlands (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Persian Highlands (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Punbjab (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Punbjab (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Saharan Oases (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Saharan Oases (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Sahel (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Sahel (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Savanna River.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Savanna River.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Sicilia (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Sicilia (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Siwa Oasis (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Siwa Oasis (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Syria (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Syria (2).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Team Oasis - 2v2.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Team Oasis - 2v2.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Watering Holes (4).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Watering Holes (4).xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/skirmishes/Zagros Mountains (2).xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/skirmishes/Zagros Mountains (2).xml
(Stored with Git LFS)
Binary file not shown.
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="arb">
|
||||
|
||||
<!-- This shader is used for rendering overlay lines (e.g. territory boundaries), and also for
|
||||
<!-- This shader is used for rendering overlay lines (e.g. territory boundaries), and also for
|
||||
rendering the unit selection ring quad overlays, since they are almost identical. The only
|
||||
difference is that in unit selection ring mode, the uniform objectColor is ignored and instead
|
||||
replaced by a color stream from the vertices. The USE_OBJECTCOLOR define is used to switch
|
||||
between either mode. -->
|
||||
|
||||
|
||||
<vertex file="arb/overlayline.vp">
|
||||
<stream name="pos"/>
|
||||
<stream name="uv0"/>
|
||||
|
@ -111,7 +111,7 @@
|
||||
</technique>
|
||||
|
||||
|
||||
|
||||
|
||||
<technique>
|
||||
<require context="ALPHABLEND_PASS_BLEND"/>
|
||||
<require shaders="arb"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/sky"/>
|
||||
|
@ -8,38 +8,38 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byClass: function(cls){
|
||||
return {"func" : function(ent){
|
||||
return ent.hasClass(cls);
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byClassesAnd: function(clsList){
|
||||
return {"func" : function(ent){
|
||||
let ret = true;
|
||||
for (let cls of clsList)
|
||||
ret = ret && ent.hasClass(cls);
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byClassesOr: function(clsList){
|
||||
return {"func" : function(ent){
|
||||
let ret = false;
|
||||
for (let cls of clsList)
|
||||
ret = ret || ent.hasClass(cls);
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
byMetadata: function(player, key, value){
|
||||
return {"func" : function(ent){
|
||||
return ent.getMetadata(player, key) == value;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['metadata.' + key]};
|
||||
},
|
||||
|
||||
@ -50,7 +50,7 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byHasMetadata: function(player, key){
|
||||
return {"func" : function(ent){
|
||||
return ent.getMetadata(player, key) !== undefined;
|
||||
@ -61,45 +61,45 @@ m.Filters = {
|
||||
and: function(filter1, filter2){
|
||||
return {"func": function(ent){
|
||||
return filter1.func(ent) && filter2.func(ent);
|
||||
},
|
||||
},
|
||||
"dynamicProperties": filter1.dynamicProperties.concat(filter2.dynamicProperties)};
|
||||
},
|
||||
|
||||
|
||||
or: function(filter1, filter2){
|
||||
return {"func" : function(ent){
|
||||
return filter1.func(ent) || filter2.func(ent);
|
||||
},
|
||||
},
|
||||
"dynamicProperties": filter1.dynamicProperties.concat(filter2.dynamicProperties)};
|
||||
},
|
||||
|
||||
|
||||
not: function(filter){
|
||||
return {"func": function(ent){
|
||||
return !filter.func(ent);
|
||||
},
|
||||
"dynamicProperties": filter.dynamicProperties};
|
||||
},
|
||||
|
||||
|
||||
byOwner: function(owner){
|
||||
return {"func" : function(ent){
|
||||
return ent.owner() === owner;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['owner']};
|
||||
},
|
||||
|
||||
|
||||
byNotOwner: function(owner){
|
||||
return {"func" : function(ent){
|
||||
return ent.owner() !== owner;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['owner']};
|
||||
},
|
||||
|
||||
|
||||
byOwners: function(owners){
|
||||
return {"func" : function(ent){
|
||||
for (let owner of owners)
|
||||
if (ent.owner() === owner)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['owner']};
|
||||
},
|
||||
|
||||
@ -112,7 +112,7 @@ m.Filters = {
|
||||
byTrainingQueue: function(){
|
||||
return {"func" : function(ent){
|
||||
return ent.trainingQueue();
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['trainingQueue']};
|
||||
},
|
||||
byResearchAvailable: function(civ){
|
||||
@ -127,14 +127,14 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": ['unitAIOrderData']};
|
||||
},
|
||||
|
||||
|
||||
byCanAttack: function(saidClass){
|
||||
return {"func" : function(ent){
|
||||
return ent.canAttackClass(saidClass);
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
isGarrisoned: function(){
|
||||
return {"func" : function(ent){
|
||||
return ent.position() === undefined;
|
||||
@ -145,17 +145,17 @@ m.Filters = {
|
||||
isSoldier: function(){
|
||||
return {"func" : function(ent){
|
||||
return Filters.byClassesOr(["CitizenSoldier", "Super"])(ent);
|
||||
},
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
isIdle: function(){
|
||||
return {"func" : function(ent){
|
||||
return ent.isIdle();
|
||||
},
|
||||
},
|
||||
"dynamicProperties": ['idle']};
|
||||
},
|
||||
|
||||
|
||||
isFoundation: function(){
|
||||
return {"func": function(ent){
|
||||
return ent.foundationProgress() !== undefined;
|
||||
@ -185,8 +185,8 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": ['position']};
|
||||
},
|
||||
|
||||
// Distance filter with no auto updating, use with care
|
||||
|
||||
// Distance filter with no auto updating, use with care
|
||||
byStaticDistance: function(startPoint, dist){
|
||||
return {"func": function(ent){
|
||||
if (!ent.position())
|
||||
@ -195,7 +195,7 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byTerritory: function(Map, territoryIndex){
|
||||
return {"func": function(ent){
|
||||
return Map.point(ent.position()) == territoryIndex;
|
||||
@ -209,7 +209,7 @@ m.Filters = {
|
||||
},
|
||||
"dynamicProperties": []};
|
||||
},
|
||||
|
||||
|
||||
byResource: function(resourceType){
|
||||
return {"func" : function(ent){
|
||||
if (!ent.resourceSupplyMax())
|
||||
@ -224,7 +224,7 @@ m.Filters = {
|
||||
return false;
|
||||
|
||||
// Don't go for floating treasures since we won't be able to reach them and it kills the pathfinder.
|
||||
if (ent.templateName() == "other/special_treasure_shipwreck_debris" ||
|
||||
if (ent.templateName() == "other/special_treasure_shipwreck_debris" ||
|
||||
ent.templateName() == "other/special_treasure_shipwreck" )
|
||||
return false;
|
||||
|
||||
@ -245,7 +245,7 @@ m.Filters = {
|
||||
// Skip targets that are too hard to hunt
|
||||
if (!ent.isHuntable())
|
||||
return false;
|
||||
// And don't go for the fish! TODO: better accessibility checks
|
||||
// And don't go for the fish! TODO: better accessibility checks
|
||||
if (ent.hasClass("SeaCreature"))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -85,7 +85,7 @@ m.GameState.prototype.updatingGlobalCollection = function(id, filter, collection
|
||||
|
||||
let newCollection = collection !== undefined ? collection.filter(filter) : this.entities.filter(filter);
|
||||
newCollection.registerUpdates();
|
||||
this.EntCollecNames.set(id, newCollection);
|
||||
this.EntCollecNames.set(id, newCollection);
|
||||
return newCollection;
|
||||
};
|
||||
|
||||
@ -212,11 +212,11 @@ m.GameState.prototype.canResearch = function(techTemplateName, noRequirementChec
|
||||
|
||||
if (noRequirementCheck === true)
|
||||
return true;
|
||||
|
||||
|
||||
// not already researched, check if we can.
|
||||
// basically a copy of the function in technologyManager since we can't use it.
|
||||
// Checks the requirements for a technology to see if it can be researched at the current time
|
||||
|
||||
|
||||
// The technology which this technology supersedes is required
|
||||
if (template.supersedes() && !this.playerData.researchedTechs[template.supersedes()])
|
||||
return false;
|
||||
@ -243,7 +243,7 @@ m.GameState.prototype.checkTechRequirements = function(reqs)
|
||||
// If there are no requirements then all requirements are met
|
||||
if (!reqs)
|
||||
return true;
|
||||
|
||||
|
||||
if (reqs.all)
|
||||
return reqs.all.every(r => this.checkTechRequirements(r));
|
||||
if (reqs.any)
|
||||
@ -255,12 +255,12 @@ m.GameState.prototype.checkTechRequirements = function(reqs)
|
||||
if (reqs.tech)
|
||||
return this.playerData.researchedTechs[reqs.tech] !== undefined && this.playerData.researchedTechs[reqs.tech];
|
||||
if (reqs.class && reqs.numberOfTypes)
|
||||
return this.playerData.typeCountsByClass[reqs.class] &&
|
||||
return this.playerData.typeCountsByClass[reqs.class] &&
|
||||
Object.keys(this.playerData.typeCountsByClass[reqs.class]).length >= reqs.numberOfTypes;
|
||||
if (reqs.class && reqs.number)
|
||||
return this.playerData.classCounts[reqs.class] &&
|
||||
this.playerData.classCounts[reqs.class] >= reqs.number;
|
||||
|
||||
|
||||
// The technologies requirements are not a recognised format
|
||||
error("Bad requirements " + uneval(reqs));
|
||||
return false;
|
||||
@ -404,7 +404,7 @@ m.GameState.prototype.isEntityEnemy = function(ent)
|
||||
return false;
|
||||
return this.playerData.isEnemy[ent.owner()];
|
||||
};
|
||||
|
||||
|
||||
m.GameState.prototype.isEntityOwn = function(ent)
|
||||
{
|
||||
if (!ent)
|
||||
@ -681,7 +681,7 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
|
||||
let template = this.getTemplate(trainable);
|
||||
if (!template || !template.available(this))
|
||||
continue;
|
||||
|
||||
|
||||
let okay = true;
|
||||
for (let clas of classes)
|
||||
{
|
||||
@ -718,7 +718,7 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
|
||||
* If there are pairs, both techs are returned.
|
||||
*/
|
||||
m.GameState.prototype.findAvailableTech = function()
|
||||
{
|
||||
{
|
||||
let allResearchable = [];
|
||||
let civ = this.playerData.civ;
|
||||
this.getOwnEntities().forEach(function(ent) {
|
||||
@ -754,7 +754,7 @@ m.GameState.prototype.findAvailableTech = function()
|
||||
* Return true if we have a building able to train that template
|
||||
*/
|
||||
m.GameState.prototype.hasTrainer = function(template)
|
||||
{
|
||||
{
|
||||
let civ = this.playerData.civ;
|
||||
for (let ent of this.getOwnTrainingFacilities().values())
|
||||
{
|
||||
@ -769,7 +769,7 @@ m.GameState.prototype.hasTrainer = function(template)
|
||||
* Find buildings able to train that template.
|
||||
*/
|
||||
m.GameState.prototype.findTrainers = function(template)
|
||||
{
|
||||
{
|
||||
let civ = this.playerData.civ;
|
||||
return this.getOwnTrainingFacilities().filter(function(ent) {
|
||||
let trainable = ent.trainableEntities(civ);
|
||||
|
@ -65,10 +65,10 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type = "linea
|
||||
// code duplicating for speed
|
||||
if (type === "linear")
|
||||
{
|
||||
let str = strength / maxDist;
|
||||
let str = strength / maxDist;
|
||||
for (let y = y0; y < y1; ++y)
|
||||
{
|
||||
let dy = y - cy;
|
||||
let dy = y - cy;
|
||||
for (let x = x0; x < x1; ++x)
|
||||
{
|
||||
let dx = x - cx;
|
||||
@ -91,7 +91,7 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type = "linea
|
||||
let str = strength / maxDist2;
|
||||
for (let y = y0; y < y1; ++y)
|
||||
{
|
||||
let dy = y - cy;
|
||||
let dy = y - cy;
|
||||
for (let x = x0; x < x1; ++x)
|
||||
{
|
||||
let dx = x - cx;
|
||||
@ -99,7 +99,7 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type = "linea
|
||||
if (r2 >= maxDist2)
|
||||
continue;
|
||||
let quant = str * (maxDist2 - r2);
|
||||
let w = x + y * this.width;
|
||||
let w = x + y * this.width;
|
||||
if (this.map[w] + quant < 0)
|
||||
this.map[w] = 0;
|
||||
else if (this.map[w] + quant > this.maxVal)
|
||||
@ -120,7 +120,7 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type = "linea
|
||||
let r2 = dx*dx + dy*dy;
|
||||
if (r2 >= maxDist2)
|
||||
continue;
|
||||
let w = x + y * this.width;
|
||||
let w = x + y * this.width;
|
||||
if (this.map[w] + strength < 0)
|
||||
this.map[w] = 0;
|
||||
else if (this.map[w] + strength > this.maxVal)
|
||||
|
@ -81,7 +81,7 @@ m.g_ResourceForbiddenComponents = {
|
||||
};
|
||||
|
||||
m.SharedScript.prototype.GetTemplate = function(name)
|
||||
{
|
||||
{
|
||||
if (this._templates[name])
|
||||
return this._templates[name];
|
||||
|
||||
@ -92,24 +92,24 @@ m.SharedScript.prototype.GetTemplate = function(name)
|
||||
if (name.indexOf("foundation|") !== -1)
|
||||
{
|
||||
let base = this.GetTemplate(name.substr(11));
|
||||
|
||||
|
||||
let foundation = {};
|
||||
for (let key in base)
|
||||
if (!m.g_FoundationForbiddenComponents[key])
|
||||
foundation[key] = base[key];
|
||||
|
||||
|
||||
this._derivedTemplates[name] = foundation;
|
||||
return foundation;
|
||||
}
|
||||
else if (name.indexOf("resource|") !== -1)
|
||||
{
|
||||
let base = this.GetTemplate(name.substr(9));
|
||||
|
||||
|
||||
let resource = {};
|
||||
for (let key in base)
|
||||
if (!m.g_ResourceForbiddenComponents[key])
|
||||
resource[key] = base[key];
|
||||
|
||||
|
||||
this._derivedTemplates[name] = resource;
|
||||
return resource;
|
||||
}
|
||||
@ -234,13 +234,13 @@ m.SharedScript.prototype.onUpdate = function(state)
|
||||
this.passabilityMap.cellSize = this.mapSize / this.passabilityMap.width;
|
||||
this.territoryMap = state.territoryMap;
|
||||
this.territoryMap.cellSize = this.mapSize / this.territoryMap.width;
|
||||
|
||||
|
||||
for (let i in this.gameState)
|
||||
this.gameState[i].update(this);
|
||||
|
||||
// TODO: merge this with "ApplyEntitiesDelta" since after all they do the same.
|
||||
this.updateResourceMaps(this.events);
|
||||
|
||||
|
||||
Engine.ProfileStop();
|
||||
};
|
||||
|
||||
@ -249,7 +249,7 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
|
||||
Engine.ProfileStart("Shared ApplyEntitiesDelta");
|
||||
|
||||
let foundationFinished = {};
|
||||
|
||||
|
||||
// by order of updating:
|
||||
// we "Destroy" last because we want to be able to switch Metadata first.
|
||||
|
||||
@ -263,7 +263,7 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
|
||||
let entity = new m.Entity(this, state.entities[evt.entity]);
|
||||
this._entities.set(evt.entity, entity);
|
||||
this.entities.addEnt(entity);
|
||||
|
||||
|
||||
// Update all the entity collections since the create operation affects static properties as well as dynamic
|
||||
for (let entCol of this._entityCollections.values())
|
||||
entCol.updateEnt(entity);
|
||||
@ -305,7 +305,7 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
|
||||
for (let key in evt.metadata)
|
||||
this.setMetadata(evt.owner, this._entities.get(evt.id), key, evt.metadata[key]);
|
||||
}
|
||||
|
||||
|
||||
let DestroyEvents = state.events.Destroy;
|
||||
for (let i = 0; i < DestroyEvents.length; ++i)
|
||||
{
|
||||
@ -447,7 +447,7 @@ m.SharedScript.prototype.deleteMetadata = function(player, ent, key)
|
||||
return true;
|
||||
metadata[key] = undefined;
|
||||
delete metadata[key];
|
||||
this.updateEntityCollections('metadata', ent);
|
||||
this.updateEntityCollections('metadata', ent);
|
||||
this.updateEntityCollections('metadata.' + key, ent);
|
||||
return true;
|
||||
};
|
||||
|
@ -136,7 +136,7 @@ m.Technology.prototype.isAffected = function(classes)
|
||||
{
|
||||
if (!this._template.affects)
|
||||
return false;
|
||||
|
||||
|
||||
for (let affect of this._template.affects)
|
||||
{
|
||||
let reqClasses = affect.split(" ");
|
||||
|
@ -3,7 +3,7 @@ var API3 = function(m)
|
||||
|
||||
/**
|
||||
* TerrainAnalysis, inheriting from the Map Component.
|
||||
*
|
||||
*
|
||||
* This creates a suitable passability map.
|
||||
* This is part of the Shared Script, and thus should only be used for things that are non-player specific.
|
||||
* This.map is a map of the world, where particular stuffs are pointed with a value
|
||||
@ -36,12 +36,12 @@ m.TerrainAnalysis.prototype.init = function(sharedScript, rawState)
|
||||
201 is shallow water (passable by land units and water units)
|
||||
255 is land (or extremely shallow water where ships can't go).
|
||||
*/
|
||||
|
||||
|
||||
for (let i = 0; i < passabilityMap.data.length; ++i)
|
||||
{
|
||||
// If impassable for land units, set to 0, else to 255.
|
||||
obstructionTiles[i] = (passabilityMap.data[i] & obstructionMaskLand) ? 0 : 255;
|
||||
|
||||
|
||||
if (!(passabilityMap.data[i] & obstructionMaskWater) && obstructionTiles[i] === 0)
|
||||
obstructionTiles[i] = 200; // if navigable and not walkable (ie basic water), set to 200.
|
||||
else if (!(passabilityMap.data[i] & obstructionMaskWater) && obstructionTiles[i] === 255)
|
||||
@ -53,14 +53,14 @@ m.TerrainAnalysis.prototype.init = function(sharedScript, rawState)
|
||||
|
||||
/**
|
||||
* Accessibility inherits from TerrainAnalysis
|
||||
*
|
||||
*
|
||||
* This can easily and efficiently determine if any two points are connected.
|
||||
* it can also determine if any point is "probably" reachable, assuming the unit can get close enough
|
||||
* for optimizations it's called after the TerrainAnalyser has finished initializing his map
|
||||
* so this can use the land regions already.
|
||||
*/
|
||||
m.Accessibility = function()
|
||||
{
|
||||
{
|
||||
};
|
||||
|
||||
m.copyPrototype(m.Accessibility, m.TerrainAnalysis);
|
||||
@ -76,12 +76,12 @@ m.Accessibility.prototype.init = function(rawState, terrainAnalyser)
|
||||
this.regionType = []; // "inaccessible", "land" or "water";
|
||||
// ID of the region associated with an array of region IDs.
|
||||
this.regionLinks = [];
|
||||
|
||||
|
||||
// initialized to 0, it's more optimized to start at 1 (I'm checking that if it's not 0, then it's already aprt of a region, don't touch);
|
||||
// However I actually store all unpassable as region 1 (because if I don't, on some maps the toal nb of region is over 256, and it crashes as the mapis 8bit.)
|
||||
// So start at 2.
|
||||
this.regionID = 2;
|
||||
|
||||
|
||||
for (let i = 0; i < this.landPassMap.length; ++i)
|
||||
{
|
||||
if (this.map[i] !== 0)
|
||||
@ -97,7 +97,7 @@ m.Accessibility.prototype.init = function(rawState, terrainAnalyser)
|
||||
this.floodFill(i,1,true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// calculating region links. Regions only touching diagonaly are not linked.
|
||||
// since we're checking all of them, we'll check from the top left to the bottom right
|
||||
let w = this.width;
|
||||
@ -135,7 +135,7 @@ m.Accessibility.prototype.init = function(rawState, terrainAnalyser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Engine.DumpImage("LandPassMap.png", this.landPassMap, this.width, this.height, 255);
|
||||
//Engine.DumpImage("NavalPassMap.png", this.navalPassMap, this.width, this.height, 255);
|
||||
};
|
||||
@ -276,7 +276,7 @@ m.Accessibility.prototype.floodFill = function(startIndex, value, onWater)
|
||||
this.landPassMap[startIndex] = 1; // impassable for land
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// here we'll be able to start.
|
||||
for (let i = this.regionSize.length; i <= value; ++i)
|
||||
{
|
||||
@ -292,7 +292,7 @@ m.Accessibility.prototype.floodFill = function(startIndex, value, onWater)
|
||||
let IndexArray = [startIndex];
|
||||
let newIndex;
|
||||
while(IndexArray.length)
|
||||
{
|
||||
{
|
||||
newIndex = IndexArray.pop();
|
||||
|
||||
y = 0;
|
||||
@ -317,7 +317,7 @@ m.Accessibility.prototype.floodFill = function(startIndex, value, onWater)
|
||||
let index;
|
||||
do {
|
||||
index = newIndex + w*y;
|
||||
|
||||
|
||||
if (floodFor === "land" && this.landPassMap[index] === 0 && this.map[index] !== 0 && this.map[index] !== 200)
|
||||
{
|
||||
this.landPassMap[index] = value;
|
||||
@ -330,7 +330,7 @@ m.Accessibility.prototype.floodFill = function(startIndex, value, onWater)
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
|
||||
if (index%w > 0)
|
||||
{
|
||||
if (floodFor === "land" && this.landPassMap[index -1] === 0 && this.map[index -1] !== 0 && this.map[index -1] !== 200)
|
||||
|
@ -97,7 +97,7 @@ m.getMapIndices = function(i, map1, map2)
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the list of points of map2 contained inside the cell i of map1
|
||||
* Returns the list of points of map2 contained inside the cell i of map1
|
||||
* map1.cellSize must be a multiple of map2.cellSize
|
||||
*/
|
||||
m.getMapPoints = function(i, map1, map2)
|
||||
|
@ -259,7 +259,7 @@ m.Army.prototype.isCapturing = function (gameState)
|
||||
return false;
|
||||
let ent = gameState.getEntityById(this.foeEntities[0]);
|
||||
return ent && ent.hasClass("Structure");
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* this one is "undefined entity" proof because it's called at odd times.
|
||||
@ -305,7 +305,7 @@ m.Army.prototype.merge = function (gameState, otherArmy)
|
||||
}
|
||||
for (let i in otherArmy.assignedTo)
|
||||
this.assignedTo[i] = otherArmy.assignedTo[i];
|
||||
|
||||
|
||||
for (let id of otherArmy.foeEntities)
|
||||
this.addFoe(gameState, id, true);
|
||||
// TODO: reassign those ?
|
||||
@ -314,7 +314,7 @@ m.Army.prototype.merge = function (gameState, otherArmy)
|
||||
|
||||
this.recalculatePosition(gameState, true);
|
||||
this.recalculateStrengths(gameState);
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -395,7 +395,7 @@ m.Army.prototype.onUpdate = function (gameState)
|
||||
let breakaways = [];
|
||||
// TODO: assign unassigned defenders, cleanup of a few things.
|
||||
// perhaps occasional strength recomputation
|
||||
|
||||
|
||||
// occasional update or breakaways, positions…
|
||||
if (gameState.ai.elapsedTime - this.positionLastUpdate > 5)
|
||||
{
|
||||
|
@ -362,7 +362,7 @@ m.AttackManager.prototype.getEnemyPlayer = function(gameState, attack)
|
||||
let veto = {};
|
||||
for (let i in this.defeated)
|
||||
veto[i] = true;
|
||||
// No rush if enemy too well defended (i.e. iberians)
|
||||
// No rush if enemy too well defended (i.e. iberians)
|
||||
if (attack.type === "Rush")
|
||||
{
|
||||
for (let i = 1; i < gameState.sharedScript.playersData.length; ++i)
|
||||
|
@ -24,7 +24,7 @@ m.BaseManager = function(gameState, Config)
|
||||
this.accessIndex = undefined;
|
||||
|
||||
// Maximum distance (from any dropsite) to look for resources
|
||||
// 3 areas are used: from 0 to max/4, from max/4 to max/2 and from max/2 to max
|
||||
// 3 areas are used: from 0 to max/4, from max/4 to max/2 and from max/2 to max
|
||||
this.maxDistResourceSquare = 360*360;
|
||||
|
||||
this.constructing = false;
|
||||
@ -45,7 +45,7 @@ m.BaseManager.prototype.init = function(gameState, state)
|
||||
// entitycollections
|
||||
this.units = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "base", this.ID));
|
||||
this.workers = this.units.filter(API3.Filters.byMetadata(PlayerID, "role", "worker"));
|
||||
this.buildings = gameState.getOwnStructures().filter(API3.Filters.byMetadata(PlayerID, "base", this.ID));
|
||||
this.buildings = gameState.getOwnStructures().filter(API3.Filters.byMetadata(PlayerID, "base", this.ID));
|
||||
|
||||
this.units.registerUpdates();
|
||||
this.workers.registerUpdates();
|
||||
@ -134,7 +134,7 @@ m.BaseManager.prototype.checkEvents = function (gameState, events, queues)
|
||||
continue;
|
||||
if (evt.newentity == evt.entity) // repaired building
|
||||
continue;
|
||||
|
||||
|
||||
if (ent.getMetadata(PlayerID, "base") == this.ID)
|
||||
if (ent.resourceDropsiteTypes() && !ent.hasClass("Elephant"))
|
||||
this.assignResourceToDropsite(gameState, ent);
|
||||
@ -238,7 +238,7 @@ m.BaseManager.prototype.assignResourceToDropsite = function (gameState, dropsite
|
||||
if (dist < maxDistResourceSquare)
|
||||
{
|
||||
if (dist < maxDistResourceSquare/16) // distmax/4
|
||||
nearby.push({ "dropsite": dropsiteId, "id": supply.id(), "ent": supply, "dist": dist });
|
||||
nearby.push({ "dropsite": dropsiteId, "id": supply.id(), "ent": supply, "dist": dist });
|
||||
else if (dist < maxDistResourceSquare/4) // distmax/2
|
||||
medium.push({ "dropsite": dropsiteId, "id": supply.id(), "ent": supply, "dist": dist });
|
||||
else
|
||||
@ -253,13 +253,13 @@ m.BaseManager.prototype.assignResourceToDropsite = function (gameState, dropsite
|
||||
/* let debug = false;
|
||||
if (debug)
|
||||
{
|
||||
faraway.forEach(function(res){
|
||||
faraway.forEach(function(res){
|
||||
Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [res.ent.id()], "rgb": [2,0,0]});
|
||||
});
|
||||
medium.forEach(function(res){
|
||||
medium.forEach(function(res){
|
||||
Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [res.ent.id()], "rgb": [0,2,0]});
|
||||
});
|
||||
nearby.forEach(function(res){
|
||||
nearby.forEach(function(res){
|
||||
Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [res.ent.id()], "rgb": [0,0,2]});
|
||||
});
|
||||
} */
|
||||
@ -304,11 +304,11 @@ m.BaseManager.prototype.removeDropsite = function (gameState, ent)
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the position of the best place to build a new dropsite for the specified resource
|
||||
* Returns the position of the best place to build a new dropsite for the specified resource
|
||||
*/
|
||||
m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource)
|
||||
{
|
||||
|
||||
|
||||
let template = gameState.getTemplate(gameState.applyCiv("structures/{civ}_storehouse"));
|
||||
let halfSize = 0;
|
||||
if (template.get("Footprint/Square"))
|
||||
@ -521,7 +521,7 @@ m.BaseManager.prototype.checkResourceLevels = function (gameState, queues)
|
||||
this.gatherers[type].lost = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/** Adds the estimated gather rates from this base to the currentRates */
|
||||
@ -537,7 +537,7 @@ m.BaseManager.prototype.getGatherRates = function(gameState, currentRates)
|
||||
|
||||
this.gatherersByType(gameState, res).forEach(function (ent) {
|
||||
if (ent.isIdle() || !ent.position())
|
||||
return;
|
||||
return;
|
||||
let gRate = ent.currentGatherRate();
|
||||
if (gRate)
|
||||
currentRates[res] += Math.log(1+gRate)/1.1;
|
||||
@ -600,7 +600,7 @@ m.BaseManager.prototype.setWorkersIdleByPriority = function(gameState)
|
||||
for (let i = mostNeeded.length-1; i > 0; --i)
|
||||
{
|
||||
let lessNeed = mostNeeded[i];
|
||||
for (let j = 0; j < i; ++j)
|
||||
for (let j = 0; j < i; ++j)
|
||||
{
|
||||
let moreNeed = mostNeeded[j];
|
||||
let lastFailed = gameState.ai.HQ.lastFailedGather[moreNeed.type];
|
||||
@ -616,7 +616,7 @@ m.BaseManager.prototype.setWorkersIdleByPriority = function(gameState)
|
||||
if (lessNeed.type === "food" && gatherers.filter(API3.Filters.byClass("CitizenSoldier")).hasEntities())
|
||||
only = "CitizenSoldier";
|
||||
else if ((lessNeed.type === "stone" || lessNeed.type === "metal") && moreNeed.type !== "stone" && moreNeed.type !== "metal" &&
|
||||
gatherers.filter(API3.Filters.byClass("Female")).hasEntities())
|
||||
gatherers.filter(API3.Filters.byClass("Female")).hasEntities())
|
||||
only = "Female";
|
||||
|
||||
gatherers.forEach( function (ent) {
|
||||
@ -743,11 +743,11 @@ m.BaseManager.prototype.pickBuilders = function(gameState, workers, number)
|
||||
|
||||
/**
|
||||
* If we have some foundations, and we don't have enough builder-workers,
|
||||
* try reassigning some other workers who are nearby
|
||||
* try reassigning some other workers who are nearby
|
||||
* AI tries to use builders sensibly, not completely stopping its econ.
|
||||
*/
|
||||
m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
|
||||
{
|
||||
{
|
||||
let foundations = this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(),API3.Filters.not(API3.Filters.byClass("Field")))).toEntityArray();
|
||||
|
||||
let damagedBuildings = this.buildings.filter(ent => ent.foundationProgress() === undefined && ent.needsRepair());
|
||||
@ -791,7 +791,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
|
||||
}
|
||||
}
|
||||
|
||||
let builderTot = builderWorkers.length - idleBuilderWorkers.length;
|
||||
let builderTot = builderWorkers.length - idleBuilderWorkers.length;
|
||||
|
||||
for (let target of foundations)
|
||||
{
|
||||
@ -868,7 +868,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
|
||||
coeffB *= 0.5 * (1 + Math.sqrt(coeffB)/5/time);
|
||||
else if (workerB.getMetadata(PlayerID, "gather-type") === "food")
|
||||
coeffB *= 3;
|
||||
return coeffA - coeffB;
|
||||
return coeffA - coeffB;
|
||||
});
|
||||
let current = 0;
|
||||
let nonBuilderTot = nonBuilderWorkers.length;
|
||||
@ -941,7 +941,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
|
||||
});
|
||||
let num = Math.min(nonBuilderWorkers.length, targetNB-assigned);
|
||||
let nearestNonBuilders = nonBuilderWorkers.filterNearest(target.position(), num);
|
||||
|
||||
|
||||
nearestNonBuilders.forEach(function(ent) {
|
||||
assigned++;
|
||||
builderTot++;
|
||||
|
@ -130,7 +130,7 @@ m.DefenseManager.prototype.isDangerous = function(gameState, entity)
|
||||
// TODO the 30 is to take roughly into account the structure size in following checks. Can be improved
|
||||
if (entity.attackTypes().indexOf("Ranged") !== -1)
|
||||
dist2Min = (entity.attackRange("Ranged").max + 30) * (entity.attackRange("Ranged").max + 30);
|
||||
|
||||
|
||||
for (let targetId of this.targetList)
|
||||
{
|
||||
let target = gameState.getEntityById(targetId);
|
||||
@ -187,7 +187,7 @@ m.DefenseManager.prototype.checkEnemyUnits = function(gameState)
|
||||
{
|
||||
if (!this.armies.length)
|
||||
{
|
||||
// check if we can recover capture points from any of our notdecaying structures
|
||||
// check if we can recover capture points from any of our notdecaying structures
|
||||
for (let ent of gameState.getOwnStructures().values())
|
||||
{
|
||||
if (ent.decaying())
|
||||
@ -356,7 +356,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState)
|
||||
{
|
||||
if (this.armies.length === 0)
|
||||
return;
|
||||
|
||||
|
||||
let armiesNeeding = [];
|
||||
// let's add defenders
|
||||
for (let army of this.armies)
|
||||
@ -364,7 +364,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState)
|
||||
let needsDef = army.needsDefenders(gameState);
|
||||
if (needsDef === false)
|
||||
continue;
|
||||
|
||||
|
||||
// Okay for now needsDef is the total needed strength.
|
||||
// we're dumb so we don't choose if we have a defender shortage.
|
||||
armiesNeeding.push( {"army": army, "need": needsDef} );
|
||||
@ -374,7 +374,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState)
|
||||
return;
|
||||
|
||||
// let's get our potential units
|
||||
let potentialDefenders = [];
|
||||
let potentialDefenders = [];
|
||||
gameState.getOwnUnits().forEach(function(ent) {
|
||||
if (!ent.position())
|
||||
return;
|
||||
@ -398,7 +398,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState)
|
||||
}
|
||||
potentialDefenders.push(ent.id());
|
||||
});
|
||||
|
||||
|
||||
for (let a = 0; a < armiesNeeding.length; ++a)
|
||||
armiesNeeding[a].army.recalculatePosition(gameState);
|
||||
|
||||
@ -566,7 +566,7 @@ m.DefenseManager.prototype.checkEvents = function(gameState, events)
|
||||
continue;
|
||||
}
|
||||
|
||||
// try to garrison any attacked range siege unit
|
||||
// try to garrison any attacked range siege unit
|
||||
if (target.hasClass("Siege") && !target.hasClass("Melee") &&
|
||||
!target.getMetadata(PlayerID, "transport") && plan !== -2 && plan !== -3)
|
||||
{
|
||||
@ -617,7 +617,7 @@ m.DefenseManager.prototype.garrisonRangedUnitsInside = function(gameState, targe
|
||||
if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") !== -1)
|
||||
{
|
||||
let subrole = ent.getMetadata(PlayerID, "subrole");
|
||||
if (subrole && (subrole === "completing" || subrole === "walking" || subrole === "attacking"))
|
||||
if (subrole && (subrole === "completing" || subrole === "walking" || subrole === "attacking"))
|
||||
continue;
|
||||
}
|
||||
if (gameState.ai.accessibility.getAccessValue(ent.position()) !== index)
|
||||
|
@ -58,7 +58,7 @@ m.DiplomacyManager.prototype.tributes = function(gameState)
|
||||
mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState);
|
||||
for (let k = 0; k < 2; ++k)
|
||||
{
|
||||
if (mostNeeded[k].type == res && mostNeeded[k].wanted > 0)
|
||||
if (mostNeeded[k].type == res && mostNeeded[k].wanted > 0)
|
||||
{
|
||||
this.nextTributeRequest.set("all", gameState.ai.elapsedTime + 90);
|
||||
this.nextTributeRequest.set(res, gameState.ai.elapsedTime + 240);
|
||||
|
@ -71,7 +71,7 @@ m.GarrisonManager.prototype.update = function(gameState, events)
|
||||
|
||||
let ent = gameState.getEntityById(list[j]);
|
||||
if (!ent) // unit must have been killed while garrisoning
|
||||
list.splice(j--, 1);
|
||||
list.splice(j--, 1);
|
||||
else if (holder.garrisoned().indexOf(list[j]) !== -1) // unit is garrisoned
|
||||
{
|
||||
this.leaveGarrison(ent);
|
||||
@ -155,13 +155,13 @@ m.GarrisonManager.prototype.update = function(gameState, events)
|
||||
}
|
||||
}
|
||||
|
||||
// Warning new garrison orders (as in the following lines) should be done after having updated the holders
|
||||
// Warning new garrison orders (as in the following lines) should be done after having updated the holders
|
||||
// (or TODO we should add a test that the garrison order is from a previous turn when updating)
|
||||
for (let [id, gmin] of this.decayingStructures.entries())
|
||||
{
|
||||
let ent = gameState.getEntityById(id);
|
||||
if (!ent || ent.owner() !== PlayerID)
|
||||
this.decayingStructures.delete(id);
|
||||
this.decayingStructures.delete(id);
|
||||
else if (this.numberOfGarrisonedUnits(ent) < gmin)
|
||||
gameState.ai.HQ.defenseManager.garrisonRangedUnitsInside(gameState, ent, {"min": gmin, "type": "decay"});
|
||||
}
|
||||
@ -231,7 +231,7 @@ m.GarrisonManager.prototype.keepGarrisoned = function(ent, holder, enemiesAround
|
||||
case 'decay':
|
||||
return this.decayingStructures.has(holder.id());
|
||||
default:
|
||||
if (ent.getMetadata(PlayerID, "onBoard") === "onBoard") // transport is not (yet ?) managed by garrisonManager
|
||||
if (ent.getMetadata(PlayerID, "onBoard") === "onBoard") // transport is not (yet ?) managed by garrisonManager
|
||||
return true;
|
||||
API3.warn("unknown type in garrisonManager " + ent.getMetadata(PlayerID, "garrisonType") +
|
||||
" for " + ent.id() + " inside " + holder.id());
|
||||
|
@ -114,7 +114,7 @@ m.createTerritoryMap = function(gameState)
|
||||
{
|
||||
let map = gameState.ai.territoryMap;
|
||||
|
||||
let ret = new API3.Map(gameState.sharedScript, "territory", map.data);
|
||||
let ret = new API3.Map(gameState.sharedScript, "territory", map.data);
|
||||
ret.getOwner = function(p) { return this.point(p) & m.TERRITORY_PLAYER_MASK; };
|
||||
ret.getOwnerIndex = function(p) { return this.map[p] & m.TERRITORY_PLAYER_MASK; };
|
||||
return ret;
|
||||
|
@ -14,7 +14,7 @@ var PETRA = function(m)
|
||||
m.NavalManager = function(Config)
|
||||
{
|
||||
this.Config = Config;
|
||||
|
||||
|
||||
// ship subCollections. Also exist for land zones, idem, not caring.
|
||||
this.seaShips = [];
|
||||
this.seaTransportShips = [];
|
||||
@ -28,7 +28,7 @@ m.NavalManager = function(Config)
|
||||
// needed NB per zone.
|
||||
this.neededTransportShips = [];
|
||||
this.neededWarShips = [];
|
||||
|
||||
|
||||
this.transportPlans = [];
|
||||
|
||||
// shore-line regions where we can load and unload units
|
||||
@ -42,7 +42,7 @@ m.NavalManager.prototype.init = function(gameState, deserializing)
|
||||
this.docks = gameState.getOwnStructures().filter(API3.Filters.and(API3.Filters.byClassesOr(["Dock", "Shipyard"]),
|
||||
API3.Filters.not(API3.Filters.isFoundation())));
|
||||
this.docks.registerUpdates();
|
||||
|
||||
|
||||
this.ships = gameState.getOwnUnits().filter(API3.Filters.and(API3.Filters.byClass("Ship"), API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role", "trader"))));
|
||||
// note: those two can overlap (some transport ships are warships too and vice-versa).
|
||||
this.transportShips = this.ships.filter(API3.Filters.and(API3.Filters.byCanGarrison(), API3.Filters.not(API3.Filters.byClass("FishingBoat"))));
|
||||
@ -53,7 +53,7 @@ m.NavalManager.prototype.init = function(gameState, deserializing)
|
||||
this.transportShips.registerUpdates();
|
||||
this.warShips.registerUpdates();
|
||||
this.fishShips.registerUpdates();
|
||||
|
||||
|
||||
let fishes = gameState.getFishableSupplies();
|
||||
let availableFishes = {};
|
||||
for (let fish of fishes.values())
|
||||
|
@ -408,7 +408,7 @@ m.QueueManager.prototype.update = function(gameState)
|
||||
|
||||
if (this.Config.debug > 1 && gameState.ai.playedTurn%50 === 0)
|
||||
this.printQueues(gameState);
|
||||
|
||||
|
||||
Engine.ProfileStop();
|
||||
};
|
||||
|
||||
@ -533,7 +533,7 @@ m.QueueManager.prototype.removeQueue = function(queueName)
|
||||
delete this.queues[queueName];
|
||||
delete this.priorities[queueName];
|
||||
delete this.accounts[queueName];
|
||||
|
||||
|
||||
this.queueArrays = [];
|
||||
for (let q in this.queues)
|
||||
this.queueArrays.push([q, this.queues[q]]);
|
||||
|
@ -294,7 +294,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the best non-obstructed:
|
||||
// Find the best non-obstructed:
|
||||
// Find target building's approximate obstruction radius, and expand by a bit to make sure we're not too close,
|
||||
// this allows room for units to walk between buildings.
|
||||
// note: not for houses and dropsites who ought to be closer to either each other or a resource.
|
||||
@ -468,7 +468,7 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
|
||||
if (bestVal < 0)
|
||||
return false;
|
||||
|
||||
// if no good place with enough water around and still in first phase, wait for expansion at the next phase
|
||||
// if no good place with enough water around and still in first phase, wait for expansion at the next phase
|
||||
if (!this.metadata.proximity && bestWater < 10 && gameState.currentPhase() == 1)
|
||||
return false;
|
||||
|
||||
@ -517,7 +517,7 @@ m.ConstructionPlan.prototype.getDockAngle = function(gameState, x, z, size)
|
||||
let angle = (i/numPoints)*2*Math.PI;
|
||||
pos = [x - (1+dist)*size*Math.sin(angle), z + (1+dist)*size*Math.cos(angle)];
|
||||
pos = gameState.ai.accessibility.gamePosToMapPos(pos);
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
pos[1] < 0 || pos[1] >= gameState.ai.accessibility.height)
|
||||
continue;
|
||||
let j = pos[0] + pos[1]*gameState.ai.accessibility.width;
|
||||
@ -595,21 +595,21 @@ m.ConstructionPlan.prototype.checkDockPlacement = function(gameState, x, z, half
|
||||
for (let i = 1; i < 5; ++i)
|
||||
{
|
||||
pos = gameState.ai.accessibility.gamePosToMapPos([x + sz + i*(sp+sw), z + cz + i*(cp-cw)]);
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
pos[1] < 0 || pos[1] >= gameState.ai.accessibility.height)
|
||||
break;
|
||||
j = pos[0] + pos[1]*gameState.ai.accessibility.width;
|
||||
if (gameState.ai.accessibility.landPassMap[j] > 1 || gameState.ai.accessibility.navalPassMap[j] < 2)
|
||||
break;
|
||||
pos = gameState.ai.accessibility.gamePosToMapPos([x + sz + i*sp, z + cz + i*cp]);
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
pos[1] < 0 || pos[1] >= gameState.ai.accessibility.height)
|
||||
break;
|
||||
j = pos[0] + pos[1]*gameState.ai.accessibility.width;
|
||||
if (gameState.ai.accessibility.landPassMap[j] > 1 || gameState.ai.accessibility.navalPassMap[j] < 2)
|
||||
break;
|
||||
pos = gameState.ai.accessibility.gamePosToMapPos([x + sz + i*(sp-sw), z + cz + i*(cp+cw)]);
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
if (pos[0] < 0 || pos[0] >= gameState.ai.accessibility.width ||
|
||||
pos[1] < 0 || pos[1] >= gameState.ai.accessibility.height)
|
||||
break;
|
||||
j = pos[0] + pos[1]*gameState.ai.accessibility.width;
|
||||
|
@ -20,7 +20,7 @@ m.ResearchManager.prototype.checkPhase = function(gameState, queues)
|
||||
|
||||
let townPhase = gameState.townPhase();
|
||||
let cityPhase = gameState.cityPhase();
|
||||
|
||||
|
||||
if (gameState.canResearch(townPhase,true) && gameState.getPopulation() >= this.Config.Economy.popForTown - 10 &&
|
||||
gameState.hasResearchers(townPhase, true))
|
||||
{
|
||||
@ -153,7 +153,7 @@ m.ResearchManager.prototype.researchPreferredTechs = function(gameState, techs)
|
||||
continue;
|
||||
}
|
||||
for (let i in template.modifications)
|
||||
{
|
||||
{
|
||||
if (template.modifications[i].value === "ResourceGatherer/Rates/stone.rock")
|
||||
return tech[0];
|
||||
else if (template.modifications[i].value === "ResourceGatherer/Rates/metal.ore")
|
||||
|
@ -88,7 +88,7 @@ m.HQ.prototype.assignStartingEntities = function(gameState)
|
||||
if (sea > 1 && !this.navalRegions[sea])
|
||||
this.navalRegions[sea] = true;
|
||||
|
||||
// if garrisoned units inside, ungarrison them except if a ship in which case we will make a transport
|
||||
// if garrisoned units inside, ungarrison them except if a ship in which case we will make a transport
|
||||
// when a construction will start (see createTransportIfNeeded)
|
||||
if (ent.isGarrisonHolder() && ent.garrisoned().length && !ent.hasClass("Ship"))
|
||||
for (let id of ent.garrisoned())
|
||||
@ -176,7 +176,7 @@ m.HQ.prototype.regionAnalysis = function(gameState)
|
||||
let totalSize = passabilityMap.width * passabilityMap.width;
|
||||
let minLandSize = Math.floor(0.1*totalSize);
|
||||
let minWaterSize = Math.floor(0.2*totalSize);
|
||||
let cellArea = passabilityMap.cellSize * passabilityMap.cellSize;
|
||||
let cellArea = passabilityMap.cellSize * passabilityMap.cellSize;
|
||||
for (let i = 0; i < accessibility.regionSize.length; ++i)
|
||||
{
|
||||
if (landIndex && i == landIndex)
|
||||
@ -269,7 +269,7 @@ m.HQ.prototype.buildFirstBase = function(gameState)
|
||||
goal = "dock";
|
||||
}
|
||||
|
||||
// We first choose as startingPoint the point where we have the more units
|
||||
// We first choose as startingPoint the point where we have the more units
|
||||
let startingPoint = [];
|
||||
for (let ent of gameState.getOwnUnits().values())
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ m.TradeManager.prototype.setTradingGoods = function(gameState)
|
||||
let tradingGoods = {};
|
||||
for (let res in gameState.ai.HQ.wantedRates)
|
||||
tradingGoods[res] = 0;
|
||||
// first, try to anticipate future needs
|
||||
// first, try to anticipate future needs
|
||||
let stocks = gameState.ai.HQ.getTotalResourceLevel(gameState);
|
||||
let mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState);
|
||||
let remaining = 100;
|
||||
@ -247,7 +247,7 @@ m.TradeManager.prototype.performBarter = function(gameState)
|
||||
else if (available[sell] > 1000)
|
||||
barterRateMin = 10;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
barterRateMin = 70;
|
||||
if (available[sell] > 1000)
|
||||
@ -386,7 +386,7 @@ m.TradeManager.prototype.checkEvents = function(gameState, events)
|
||||
|
||||
/**
|
||||
* fills the best trade route in this.tradeRoute and the best potential route in this.potentialTradeRoute
|
||||
* If an index is given, it returns the best route with this index or the best land route if index is a land index
|
||||
* If an index is given, it returns the best route with this index or the best land route if index is a land index
|
||||
*/
|
||||
m.TradeManager.prototype.checkRoutes = function(gameState, accessIndex)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ var PETRA = function(m)
|
||||
* = "onBoard" when garrisoned in a ship
|
||||
* = undefined otherwise
|
||||
* endPos = position of destination
|
||||
*
|
||||
*
|
||||
* metadata for ships
|
||||
* transporter = this.ID
|
||||
*/
|
||||
@ -81,7 +81,7 @@ m.TransportPlan.prototype.init = function(gameState)
|
||||
this.units = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "transport", this.ID));
|
||||
this.ships = gameState.ai.HQ.navalManager.ships.filter(API3.Filters.byMetadata(PlayerID, "transporter", this.ID));
|
||||
this.transportShips = gameState.ai.HQ.navalManager.transportShips.filter(API3.Filters.byMetadata(PlayerID, "transporter", this.ID));
|
||||
|
||||
|
||||
this.units.registerUpdates();
|
||||
this.ships.registerUpdates();
|
||||
this.transportShips.registerUpdates();
|
||||
@ -290,7 +290,7 @@ m.TransportPlan.prototype.onBoarding = function(gameState)
|
||||
self.boardingPos[shipId] = self.getBoardingPos(gameState, ship, self.startIndex, self.sea, undefined, false);
|
||||
}
|
||||
ship.move(self.boardingPos[shipId][0], self.boardingPos[shipId][1]);
|
||||
ship.setMetadata(PlayerID, "timeGarrison", time);
|
||||
ship.setMetadata(PlayerID, "timeGarrison", time);
|
||||
}
|
||||
else if (time - ent.getMetadata(PlayerID, "timeGarrison") > 2)
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ m.Worker.prototype.update = function(gameState, ent)
|
||||
{
|
||||
if (unitAIStateOrder === "REPAIR")
|
||||
{
|
||||
// update our target in case UnitAI sent us to a different foundation because of autocontinue
|
||||
// update our target in case UnitAI sent us to a different foundation because of autocontinue
|
||||
if (ent.unitAIOrderData()[0] && ent.unitAIOrderData()[0].target &&
|
||||
ent.getMetadata(PlayerID, "target-foundation") !== ent.unitAIOrderData()[0].target)
|
||||
ent.setMetadata(PlayerID, "target-foundation", ent.unitAIOrderData()[0].target);
|
||||
@ -533,7 +533,7 @@ m.Worker.prototype.startHunting = function(gameState, position)
|
||||
if (!position && this.gatherTreasure(gameState))
|
||||
return true;
|
||||
|
||||
let resources = gameState.getHuntableSupplies();
|
||||
let resources = gameState.getHuntableSupplies();
|
||||
if (!resources.hasEntities())
|
||||
return false;
|
||||
|
||||
@ -587,7 +587,7 @@ m.Worker.prototype.startHunting = function(gameState, position)
|
||||
return;
|
||||
|
||||
let canFlee = !supply.hasClass("Domestic") && supply.templateName().indexOf("resource|") == -1;
|
||||
// Only cavalry and range units should hunt fleeing animals
|
||||
// Only cavalry and range units should hunt fleeing animals
|
||||
if (canFlee && !isCavalry && !isRanged)
|
||||
return;
|
||||
|
||||
@ -766,11 +766,11 @@ m.Worker.prototype.gatherNearestField = function(gameState, baseID)
|
||||
|
||||
/**
|
||||
* WARNING with the present options of AI orders, the unit will not gather after building the farm.
|
||||
* This is done by calling the gatherNearestField function when construction is completed.
|
||||
* This is done by calling the gatherNearestField function when construction is completed.
|
||||
*/
|
||||
m.Worker.prototype.buildAnyField = function(gameState, baseID)
|
||||
{
|
||||
let baseFoundations = gameState.getOwnFoundations().filter(API3.Filters.byMetadata(PlayerID, "base", baseID));
|
||||
let baseFoundations = gameState.getOwnFoundations().filter(API3.Filters.byMetadata(PlayerID, "base", baseID));
|
||||
let maxGatherers = gameState.getTemplate(gameState.applyCiv("structures/{civ}_field")).maxGatherers();
|
||||
let bestFarmEnt = false;
|
||||
let bestFarmDist = 10000000;
|
||||
|
@ -5,7 +5,7 @@ var baseConfig = {
|
||||
"enemyRatio" : 1.5, // attackMoveToLocation
|
||||
"groupSize" : 10 // military
|
||||
},
|
||||
|
||||
|
||||
// defence
|
||||
"defence" : {
|
||||
"acquireDistance" : 220,
|
||||
@ -15,7 +15,7 @@ var baseConfig = {
|
||||
"groupMergeRadius" : 10,
|
||||
"defenderRatio" : 2
|
||||
},
|
||||
|
||||
|
||||
// military
|
||||
"buildings" : {
|
||||
"moderate" : {
|
||||
@ -46,7 +46,7 @@ var baseConfig = {
|
||||
"defenceBuilding" : 17,
|
||||
"civilCentre" : 1000
|
||||
},
|
||||
|
||||
|
||||
"debug" : false
|
||||
};
|
||||
|
||||
|
@ -12,39 +12,39 @@
|
||||
var Timer = function() {
|
||||
///Private array.
|
||||
var alarmList = [];
|
||||
|
||||
|
||||
///Private methods
|
||||
function num_alarms() {
|
||||
return alarmList.length;
|
||||
};
|
||||
|
||||
|
||||
function get_alarm(id) {
|
||||
return alarmList[id];
|
||||
};
|
||||
|
||||
|
||||
function add_alarm(index, alarm) {
|
||||
alarmList[index] = alarm;
|
||||
};
|
||||
|
||||
|
||||
function delete_alarm(id) {
|
||||
// Set the array element to undefined
|
||||
delete alarmList[id];
|
||||
};
|
||||
|
||||
|
||||
///Privileged methods
|
||||
// Add an new alarm to the list
|
||||
this.setTimer = function(gameState, interval, delay, repeat) {
|
||||
delay = delay || 0;
|
||||
repeat = repeat || -1;
|
||||
|
||||
|
||||
var index = num_alarms();
|
||||
|
||||
|
||||
//Add a new alarm to the list
|
||||
add_alarm(index, new alarm(gameState, index, interval, delay, repeat));
|
||||
return index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if a alarm has reached its interval.
|
||||
this.checkTimer = function(gameState,id) {
|
||||
var alarm = get_alarm(id);
|
||||
@ -54,7 +54,7 @@ var Timer = function() {
|
||||
return false;
|
||||
var time = gameState.getTimeElapsed();
|
||||
var alarmState = false;
|
||||
|
||||
|
||||
// If repeat forever (repeat is -1). Or if the alarm has rung less times than repeat.
|
||||
if (alarm.repeat < 0 || alarm.counter < alarm.repeat) {
|
||||
var time_difference = time - alarm.start_time - alarm.delay - alarm.interval * alarm.counter;
|
||||
@ -63,26 +63,26 @@ var Timer = function() {
|
||||
alarm.counter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if the alarm has rung 'alarm.repeat' times if so, delete the alarm.
|
||||
if (alarm.counter >= alarm.repeat && alarm.repeat != -1) {
|
||||
this.clearTimer(id);
|
||||
}
|
||||
|
||||
|
||||
return alarmState;
|
||||
};
|
||||
|
||||
|
||||
// Remove an alarm from the list.
|
||||
this.clearTimer = function(id) {
|
||||
delete_alarm(id);
|
||||
};
|
||||
|
||||
|
||||
// Activate a deactivated alarm.
|
||||
this.activateTimer = function(id) {
|
||||
var alarm = get_alarm(id);
|
||||
alarm.active = true;
|
||||
};
|
||||
|
||||
|
||||
// Deactivate an active alarm but don't delete it.
|
||||
this.deactivateTimer = function(id) {
|
||||
var alarm = get_alarm(id);
|
||||
@ -97,7 +97,7 @@ var alarm = function(gameState, id, interval, delay, repeat) {
|
||||
this.interval = interval;
|
||||
this.delay = delay;
|
||||
this.repeat = repeat;
|
||||
|
||||
|
||||
this.start_time = gameState.getTimeElapsed();
|
||||
this.active = true;
|
||||
this.counter = 0;
|
||||
|
@ -1,15 +1,15 @@
|
||||
var TutorialAI = (function() {
|
||||
var m = {};
|
||||
|
||||
|
||||
m.TutorialAI = function(settings) {
|
||||
API3.BaseAI.call(this, settings);
|
||||
|
||||
this.turn = 0;
|
||||
|
||||
|
||||
this.firstTime = true;
|
||||
|
||||
this.savedEvents = [];
|
||||
|
||||
|
||||
this.toUpdate = [];
|
||||
}
|
||||
|
||||
@ -19,21 +19,21 @@ m.TutorialAI.prototype = new API3.BaseAI();
|
||||
m.TutorialAI.prototype.runInit = function(gameState) {
|
||||
if (this.firstTime){
|
||||
this.firstTime = false;
|
||||
|
||||
|
||||
this.chooseTutorial(gameState);
|
||||
|
||||
|
||||
if (this.tutorial === undefined) return;
|
||||
|
||||
|
||||
this.currentPos = 0;
|
||||
this.currentState = this.tutorial[this.currentPos];
|
||||
|
||||
|
||||
this.lastChat = -1000000;
|
||||
}
|
||||
};
|
||||
|
||||
m.TutorialAI.prototype.chooseTutorial = function(gameState) {
|
||||
var trees = gameState.updatingCollection("trees", API3.Filters.byClass("ForestPlant"), gameState.getEntities());
|
||||
|
||||
|
||||
var numTrees = trees.length;
|
||||
switch (numTrees) {
|
||||
case 945:
|
||||
@ -50,22 +50,22 @@ m.TutorialAI.prototype.OnUpdate = function() {
|
||||
if (this.gameFinished){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.events.length)
|
||||
this.savedEvents = this.savedEvents.concat(this.events);
|
||||
|
||||
|
||||
Engine.ProfileStart("tutorialBot");
|
||||
|
||||
|
||||
var gameState = this.gameState;
|
||||
this.runInit(gameState);
|
||||
|
||||
|
||||
if (this.tutorial === undefined) return;
|
||||
|
||||
|
||||
if (gameState.getTimeElapsed() - this.lastChat > 30000){
|
||||
this.chat(this.currentState.instructions);
|
||||
this.lastChat = gameState.getTimeElapsed();
|
||||
}
|
||||
|
||||
|
||||
// check to see if we need to change state
|
||||
var nextState = this.tutorial[this.currentPos + 1];
|
||||
var doNext = false;
|
||||
@ -73,7 +73,7 @@ m.TutorialAI.prototype.OnUpdate = function() {
|
||||
case "near_cc":
|
||||
var ents = gameState.getEnemyEntities();
|
||||
var CC = gameState.updatingCollection("cc", API3.Filters.and(API3.Filters.byClass("CivCentre"), API3.Filters.byOwner(2)), gameState.getEntities());
|
||||
|
||||
|
||||
ents.forEach(function(ent) {
|
||||
if (!ent.position()){
|
||||
return;
|
||||
@ -114,7 +114,7 @@ m.TutorialAI.prototype.OnUpdate = function() {
|
||||
break;
|
||||
case "entity_count":
|
||||
var ents = gameState.updatingCollection(
|
||||
nextState.template,
|
||||
nextState.template,
|
||||
API3.Filters.byType(nextState.template),
|
||||
gameState.getEnemyEntities());
|
||||
if (ents.length >= nextState.count) {
|
||||
@ -125,7 +125,7 @@ m.TutorialAI.prototype.OnUpdate = function() {
|
||||
doNext = true;
|
||||
for (var i = 0; i < nextState.templates.length; i++) {
|
||||
var ents = gameState.updatingCollection(
|
||||
nextState.templates[i],
|
||||
nextState.templates[i],
|
||||
API3.Filters.byType(nextState.templates[i]),
|
||||
gameState.getEnemyEntities());
|
||||
if (ents.length < nextState.counts[i]) {
|
||||
@ -161,13 +161,13 @@ m.TutorialAI.prototype.OnUpdate = function() {
|
||||
if (this.currentState.action) {
|
||||
this.currentState.action(gameState);
|
||||
}
|
||||
|
||||
|
||||
if (this.currentPos >= this.tutorial.length - 1){
|
||||
gameState.getOwnEntities().destroy();
|
||||
this.gameFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete this.savedEvents;
|
||||
this.savedEvents = [];
|
||||
|
||||
@ -189,7 +189,7 @@ m.TutorialAI.prototype.Serialize = function()
|
||||
return {
|
||||
_rawEntities: this._rawEntities,
|
||||
_ownEntities: this._ownEntities,
|
||||
_entityMetadata: {} // We store fancy data structures in entity metadata so
|
||||
_entityMetadata: {} // We store fancy data structures in entity metadata so
|
||||
//don't try and serialize it
|
||||
};
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ AIInterface.prototype.GetNonEntityRepresentation = function()
|
||||
|
||||
// Return the same game state as the GUI uses
|
||||
let state = cmpGuiInterface.GetSimulationState(-1);
|
||||
|
||||
|
||||
// Add some extra AI-specific data
|
||||
// add custom events and reset them for the next turn
|
||||
state.events = {};
|
||||
@ -132,7 +132,7 @@ AIInterface.prototype.GetRepresentation = function()
|
||||
* Intended to be called first, during the map initialization: no caching
|
||||
*/
|
||||
AIInterface.prototype.GetFullRepresentation = function(flushEvents)
|
||||
{
|
||||
{
|
||||
let state = this.GetNonEntityRepresentation();
|
||||
|
||||
if (flushEvents)
|
||||
@ -146,7 +146,7 @@ AIInterface.prototype.GetFullRepresentation = function(flushEvents)
|
||||
for (let id of Engine.GetEntitiesWithInterface(IID_AIProxy))
|
||||
state.entities[id] = Engine.QueryInterface(id, IID_AIProxy).GetFullRepresentation();
|
||||
Engine.ProfileStop();
|
||||
|
||||
|
||||
state.changedTemplateInfo = this.changedTemplateInfo;
|
||||
this.changedTemplateInfo = {};
|
||||
state.changedEntityTemplateInfo = this.changedEntityTemplateInfo;
|
||||
|
@ -146,7 +146,7 @@ AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg)
|
||||
{
|
||||
if (!this.NotifyChange())
|
||||
return;
|
||||
|
||||
|
||||
let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
|
||||
this.changes.garrisoned = cmpGarrisonHolder.GetEntities();
|
||||
|
||||
@ -329,7 +329,7 @@ AIProxy.prototype.GetFullRepresentation = function()
|
||||
AIProxy.prototype.OnOwnershipChanged = function(msg)
|
||||
{
|
||||
this.NotifyChange();
|
||||
|
||||
|
||||
if (msg.from === -1)
|
||||
{
|
||||
this.cmpAIInterface.PushEvent("Create", {"entity" : msg.entity});
|
||||
@ -341,7 +341,7 @@ AIProxy.prototype.OnOwnershipChanged = function(msg)
|
||||
this.needsFullGet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.changes.owner = msg.to;
|
||||
this.cmpAIInterface.PushEvent("OwnershipChanged", msg);
|
||||
};
|
||||
|
@ -1,10 +1,10 @@
|
||||
function AlertRaiser() {}
|
||||
|
||||
AlertRaiser.prototype.Schema =
|
||||
AlertRaiser.prototype.Schema =
|
||||
"<element name='MaximumLevel'><data type='nonNegativeInteger'/></element>" +
|
||||
"<element name='Range'><data type='nonNegativeInteger'/></element>";
|
||||
|
||||
AlertRaiser.prototype.Init = function()
|
||||
AlertRaiser.prototype.Init = function()
|
||||
{
|
||||
this.level = 0;
|
||||
|
||||
@ -39,7 +39,7 @@ AlertRaiser.prototype.SoundAlert = function()
|
||||
|
||||
AlertRaiser.prototype.UpdateUnits = function(units)
|
||||
{
|
||||
var level = this.GetLevel();
|
||||
var level = this.GetLevel();
|
||||
for each (var unit in units)
|
||||
{
|
||||
var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI);
|
||||
@ -117,7 +117,7 @@ AlertRaiser.prototype.EndOfAlert = function()
|
||||
continue;
|
||||
|
||||
cmpUnitAI.ResetAlert();
|
||||
|
||||
|
||||
if (cmpUnitAI.HasWorkOrders())
|
||||
cmpUnitAI.BackToWork();
|
||||
else
|
||||
@ -136,7 +136,7 @@ AlertRaiser.prototype.EndOfAlert = function()
|
||||
// If the garrison building was destroyed, the unit is already ejected
|
||||
if (!cmpGarrisonHolder || cmpGarrisonHolder.PerformEject([slot.unit], true))
|
||||
{
|
||||
cmpUnitAI.ResetAlert();
|
||||
cmpUnitAI.ResetAlert();
|
||||
if (cmpUnitAI.HasWorkOrders())
|
||||
cmpUnitAI.BackToWork();
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ Armour.prototype.Schema =
|
||||
"<element name='Crush' a:help='Crush damage protection'>" +
|
||||
"<ref name='nonNegativeDecimal'/>" +
|
||||
"</element>" +
|
||||
"<optional>" +
|
||||
"<optional>" +
|
||||
"<element name='Foundation' a:help='Armour given to building foundations'>" +
|
||||
"<interleave>" +
|
||||
"<element name='Hack' a:help='Hack damage protection'>" +
|
||||
@ -48,7 +48,7 @@ Armour.prototype.SetInvulnerability = function(invulnerability)
|
||||
*/
|
||||
Armour.prototype.TakeDamage = function(hack, pierce, crush)
|
||||
{
|
||||
if (this.invulnerable)
|
||||
if (this.invulnerable)
|
||||
return { "killed": false, "change": 0 };
|
||||
|
||||
// Adjust damage values based on armour; exponential armour: damage = attack * 0.9^armour
|
||||
@ -71,17 +71,17 @@ Armour.prototype.GetArmourStrengths = function()
|
||||
// Work out the armour values with technology effects
|
||||
var applyMods = (type, foundation) => {
|
||||
var strength;
|
||||
if (foundation)
|
||||
if (foundation)
|
||||
{
|
||||
strength = +this.template.Foundation[type];
|
||||
type = "Foundation/" + type;
|
||||
}
|
||||
else
|
||||
strength = +this.template[type];
|
||||
|
||||
|
||||
return ApplyValueModificationsToEntity("Armour/" + type, strength, this.entity);
|
||||
};
|
||||
|
||||
|
||||
var foundation = Engine.QueryInterface(this.entity, IID_Foundation) && this.template.Foundation;
|
||||
|
||||
return {
|
||||
|
@ -461,7 +461,7 @@ Attack.prototype.PerformAttack = function(type, target)
|
||||
{
|
||||
let attackerOwner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner();
|
||||
let cmpDamage = Engine.QueryInterface(SYSTEM_ENTITY, IID_Damage);
|
||||
|
||||
|
||||
// If this is a ranged attack, then launch a projectile
|
||||
if (type == "Ranged")
|
||||
{
|
||||
@ -556,7 +556,7 @@ Attack.prototype.PerformAttack = function(type, target)
|
||||
{
|
||||
if (attackerOwner == -1)
|
||||
return;
|
||||
|
||||
|
||||
let multiplier = this.GetAttackBonus(type, target);
|
||||
let cmpHealth = Engine.QueryInterface(target, IID_Health);
|
||||
if (!cmpHealth || cmpHealth.GetHitpoints() == 0)
|
||||
|
@ -58,7 +58,7 @@ AttackDetection.prototype.OnGlobalAttacked = function(msg)
|
||||
AttackDetection.prototype.AttackAlert = function(target, attacker, attackerOwner)
|
||||
{
|
||||
let playerID = Engine.QueryInterface(this.entity, IID_Player).GetPlayerID();
|
||||
|
||||
|
||||
// Don't register attacks dealt against other players
|
||||
if (Engine.QueryInterface(target, IID_Ownership).GetOwner() != playerID)
|
||||
return;
|
||||
@ -73,7 +73,7 @@ AttackDetection.prototype.AttackAlert = function(target, attacker, attackerOwner
|
||||
// and generally are not so valuable as other units/buildings,
|
||||
// we have a lower priority notification for it, which can be
|
||||
// overriden by a regular one.
|
||||
var cmpTargetIdentity = Engine.QueryInterface(target, IID_Identity);
|
||||
var cmpTargetIdentity = Engine.QueryInterface(target, IID_Identity);
|
||||
var targetIsDomesticAnimal = cmpTargetIdentity && cmpTargetIdentity.HasClass("Animal") && cmpTargetIdentity.HasClass("Domestic");
|
||||
|
||||
var cmpPosition = Engine.QueryInterface(target, IID_Position);
|
||||
|
@ -267,7 +267,7 @@ BuildRestrictions.prototype.CheckPlacement = function()
|
||||
var cmpIdentity = Engine.QueryInterface(id, IID_Identity);
|
||||
return cmpIdentity.GetClassesList().indexOf(cat) > -1;
|
||||
};
|
||||
|
||||
|
||||
if (this.template.Distance.MinDistance)
|
||||
{
|
||||
var dist = +this.template.Distance.MinDistance;
|
||||
|
@ -35,11 +35,11 @@ Builder.prototype.GetEntitiesList = function()
|
||||
if (cmpIdentity)
|
||||
string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());
|
||||
entities = string.split(/\s+/);
|
||||
|
||||
|
||||
// Remove disabled entities
|
||||
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
|
||||
var disabledEntities = cmpPlayer.GetDisabledTemplates();
|
||||
|
||||
|
||||
for (var i = entities.length - 1; i >= 0; --i)
|
||||
if (disabledEntities[entities[i]])
|
||||
entities.splice(i, 1);
|
||||
|
@ -13,7 +13,7 @@ Capturable.prototype.Schema =
|
||||
|
||||
Capturable.prototype.Init = function()
|
||||
{
|
||||
// Cache this value
|
||||
// Cache this value
|
||||
this.maxCp = +this.template.CapturePoints;
|
||||
this.cp = [];
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
function Damage() {}
|
||||
|
||||
Damage.prototype.Schema =
|
||||
Damage.prototype.Schema =
|
||||
"<a:component type='system'/><empty/>";
|
||||
|
||||
|
||||
Damage.prototype.Init = function()
|
||||
{
|
||||
};
|
||||
@ -86,7 +86,7 @@ Damage.prototype.MissileHit = function(data, lateness)
|
||||
{
|
||||
if (!data.position)
|
||||
return;
|
||||
|
||||
|
||||
// Do this first in case the direct hit kills the target
|
||||
if (data.isSplash)
|
||||
{
|
||||
@ -114,7 +114,7 @@ Damage.prototype.MissileHit = function(data, lateness)
|
||||
}
|
||||
|
||||
let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager);
|
||||
|
||||
|
||||
// Deal direct damage if we hit the main target
|
||||
if (this.TestCollision(data.target, data.position, lateness))
|
||||
{
|
||||
@ -122,7 +122,7 @@ Damage.prototype.MissileHit = function(data, lateness)
|
||||
cmpProjectileManager.RemoveProjectile(data.projectileId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let targetPosition = this.InterpolatedLocation(data.target, lateness);
|
||||
if (!targetPosition)
|
||||
return;
|
||||
@ -264,7 +264,7 @@ Damage.prototype.TargetKilled = function(attacker, target, attackerOwner)
|
||||
{
|
||||
let cmpAttackerOwnership = Engine.QueryInterface(attacker, IID_Ownership);
|
||||
let atkOwner = cmpAttackerOwnership && cmpAttackerOwnership.GetOwner() != -1 ? cmpAttackerOwnership.GetOwner() : attackerOwner;
|
||||
|
||||
|
||||
// Add to killer statistics.
|
||||
let cmpKillerPlayerStatisticsTracker = QueryPlayerIDInterface(atkOwner, IID_StatisticsTracker);
|
||||
if (cmpKillerPlayerStatisticsTracker)
|
||||
@ -279,5 +279,5 @@ Damage.prototype.TargetKilled = function(attacker, target, attackerOwner)
|
||||
if (cmpLooter)
|
||||
cmpLooter.Collect(target);
|
||||
};
|
||||
|
||||
|
||||
Engine.RegisterSystemComponentType(IID_Damage, "Damage", Damage);
|
||||
|
@ -6,7 +6,7 @@ function EndGameManager() {}
|
||||
|
||||
EndGameManager.prototype.Schema =
|
||||
"<a:component type='system'/><empty/>";
|
||||
|
||||
|
||||
EndGameManager.prototype.Init = function()
|
||||
{
|
||||
this.gameType = "conquest";
|
||||
|
@ -67,7 +67,7 @@ const BUILD = "build";
|
||||
EntityLimits.prototype.Init = function()
|
||||
{
|
||||
this.limit = {};
|
||||
this.count = {}; // counts entities which change the limit of the given category
|
||||
this.count = {}; // counts entities which change the limit of the given category
|
||||
this.changers = {};
|
||||
this.removers = {};
|
||||
this.classCount = {}; // counts entities with the given class, used in the limit removal
|
||||
@ -151,7 +151,7 @@ EntityLimits.prototype.AllowedToCreate = function(limitType, category, count)
|
||||
// Allow unspecified categories and those with no limit
|
||||
if (this.count[category] === undefined || this.limit[category] === undefined)
|
||||
return true;
|
||||
|
||||
|
||||
if (this.count[category] + count > this.limit[category])
|
||||
{
|
||||
var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
|
||||
@ -173,17 +173,17 @@ EntityLimits.prototype.AllowedToCreate = function(limitType, category, count)
|
||||
}
|
||||
var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
|
||||
cmpGUIInterface.PushNotification(notification);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.AllowedToBuild = function(category)
|
||||
{
|
||||
// We pass count 0 as the creation of the building has already taken place and
|
||||
// the ownership has been set (triggering OnGlobalOwnershipChanged)
|
||||
// the ownership has been set (triggering OnGlobalOwnershipChanged)
|
||||
return this.AllowedToCreate(BUILD, category, 0);
|
||||
};
|
||||
|
||||
@ -205,7 +205,7 @@ EntityLimits.prototype.OnGlobalOwnershipChanged = function(msg)
|
||||
var modifier = -1;
|
||||
else if (msg.to == cmpPlayer.GetPlayerID())
|
||||
var modifier = 1;
|
||||
else
|
||||
else
|
||||
return;
|
||||
|
||||
// Update entity counts
|
||||
|
@ -69,7 +69,7 @@ Formation.prototype.Schema =
|
||||
"<text a:help='example text: \"1..1,1..-1:animation1;2..2,1..-1;animation2\", this will set animation1 for the first row, and animation2 for the second row. The first part of the numbers (1..1 and 2..2) means the row range. Every row between (and including) those values will switch animations. The second part of the numbers (1..-1) denote the columns inside those rows that will be affected. Note that in both cases, you can use -1 for the last row/column, -2 for the second to last, etc.'/>" +
|
||||
"</element>" +
|
||||
"</zeroOrMore>" +
|
||||
"</element>";
|
||||
"</element>";
|
||||
|
||||
var g_ColumnDistanceThreshold = 128; // distance at which we'll switch between column/box formations
|
||||
|
||||
@ -367,7 +367,7 @@ Formation.prototype.RemoveMembers = function(ents)
|
||||
Formation.prototype.AddMembers = function(ents)
|
||||
{
|
||||
this.offsets = undefined;
|
||||
this.inPosition = [];
|
||||
this.inPosition = [];
|
||||
|
||||
for each (var ent in this.formationMembersWithAura)
|
||||
{
|
||||
@ -385,7 +385,7 @@ Formation.prototype.AddMembers = function(ents)
|
||||
{
|
||||
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
||||
cmpUnitAI.SetFormationController(this.entity);
|
||||
|
||||
|
||||
var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
|
||||
if (cmpAuras && cmpAuras.HasFormationAura())
|
||||
{
|
||||
@ -517,8 +517,8 @@ Formation.prototype.MoveMembersIntoFormation = function(moveCenter, force)
|
||||
var cmpUnitAI = Engine.QueryInterface(offset.ent, IID_UnitAI);
|
||||
if (!cmpUnitAI)
|
||||
continue;
|
||||
|
||||
var data =
|
||||
|
||||
var data =
|
||||
{
|
||||
"target": this.entity,
|
||||
"x": offset.x,
|
||||
@ -604,9 +604,9 @@ Formation.prototype.ComputeFormationOffsets = function(active, positions)
|
||||
var sortingClasses = this.sortingClasses.slice();
|
||||
sortingClasses.push("Unknown");
|
||||
|
||||
// the entities will be assigned to positions in the formation in
|
||||
// the entities will be assigned to positions in the formation in
|
||||
// the same order as the types list is ordered
|
||||
var types = {};
|
||||
var types = {};
|
||||
for (var i = 0; i < sortingClasses.length; ++i)
|
||||
types[sortingClasses[i]] = [];
|
||||
|
||||
@ -750,7 +750,7 @@ Formation.prototype.ComputeFormationOffsets = function(active, positions)
|
||||
if (this.sortingOrder == "fillFromTheSides")
|
||||
offsets.sort(function(o1, o2) { return Math.abs(o1.x) < Math.abs(o2.x);});
|
||||
else if (this.sortingOrder == "fillToTheCenter")
|
||||
offsets.sort(function(o1, o2) {
|
||||
offsets.sort(function(o1, o2) {
|
||||
return Math.max(Math.abs(o1.x), Math.abs(o1.y)) < Math.max(Math.abs(o2.x), Math.abs(o2.y));
|
||||
});
|
||||
|
||||
@ -820,7 +820,7 @@ Formation.prototype.GetRealOffsetPositions = function(offsets, pos)
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the estimated rotation of the formation
|
||||
* calculate the estimated rotation of the formation
|
||||
* based on the first unitAI target position when ordered to walk,
|
||||
* based on the current rotation in other cases
|
||||
* Return the sine and cosine of the angle
|
||||
@ -875,7 +875,7 @@ Formation.prototype.ComputeMotionParameters = function()
|
||||
|
||||
Formation.prototype.ShapeUpdate = function()
|
||||
{
|
||||
// Check the distance to twin formations, and merge if when
|
||||
// Check the distance to twin formations, and merge if when
|
||||
// the formations could collide
|
||||
for (var i = this.twinFormations.length - 1; i >= 0; --i)
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ FormationAttack.prototype.GetRange = function(target)
|
||||
if (!type)
|
||||
continue;
|
||||
|
||||
// if the formation can attack, take the minimum max range (so units are certainly in range),
|
||||
// if the formation can attack, take the minimum max range (so units are certainly in range),
|
||||
// If the formation can't attack, take the maximum max range as the point where the formation will be disbanded
|
||||
// Always take the minimum min range (to not get impossible situations)
|
||||
var range = cmpAttack.GetRange(type);
|
||||
|
@ -14,7 +14,7 @@ Foundation.prototype.Init = function()
|
||||
|
||||
this.builders = []; // builder entities
|
||||
this.buildMultiplier = 1; // Multiplier for the amount of work builders do.
|
||||
|
||||
|
||||
this.previewEntity = INVALID_ENTITY;
|
||||
|
||||
// Penalty for multiple builders
|
||||
@ -43,7 +43,7 @@ Foundation.prototype.InitialiseConstruction = function(owner, template)
|
||||
};
|
||||
|
||||
/**
|
||||
* Moving the revelation logic from Build to here makes the building sink if
|
||||
* Moving the revelation logic from Build to here makes the building sink if
|
||||
* it is attacked.
|
||||
*/
|
||||
Foundation.prototype.OnHealthChanged = function(msg)
|
||||
@ -52,7 +52,7 @@ Foundation.prototype.OnHealthChanged = function(msg)
|
||||
var cmpPosition = Engine.QueryInterface(this.previewEntity, IID_Position);
|
||||
if (cmpPosition)
|
||||
cmpPosition.SetConstructionProgress(this.GetBuildProgress());
|
||||
|
||||
|
||||
Engine.PostMessage(this.entity, MT_FoundationProgressChanged, { "to": this.GetBuildPercentage() });
|
||||
};
|
||||
|
||||
@ -173,7 +173,7 @@ Foundation.prototype.Build = function(builderEnt, work)
|
||||
// this won't happen much)
|
||||
if (this.GetBuildProgress() == 1.0)
|
||||
return;
|
||||
|
||||
|
||||
// If there's any units in the way, ask them to move away
|
||||
// and return early from this method.
|
||||
var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
|
||||
@ -219,7 +219,7 @@ Foundation.prototype.Build = function(builderEnt, work)
|
||||
if (cmpObstruction && cmpObstruction.GetBlockMovementFlag())
|
||||
cmpObstruction.SetDisableBlockMovementPathfinding(false, false, -1);
|
||||
|
||||
// Call the related trigger event
|
||||
// Call the related trigger event
|
||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
||||
cmpTrigger.CallEvent("ConstructionStarted", {
|
||||
"foundation": this.entity,
|
||||
@ -354,7 +354,7 @@ Foundation.prototype.Build = function(builderEnt, work)
|
||||
return;
|
||||
}
|
||||
cmpBuildingOwnership.SetOwner(owner);
|
||||
|
||||
|
||||
/*
|
||||
Copy over the obstruction control group IDs from the foundation
|
||||
entities. This is needed to ensure that when a foundation is completed
|
||||
@ -367,21 +367,21 @@ Foundation.prototype.Build = function(builderEnt, work)
|
||||
new control group containing only itself, and will hence block
|
||||
construction of any surrounding foundations that it was previously in
|
||||
the same control group with.
|
||||
|
||||
|
||||
Note that this will result in the completed building entities having
|
||||
control group IDs that equal entity IDs of old (and soon to be deleted)
|
||||
foundation entities. This should not have any consequences, however,
|
||||
since the control group IDs are only meant to be unique identifiers,
|
||||
which is still true when reusing the old ones.
|
||||
*/
|
||||
|
||||
|
||||
var cmpBuildingObstruction = Engine.QueryInterface(building, IID_Obstruction);
|
||||
if (cmpObstruction && cmpBuildingObstruction)
|
||||
{
|
||||
cmpBuildingObstruction.SetControlGroup(cmpObstruction.GetControlGroup());
|
||||
cmpBuildingObstruction.SetControlGroup2(cmpObstruction.GetControlGroup2());
|
||||
}
|
||||
|
||||
|
||||
var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
|
||||
if (cmpPlayerStatisticsTracker)
|
||||
cmpPlayerStatisticsTracker.IncreaseConstructedBuildingsCounter(building);
|
||||
|
@ -217,7 +217,7 @@ Gate.prototype.CloseGate = function()
|
||||
// The gate can't be closed if there are entities colliding with it.
|
||||
var collisions = cmpObstruction.GetUnitCollisions();
|
||||
if (collisions.length)
|
||||
{
|
||||
{
|
||||
if (!this.timer)
|
||||
{
|
||||
// Set an "instant" timer which will run on the next simulation turn.
|
||||
|
@ -37,7 +37,7 @@ Guard.prototype.AddGuard = function(ent)
|
||||
{
|
||||
if (this.entities.indexOf(ent) != -1)
|
||||
return;
|
||||
this.entities.push(ent);
|
||||
this.entities.push(ent);
|
||||
};
|
||||
|
||||
Guard.prototype.RemoveGuard = function(ent)
|
||||
|
@ -17,16 +17,16 @@ Health.prototype.Schema =
|
||||
"</element>" +
|
||||
"</optional>" +
|
||||
"<optional>" +
|
||||
"<element name='DamageVariants'>" +
|
||||
"<oneOrMore>" +
|
||||
"<element a:help='Name of the variant to select when health drops under the defined ratio'>" +
|
||||
"<anyName/>" +
|
||||
"<data type='decimal'>" +
|
||||
"<param name='minInclusive'>0</param>" +
|
||||
"<param name='maxInclusive'>1</param>" +
|
||||
"</data>" +
|
||||
"</element>" +
|
||||
"</oneOrMore>" +
|
||||
"<element name='DamageVariants'>" +
|
||||
"<oneOrMore>" +
|
||||
"<element a:help='Name of the variant to select when health drops under the defined ratio'>" +
|
||||
"<anyName/>" +
|
||||
"<data type='decimal'>" +
|
||||
"<param name='minInclusive'>0</param>" +
|
||||
"<param name='maxInclusive'>1</param>" +
|
||||
"</data>" +
|
||||
"</element>" +
|
||||
"</oneOrMore>" +
|
||||
"</element>" +
|
||||
"</optional>" +
|
||||
"<element name='RegenRate' a:help='Hitpoint regeneration rate per second.'>" +
|
||||
@ -97,7 +97,7 @@ Health.prototype.SetHitpoints = function(value)
|
||||
|
||||
var old = this.hitpoints;
|
||||
this.hitpoints = Math.max(1, Math.min(this.GetMaxHitpoints(), value));
|
||||
|
||||
|
||||
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
if (cmpRangeManager)
|
||||
{
|
||||
@ -154,7 +154,7 @@ Health.prototype.ExecuteRegeneration = function()
|
||||
|
||||
if (regen > 0)
|
||||
this.Increase(regen);
|
||||
else
|
||||
else
|
||||
this.Reduce(-regen);
|
||||
};
|
||||
|
||||
@ -272,7 +272,7 @@ Health.prototype.Increase = function(amount)
|
||||
|
||||
var old = this.hitpoints;
|
||||
this.hitpoints = Math.min(this.hitpoints + amount, this.GetMaxHitpoints());
|
||||
|
||||
|
||||
if (this.hitpoints == this.GetMaxHitpoints())
|
||||
{
|
||||
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
@ -361,19 +361,19 @@ Health.prototype.UpdateActor = function()
|
||||
return;
|
||||
let ratio = this.GetHitpoints() / this.GetMaxHitpoints();
|
||||
let newDamageVariant = "alive";
|
||||
if (ratio > 0)
|
||||
{
|
||||
if (ratio > 0)
|
||||
{
|
||||
let minTreshold = 1;
|
||||
for (let key in this.template.DamageVariants)
|
||||
{
|
||||
for (let key in this.template.DamageVariants)
|
||||
{
|
||||
let treshold = +this.template.DamageVariants[key];
|
||||
if (treshold < ratio || treshold > minTreshold)
|
||||
if (treshold < ratio || treshold > minTreshold)
|
||||
continue;
|
||||
newDamageVariant = key;
|
||||
minTreshold = treshold;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
else
|
||||
newDamageVariant = "death";
|
||||
|
||||
if (this.damageVariant && this.damageVariant == newDamageVariant)
|
||||
@ -402,10 +402,10 @@ Health.prototype.OnValueModification = function(msg)
|
||||
|
||||
let oldRegenRate = this.regenRate;
|
||||
this.regenRate = ApplyValueModificationsToEntity("Health/RegenRate", +this.template.RegenRate, this.entity);
|
||||
|
||||
|
||||
let oldIdleRegenRate = this.idleRegenRate;
|
||||
this.idleRegenRate = ApplyValueModificationsToEntity("Health/IdleRegenRate", +this.template.IdleRegenRate, this.entity);
|
||||
|
||||
|
||||
if (this.regenRate != oldRegenRate || this.idleRegenRate != oldIdleRegenRate)
|
||||
this.CheckRegenTimer();
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ Market.prototype.Init = function()
|
||||
|
||||
Market.prototype.AddTrader = function(ent)
|
||||
{
|
||||
this.traders.add(ent);
|
||||
this.traders.add(ent);
|
||||
};
|
||||
|
||||
Market.prototype.RemoveTrader = function(ent)
|
||||
|
@ -24,7 +24,7 @@ PlayerManager.prototype.AddPlayer = function(ent)
|
||||
}
|
||||
newDiplo[id] = 1;
|
||||
cmpPlayer.SetDiplomacy(newDiplo);
|
||||
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ PlayerManager.prototype.RemoveAllPlayers = function()
|
||||
|
||||
PlayerManager.prototype.RemoveLastPlayer = function()
|
||||
{
|
||||
if (this.playerEntities.length == 0)
|
||||
if (this.playerEntities.length == 0)
|
||||
return;
|
||||
|
||||
var lastId = this.playerEntities.pop();
|
||||
|
@ -14,15 +14,15 @@ ProductionQueue.prototype.Schema =
|
||||
"<element name='BatchTimeModifier' a:help='Modifier that influences the time benefit for batch training'>" +
|
||||
"<ref name='nonNegativeDecimal'/>" +
|
||||
"</element>" +
|
||||
"<optional>" +
|
||||
"<optional>" +
|
||||
"<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building's four-character civ code'>" +
|
||||
"<attribute name='datatype'>" +
|
||||
"<value>tokens</value>" +
|
||||
"</attribute>" +
|
||||
"<text/>" +
|
||||
"</element>" +
|
||||
"</optional>" +
|
||||
"<optional>" +
|
||||
"</optional>" +
|
||||
"<optional>" +
|
||||
"<element name='Technologies' a:help='Space-separated list of technology names that this building can research.'>" +
|
||||
"<attribute name='datatype'>" +
|
||||
"<value>tokens</value>" +
|
||||
@ -52,7 +52,7 @@ ProductionQueue.prototype.Init = function()
|
||||
// "timeTotal": 15000, // msecs
|
||||
// "timeRemaining": 10000, // msecs
|
||||
// }
|
||||
//
|
||||
//
|
||||
// {
|
||||
// "id": 1,
|
||||
// "player": 1, // who paid for this research; we need this to cope with refunds cleanly
|
||||
@ -321,7 +321,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
|
||||
"timeRemaining": time*1000,
|
||||
});
|
||||
|
||||
// Call the related trigger event
|
||||
// Call the related trigger event
|
||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
||||
cmpTrigger.CallEvent("TrainingQueued", {"playerid": cmpPlayer.GetPlayerID(), "unitTemplate": templateName, "count": count, "metadata": metadata, "trainerEntity": this.entity});
|
||||
}
|
||||
@ -354,7 +354,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
|
||||
if (!cmpPlayer.TrySubtractResources(cost))
|
||||
return;
|
||||
|
||||
// Tell the technology manager that we have started researching this so that people can't research the same
|
||||
// Tell the technology manager that we have started researching this so that people can't research the same
|
||||
// thing twice.
|
||||
var cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
|
||||
cmpTechnologyManager.QueuedResearch(templateName, this.entity);
|
||||
@ -372,7 +372,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
|
||||
"timeRemaining": time*1000,
|
||||
});
|
||||
|
||||
// Call the related trigger event
|
||||
// Call the related trigger event
|
||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
||||
cmpTrigger.CallEvent("ResearchQueued", {"playerid": cmpPlayer.GetPlayerID(), "technologyTemplate": templateName, "researcherEntity": this.entity});
|
||||
}
|
||||
@ -641,7 +641,7 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata)
|
||||
|
||||
if (spawnedEnts.length > 0 && !cmpAutoGarrison)
|
||||
{
|
||||
// If a rally point is set, walk towards it (in formation) using a suitable command based on where the
|
||||
// If a rally point is set, walk towards it (in formation) using a suitable command based on where the
|
||||
// rally point is placed.
|
||||
if (cmpRallyPoint)
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ Promotion.prototype.Promote = function(promotedTemplateName)
|
||||
if (cmpCurrentUnitAI.IsGarrisoned())
|
||||
cmpPromotedUnitAI.SetGarrisoned();
|
||||
if (cmpCurrentUnitPosition.IsInWorld()) // do not cheer if not visibly garrisoned
|
||||
cmpPromotedUnitAI.Cheer();
|
||||
cmpPromotedUnitAI.Cheer();
|
||||
cmpPromotedUnitAI.AddOrders(orders);
|
||||
|
||||
var workOrders = cmpCurrentUnitAI.GetWorkOrders();
|
||||
|
@ -34,7 +34,7 @@ RallyPoint.prototype.GetPositions = function()
|
||||
// Update the rallypoint coordinates if the target is alive
|
||||
if (!this.data[i] || !this.data[i].target || !this.TargetIsAlive(this.data[i].target))
|
||||
continue;
|
||||
|
||||
|
||||
// and visible
|
||||
if (cmpRangeManager && cmpOwnership &&
|
||||
cmpRangeManager.GetLosVisibility(this.data[i].target, cmpOwnership.GetOwner()) != "visible")
|
||||
@ -69,7 +69,7 @@ RallyPoint.prototype.AddData = function(data)
|
||||
};
|
||||
|
||||
// Returns an array with the data associated with this rally point. Each element has the structure:
|
||||
// {"type": "walk/gather/garrison/...", "target": targetEntityId, "resourceType": "tree/fruit/ore/..."} where target
|
||||
// {"type": "walk/gather/garrison/...", "target": targetEntityId, "resourceType": "tree/fruit/ore/..."} where target
|
||||
// and resourceType (specific resource type) are optional, also target may be an invalid entity, check for existence.
|
||||
RallyPoint.prototype.GetData = function()
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user