@aaronjewell/w3-build-order
Version:
Library for configuring a build order in Warcraft 3
1,687 lines (1,486 loc) • 138 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['w3-build-order'] = {}));
}(this, (function (exports) { 'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it;
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
var F = function () {};
return {
s: F,
n: function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
},
e: function (e) {
throw e;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
return {
s: function () {
it = o[Symbol.iterator]();
},
n: function () {
var step = it.next();
normalCompletion = step.done;
return step;
},
e: function (e) {
didErr = true;
err = e;
},
f: function () {
try {
if (!normalCompletion && it.return != null) it.return();
} finally {
if (didErr) throw err;
}
}
};
}
var buildings = [{
id: "altarOfStorms",
name: "Altar of Storms",
type: "building",
gold: 180,
lumber: 50,
buildTime: 60,
supply: 0,
dependsOn: [],
order: 6,
units: ["bladeMaster", "farSeer", "shadowHunter", "taurenChieftain"],
upgrades: [],
items: [],
image: "orc/altarofstorms.png"
}, {
id: "barracks",
name: "Barracks",
type: "building",
gold: 180,
lumber: 50,
buildTime: 60,
supply: 0,
dependsOn: [],
order: 2,
units: ["grunt"],
upgrades: ["trollRegeneration", "berserkerUpgrade", "burningOil"],
items: [],
image: "orc/barracks.png"
}, {
id: "beastiary",
name: "Beastiary",
type: "building",
gold: 145,
lumber: 140,
buildTime: 60,
supply: 0,
dependsOn: ["stronghold"],
order: 8,
units: [],
upgrades: ["ensnare", "envenomedSpears", "liquidFire"],
items: [],
image: "orc/beastiary.png"
}, {
id: "greatHall",
name: "Great Hall",
type: "building",
gold: 385,
lumber: 185,
buildTime: 150,
supply: 11,
tier: 1,
dependsOn: [],
order: 1,
units: ["peon"],
upgrades: ["pillage", "unitInventory", "stronghold", "fortress"],
items: [],
image: "orc/greathall.png"
}, {
id: "orcBurrow",
name: "Orc Burrow",
type: "building",
gold: 160,
lumber: 40,
buildTime: 50,
supply: 10,
dependsOn: [],
order: 5,
units: [],
upgrades: [],
items: [],
image: "orc/orcburrow.png"
}, {
id: "spiritLodge",
name: "Spirit Lodge",
type: "building",
gold: 150,
lumber: 135,
buildTime: 70,
supply: 0,
dependsOn: ["stronghold"],
order: 7,
units: [],
upgrades: ["shamanAdeptTraining", "shamanMasterTraining", "witchDoctorAdeptTraining", "witchDoctorMasterTraining"],
items: [],
image: "orc/spiritlodge.png"
}, {
id: "taurenTotem",
name: "Tauren Totem",
type: "building",
gold: 135,
lumber: 155,
buildTime: 70,
supply: 0,
dependsOn: ["warMill", "fortress"],
order: 9,
units: [],
upgrades: ["spiritWalkeAdeptTraining", "spiritWalkerMasterTraining", "pulverizeDamageIncrease"],
items: [],
image: "orc/taurentotem.png"
}, {
id: "voodooLounge",
name: "Voodoo Lounge",
type: "building",
gold: 130,
lumber: 30,
buildTime: 60,
supply: 0,
dependsOn: [],
order: 10,
units: [],
upgrades: [],
items: ["healingSalve", "lesserClarityPotion", "orbOfLightning", "potionOfHealing", "potionOfMana", "scrollOfSpeed", "scrollOfTownPortal", "tinyGreatHall"],
image: "orc/voodoolounge.png"
}, {
id: "warMill",
name: "War Mill",
type: "building",
gold: 205,
lumber: 0,
buildTime: 70,
supply: 0,
dependsOn: [],
order: 3,
units: [],
upgrades: ["spikedBarricades", "improvedSpikedBarricades", "reinforcedDefenses", "steelMeleeWeapons", "thoriumMeleeWeapons", "arcaniteMeleeWeapons", "steelRangedWeapons", "thoriumRangedWeapons", "arcaniteRangedWeapons"],
items: [],
image: "orc/warmill.png"
}, {
id: "watchTower",
name: "Watch Tower",
type: "building",
gold: 110,
lumber: 80,
buildTime: 60,
supply: 0,
dependsOn: ["warMill"],
order: 4,
units: [],
upgrades: [],
items: [],
image: "orc/watchtower.png"
}];
var units = [{
id: "peon",
name: "Peon",
type: "unit",
gold: 75,
lumber: 0,
supply: 1,
buildTime: 15,
canHarvest: true,
canMine: true,
canBuild: true,
order: 1,
image: "orc/peon.png"
}, {
id: "grunt",
name: "Grunt",
type: "unit",
gold: 200,
lumber: 0,
supply: 3,
buildTime: 30,
order: 1,
image: "orc/grunt.png"
}, {
id: "headhunter",
name: "Headhunter",
type: "unit",
gold: 135,
lumber: 20,
supply: 2,
buildTime: 20,
order: 2,
image: "orc/headhunter.png"
}, {
id: "demolisher",
name: "Demolisher",
type: "unit",
gold: 220,
lumber: 50,
supply: 4,
buildTime: 40,
order: 3,
image: "orc/demolisher.png"
}, {
id: "shaman",
name: "Shaman",
type: "unit",
gold: 130,
lumber: 20,
supply: 2,
buildTime: 30,
order: 1,
image: "orc/shaman.png"
}, {
id: "witchDoctor",
name: "Witch Doctor",
type: "unit",
gold: 145,
lumber: 25,
supply: 2,
buildTime: 30,
order: 2,
image: "orc/witchdoctor.png"
}, {
id: "raider",
name: "Raider",
type: "unit",
gold: 180,
lumber: 40,
supply: 3,
buildTime: 28,
order: 1,
image: "orc/wolfrider.png"
}, {
id: "kodoBeast",
name: "Kodo Beast",
type: "unit",
gold: 255,
lumber: 60,
supply: 4,
buildTime: 30,
order: 3,
image: "orc/kodobeast.png"
}, {
id: "windRider",
name: "Wind Rider",
type: "unit",
gold: 265,
lumber: 40,
supply: 4,
buildTime: 35,
order: 2,
image: "orc/wyvernrider.png"
}, {
id: "trollBatrider",
name: "Troll Batrider",
type: "unit",
gold: 160,
lumber: 40,
supply: 2,
buildTime: 28,
orer: 4,
image: "orc/batrider.png"
}, {
id: "tauren",
name: "Tauren",
type: "unit",
gold: 280,
lumber: 80,
supply: 5,
buildTime: 44,
order: 2,
image: "orc/tauren.png"
}, {
id: "bladeMaster",
name: "Blade Master",
type: "unit",
gold: 425,
lumber: 100,
supply: 5,
buildTime: 55,
limit: 1,
isHero: true,
order: 9,
image: "orc/blademaster.png"
}, {
id: "farSeer",
name: "Far Seer",
type: "unit",
gold: 425,
lumber: 100,
supply: 5,
buildTime: 55,
limit: 1,
isHero: true,
order: 10,
image: "orc/farseer.png"
}, {
id: "taurenChieftain",
name: "Tuaren Chieftain",
type: "unit",
gold: 425,
lumber: 100,
supply: 5,
buildTime: 55,
limit: 1,
isHero: true,
order: 11,
image: "orc/chieftain.png"
}, {
id: "shadowHunter",
name: "Shadow Hunter",
type: "unit",
gold: 425,
lumber: 100,
supply: 5,
buildTime: 55,
limit: 1,
isHero: true,
order: 5,
image: "orc/shadowhunter.png"
}];
var Action = /*#__PURE__*/function () {
function Action(_ref) {
var type = _ref.type,
start = _ref.start,
valid = _ref.valid,
duration = _ref.duration,
meta = _ref.meta;
_classCallCheck(this, Action);
this._id = Action._id++;
this.type = type;
this.start = start;
this.valid = valid;
this.duration = duration;
this.meta = meta;
}
_createClass(Action, null, [{
key: "build",
value: function build(start, buildingData, worker) {
return new Action({
type: "build",
start: start,
duration: buildingData.buildTime,
valid: true,
meta: {
worker: worker,
building: buildingData
}
});
}
}, {
key: "buy",
value: function buy(start, itemData, building) {
return new Action({
type: "buy",
start: start,
duration: 0,
valid: true,
meta: {
building: building,
item: itemData
}
});
}
}, {
key: "train",
value: function train(start, unitData, building) {
return new Action({
type: "train",
start: start,
duration: unitData.buildTime || 0,
valid: true,
meta: {
unit: unitData,
building: building
}
});
}
}, {
key: "upgrade",
value: function upgrade(start, upgradeData, building) {
return new Action({
type: "upgrade",
start: start,
duration: upgradeData.buildTime,
valid: true,
meta: {
building: building,
upgrade: upgradeData
}
});
}
}, {
key: "assignToGold",
value: function assignToGold(start, worker) {
return new Action({
type: "assignToGold",
start: start,
duration: 0,
valid: true,
meta: {
worker: worker
}
});
}
}, {
key: "removeFromGold",
value: function removeFromGold(start, worker) {
return new Action({
type: "removeFromGold",
start: start,
duration: 0,
valid: true,
meta: {
worker: worker
}
});
}
}, {
key: "assignToLumber",
value: function assignToLumber(start, worker) {
return new Action({
type: "assignToLumber",
start: start,
duration: 0,
valid: true,
meta: {
worker: worker
}
});
}
}, {
key: "removeFromLumber",
value: function removeFromLumber(start, worker) {
return new Action({
type: "removeFromLumber",
start: start,
duration: 0,
valid: true,
meta: {
worker: worker
}
});
}
}]);
return Action;
}();
_defineProperty(Action, "_id", 1);
var Building = /*#__PURE__*/function () {
function Building(_ref) {
var id = _ref.id,
name = _ref.name,
gold = _ref.gold,
lumber = _ref.lumber,
buildTime = _ref.buildTime,
dependsOn = _ref.dependsOn,
supply = _ref.supply,
type = _ref.type,
units = _ref.units,
upgrades = _ref.upgrades,
items = _ref.items,
image = _ref.image;
_classCallCheck(this, Building);
this._id = Building._id++;
this.id = id;
this.name = name;
this.gold = gold;
this.lumber = lumber;
this.buildTime = buildTime;
this.dependsOn = dependsOn;
this.units = units;
this.upgrades = upgrades;
this.items = items;
this.supply = supply;
this.image = image;
this.type = type;
}
_createClass(Building, null, [{
key: "resetIds",
value: function resetIds() {
Building._id = 1;
}
}]);
return Building;
}();
_defineProperty(Building, "_id", 1);
var Item = /*#__PURE__*/function () {
function Item(_ref) {
var id = _ref.id,
name = _ref.name,
gold = _ref.gold,
lumber = _ref.lumber,
dependsOn = _ref.dependsOn,
order = _ref.order,
type = _ref.type,
image = _ref.image;
_classCallCheck(this, Item);
this._id = Item._id++;
this.id = id;
this.name = name;
this.gold = gold;
this.order = order, this.lumber = lumber;
this.dependsOn = dependsOn;
this.image = image;
this.type = type;
}
_createClass(Item, null, [{
key: "resetIds",
value: function resetIds() {
Item._id = 1;
}
}]);
return Item;
}();
_defineProperty(Item, "_id", 1);
var ResourceList = /*#__PURE__*/function () {
function ResourceList() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, ResourceList);
this.value = value;
}
_createClass(ResourceList, [{
key: "addValues",
value: function addValues(resources) {
var resourceList = resources;
if (!(resourceList instanceof ResourceList)) {
resourceList = new ResourceList(resourceList);
}
for (var _i = 0, _Object$entries = Object.entries(resourceList.value); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
key = _Object$entries$_i[0],
value = _Object$entries$_i[1];
if (key in this.value) {
if (Array.isArray(this.value[key])) {
if (Array.isArray(value)) {
this.value[key] = this.value[key].concat(value);
} else {
this.value[key].push(value);
}
} else {
this.value[key] += value;
}
} else {
this.value[key] = value;
}
}
}
}, {
key: "removeValues",
value: function removeValues(resources) {
var _this = this;
var resourceList = resources;
if (!(resourceList instanceof ResourceList)) {
resourceList = new ResourceList(resourceList);
}
var _loop = function _loop() {
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
key = _Object$entries2$_i[0],
value = _Object$entries2$_i[1];
if (key in _this.value) {
if (Array.isArray(_this.value[key])) {
if (Array.isArray(value)) {
var _iterator = _createForOfIteratorHelper(value),
_step;
try {
var _loop2 = function _loop2() {
var v = _step.value;
var index = _this.value[key].findIndex(function (i) {
return i._id === v._id;
});
_this.value[key].splice(index, 1);
};
for (_iterator.s(); !(_step = _iterator.n()).done;) {
_loop2();
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
} else {
var index = _this.value[key].findIndex(function (i) {
return i._id === value._id;
});
_this.value[key].splice(index, 1);
}
} else {
_this.value[key] -= value;
}
} else {
throw new Error("Unable to lose resource, none accumulated.");
}
};
for (var _i2 = 0, _Object$entries2 = Object.entries(resourceList.value); _i2 < _Object$entries2.length; _i2++) {
_loop();
}
}
}]);
return ResourceList;
}();
var ResourceEvent = /*#__PURE__*/function () {
function ResourceEvent(tick, actionId) {
_classCallCheck(this, ResourceEvent);
_defineProperty(this, "resourceLoss", new ResourceList());
_defineProperty(this, "resourceGain", new ResourceList());
this.actionId = actionId;
this.tick = tick;
}
_createClass(ResourceEvent, [{
key: "loseResources",
value: function loseResources(resourceList) {
var resources = resourceList;
if (!(resourceList instanceof ResourceList)) {
resources = new ResourceList(resources);
}
this.resourceLoss.addValues(resourceList);
}
}, {
key: "gainResources",
value: function gainResources(resourceList) {
var resources = resourceList;
if (!(resourceList instanceof ResourceList)) {
resources = new ResourceList(resources);
}
this.resourceGain.addValues(resourceList);
}
}]);
return ResourceEvent;
}();
var Unit = /*#__PURE__*/function () {
function Unit(_ref) {
var id = _ref.id,
buildTime = _ref.buildTime,
_ref$canBuild = _ref.canBuild,
canBuild = _ref$canBuild === void 0 ? false : _ref$canBuild,
_ref$canHarvest = _ref.canHarvest,
canHarvest = _ref$canHarvest === void 0 ? false : _ref$canHarvest,
_ref$canMine = _ref.canMine,
canMine = _ref$canMine === void 0 ? false : _ref$canMine,
image = _ref.image,
_ref$isHero = _ref.isHero,
isHero = _ref$isHero === void 0 ? false : _ref$isHero,
order = _ref.order,
gold = _ref.gold,
lumber = _ref.lumber,
name = _ref.name,
supply = _ref.supply,
type = _ref.type;
_classCallCheck(this, Unit);
this._id = Unit._id++;
this.id = id;
this.buildTime = buildTime;
this.canBuild = canBuild;
this.canHarvest = canHarvest;
this.canMine = canMine;
this.gold = gold;
this.isHero = isHero;
this.order = order;
this.image = image;
this.lumber = lumber;
this.name = name;
this.supply = supply;
this.type = type;
}
_createClass(Unit, null, [{
key: "resetIds",
value: function resetIds() {
Unit._id = 1;
}
}]);
return Unit;
}();
_defineProperty(Unit, "_id", 1);
var Upgrade = function Upgrade(_ref) {
var id = _ref.id,
name = _ref.name,
gold = _ref.gold,
lumber = _ref.lumber,
buildTime = _ref.buildTime,
tier = _ref.tier,
replaces = _ref.replaces,
dependsOn = _ref.dependsOn,
image = _ref.image;
_classCallCheck(this, Upgrade);
this.id = id;
this.name = name;
this.gold = gold;
this.lumber = lumber;
this.buildTime = buildTime;
this.tier = tier;
this.replaces = replaces;
this.dependsOn = dependsOn;
this.image = image;
};
var EventsProcessor = /*#__PURE__*/function () {
function EventsProcessor() {
_classCallCheck(this, EventsProcessor);
}
_createClass(EventsProcessor, [{
key: "validateActions",
value: function validateActions(actions, resourceList) {
var accumulatedActions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var processedActions = [];
var _iterator = _createForOfIteratorHelper(actions),
_step;
try {
var _loop = function _loop() {
var action = _step.value;
action.valid = true;
action.error = null;
switch (action.type) {
case "build":
// Check for sufficient resources
if (resourceList.value.gold < action.meta.building.gold || resourceList.value.lumber < action.meta.building.lumber) {
action.valid = false;
action.error = "not enough resources";
} // Check if builder still exists
if (!resourceList.value.units.find(function (u) {
return u._id === action.meta.worker._id;
})) {
action.valid = false;
action.error = "worker no longer exists";
}
break;
case "buy":
// Check for sufficient resources
if (resourceList.value.gold < action.meta.item.gold || resourceList.value.lumber < action.meta.item.lumber) {
action.valid = false;
action.error = "not enough resources";
} // Check if shop still exists
if (!resourceList.value.buildings.find(function (b) {
return b._id === action.meta.building._id;
})) {
action.valid = false;
action.error = "shop no longer exists";
} // Check that we have the dependencies
if (typeof action.meta.item.dependsOn !== "undefined" && !action.meta.item.dependsOn.every(function (dependency) {
return resourceList.value.upgrades.some(function (completed) {
return completed.id === dependency;
});
})) {
action.valid = false;
action.error = "missing required upgrade";
} // Check that we haven't exceeded replenishment
if ([].concat(_toConsumableArray(accumulatedActions), processedActions).filter(function (a) {
return a.type === "buy" && a.meta.item.id === action.meta.item.id && action.start - a.start < action.meta.item.replenish;
}).length >= action.meta.item.max) {
action.valid = false;
action.error = "exceeded item replenishment";
}
break;
case "train":
if (resourceList.value.gold < action.meta.unit.gold || resourceList.value.lumber < action.meta.unit.lumber || resourceList.value.supply < action.meta.unit.supply) {
action.valid = false;
action.error = "not enough resources";
}
if (action.meta.unit.type !== "neutralUnit" && !resourceList.value.buildings.find(function (b) {
return b._id === action.meta.building._id && b.id === action.meta.building.id;
})) {
action.valid = false;
action.error = "building no longer available for training";
}
if (action.meta.unit.type !== "neutralUnit" && processedActions.filter(function (a) {
return a.type === "train" && a.meta.building._id === action.meta.building._id && a.start + a.duration >= action.start && a.start + a.duration <= action.start + action.duration;
}).length) {
action.valid = false;
action.error = "building is busy training";
}
if (action.meta.unit.limit && action.meta.unit.limit <= processedActions.filter(function (a) {
return a.type === "train" && a.meta.unit.id === action.meta.unit.id;
}).length) {
action.valid = false;
action.error = "too many of this unit produced";
} // Check that we haven't exceeded replenishment
if ([].concat(_toConsumableArray(accumulatedActions), processedActions).filter(function (a) {
return a.type === "train" && a.meta.unit.id === action.meta.unit.id && action.start - a.start < action.meta.unit.replenish;
}).length >= action.meta.unit.max) {
action.valid = false;
action.error = "exceeded unit replenishment";
}
if (action.meta.unit.availability && action.meta.unit.limit < a.start) {
action.valid = false;
action.error = "unit being produced before available";
}
break;
case "assignToGold":
if (!resourceList.value.units.find(function (u) {
return u._id === action.meta.worker._id && u.id === action.meta.worker.id;
})) {
action.valid = false;
action.error = "worker no longer available for mining";
}
break;
case "removeFromGold":
if (!resourceList.value.miningWorkers.find(function (u) {
return u._id === action.meta.worker._id && u.id === action.meta.worker.id;
})) {
action.valid = false;
action.error = "worker no longer mining at this time";
}
break;
case "assignToLumber":
if (!resourceList.value.units.find(function (u) {
return u._id === action.meta.worker._id && u.id === action.meta.worker.id;
})) {
action.valid = false;
action.error = "worker no longer available for harvesting";
}
break;
case "removeFromLumber":
if (!resourceList.value.harvestingWorkers.find(function (u) {
return u._id === action.meta.worker._id && u.id === action.meta.worker.id;
})) {
action.valid = false;
action.error = "worker no longer harvesting at this time";
}
break;
case "upgrade":
if (resourceList.value.gold < action.meta.upgrade.gold || resourceList.value.lumber < action.meta.upgrade.lumber) {
action.valid = false;
action.error = "not enough resources for upgrade";
}
if (!action.meta.upgrade.dependsOn.buildings.every(function (dependency) {
return resourceList.value.buildings.some(function (completed) {
return completed.id === dependency;
});
}) || !action.meta.upgrade.dependsOn.upgrades.every(function (dependency) {
return resourceList.value.upgrades.some(function (completed) {
return completed.id === dependency;
});
})) {
action.valid = false;
action.error = "missing required building or upgrade";
}
if (!!resourceList.value.upgrades.find(function (u) {
return u.id === action.meta.upgrade.id;
})) {
action.valid = false;
action.error = "upgrade already researched";
}
if (action.meta.upgrade.replaces && !resourceList.value.upgrades.find(function (u) {
return u.id === action.meta.upgrade.replaces;
})) {
action.valid = false;
action.error = "missing earlier version of upgrade";
}
}
processedActions.push(action);
};
for (_iterator.s(); !(_step = _iterator.n()).done;) {
_loop();
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
}, {
key: "processAction",
value: function processAction(action) {
var _immediateLoss$loseRe;
var resourceEvents = [];
switch (action.type) {
case "build":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
gold: action.meta.building.gold,
lumber: action.meta.building.lumber,
units: [action.meta.worker]
});
var futureGain = new ResourceEvent(action.start + action.duration, action._id);
futureGain.gainResources({
supply: action.meta.building.supply,
buildings: [new Building(action.meta.building)],
units: [action.meta.worker]
});
resourceEvents.push(immediateLoss, futureGain);
break;
case "buy":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
gold: action.meta.item.gold,
lumber: action.meta.item.lumber || 0 // Neutral items do not cost lumber
});
var immediateGain = new ResourceEvent(action.start + action.duration, action._id);
immediateGain.gainResources({
items: [new Item(action.meta.item)]
});
resourceEvents.push(immediateLoss, immediateGain);
break;
case "train":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources((_immediateLoss$loseRe = {
supply: action.meta.unit.supply,
gold: action.meta.unit.gold,
lumber: action.meta.unit.lumber
}, _defineProperty(_immediateLoss$loseRe, "supply", action.meta.unit.supply), _defineProperty(_immediateLoss$loseRe, "buildings", [action.meta.building]), _immediateLoss$loseRe));
var futureGain = new ResourceEvent(action.start + action.duration, action._id);
futureGain.gainResources({
units: [new Unit(action.meta.unit)],
buildings: [action.meta.building]
});
resourceEvents.push(immediateLoss, futureGain);
break;
case "assignToGold":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
units: [action.meta.worker]
});
var immediateGain = new ResourceEvent(action.start, action._id);
immediateGain.gainResources({
miningWorkers: [action.meta.worker]
});
resourceEvents.push(immediateGain, immediateLoss);
break;
case "removeFromGold":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
miningWorkers: [action.meta.worker]
});
var immediateGain = new ResourceEvent(action.start, action._id);
immediateGain.gainResources({
units: [action.meta.worker]
});
resourceEvents.push(immediateGain, immediateLoss);
break;
case "assignToLumber":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
units: [action.meta.worker]
});
var immediateGain = new ResourceEvent(action.start, action._id);
immediateGain.gainResources({
harvestingWorkers: [action.meta.worker]
});
resourceEvents.push(immediateGain, immediateLoss);
break;
case "removeFromLumber":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
harvestingWorkers: [action.meta.worker]
});
var immediateGain = new ResourceEvent(action.start, action._id);
immediateGain.gainResources({
units: [action.meta.worker]
});
resourceEvents.push(immediateGain, immediateLoss);
break;
case "upgrade":
var immediateLoss = new ResourceEvent(action.start, action._id);
immediateLoss.loseResources({
buildings: [action.meta.building],
gold: action.meta.upgrade.gold,
lumber: action.meta.upgrade.lumber
});
var futureGain = new ResourceEvent(action.start + action.duration, action._id);
futureGain.gainResources({
upgrades: [new Upgrade(action.meta.upgrade)],
buildings: [action.meta.building]
});
resourceEvents.push(immediateLoss, futureGain);
break;
}
return resourceEvents;
}
}]);
return EventsProcessor;
}();
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
/**
* lodash (Custom Build) <https://lodash.com/>
* Build: `lodash modularize exports="npm" -o ./`
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
var lodash_clonedeep = createCommonjsModule(function (module, exports) {
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;
/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';
/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;
/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
boolTag = '[object Boolean]',
dateTag = '[object Date]',
errorTag = '[object Error]',
funcTag = '[object Function]',
genTag = '[object GeneratorFunction]',
mapTag = '[object Map]',
numberTag = '[object Number]',
objectTag = '[object Object]',
promiseTag = '[object Promise]',
regexpTag = '[object RegExp]',
setTag = '[object Set]',
stringTag = '[object String]',
symbolTag = '[object Symbol]',
weakMapTag = '[object WeakMap]';
var arrayBufferTag = '[object ArrayBuffer]',
dataViewTag = '[object DataView]',
float32Tag = '[object Float32Array]',
float64Tag = '[object Float64Array]',
int8Tag = '[object Int8Array]',
int16Tag = '[object Int16Array]',
int32Tag = '[object Int32Array]',
uint8Tag = '[object Uint8Array]',
uint8ClampedTag = '[object Uint8ClampedArray]',
uint16Tag = '[object Uint16Array]',
uint32Tag = '[object Uint32Array]';
/**
* Used to match `RegExp`
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
*/
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
/** Used to match `RegExp` flags from their coerced string values. */
var reFlags = /\w*$/;
/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;
/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;
/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags = {};
cloneableTags[argsTag] = cloneableTags[arrayTag] =
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
cloneableTags[boolTag] = cloneableTags[dateTag] =
cloneableTags[float32Tag] = cloneableTags[float64Tag] =
cloneableTags[int8Tag] = cloneableTags[int16Tag] =
cloneableTags[int32Tag] = cloneableTags[mapTag] =
cloneableTags[numberTag] = cloneableTags[objectTag] =
cloneableTags[regexpTag] = cloneableTags[setTag] =
cloneableTags[stringTag] = cloneableTags[symbolTag] =
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
cloneableTags[errorTag] = cloneableTags[funcTag] =
cloneableTags[weakMapTag] = false;
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Detect free variable `exports`. */
var freeExports = exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;
/**
* Adds the key-value `pair` to `map`.
*
* @private
* @param {Object} map The map to modify.
* @param {Array} pair The key-value pair to add.
* @returns {Object} Returns `map`.
*/
function addMapEntry(map, pair) {
// Don't return `map.set` because it's not chainable in IE 11.
map.set(pair[0], pair[1]);
return map;
}
/**
* Adds `value` to `set`.
*
* @private
* @param {Object} set The set to modify.
* @param {*} value The value to add.
* @returns {Object} Returns `set`.
*/
function addSetEntry(set, value) {
// Don't return `set.add` because it's not chainable in IE 11.
set.add(value);
return set;
}
/**
* A specialized version of `_.forEach` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEach(array, iteratee) {
var index = -1,
length = array ? array.length : 0;
while (++index < length) {
if (iteratee(array[index], index, array) === false) {
break;
}
}
return array;
}
/**
* Appends the elements of `values` to `array`.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to append.
* @returns {Array} Returns `array`.
*/
function arrayPush(array, values) {
var index = -1,
length = values.length,
offset = array.length;
while (++index < length) {
array[offset + index] = values[index];
}
return array;
}
/**
* A specialized version of `_.reduce` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @param {boolean} [initAccum] Specify using the first element of `array` as
* the initial value.
* @returns {*} Returns the accumulated value.
*/
function arrayReduce(array, iteratee, accumulator, initAccum) {
var index = -1,
length = array ? array.length : 0;
if (initAccum && length) {
accumulator = array[++index];
}
while (++index < length) {
accumulator = iteratee(accumulator, array[index], index, array);
}
return accumulator;
}
/**
* The base implementation of `_.times` without support for iteratee shorthands
* or max array length checks.
*
* @private
* @param {number} n The number of times to invoke `iteratee`.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns the array of results.
*/
function baseTimes(n, iteratee) {
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
/**
* Gets the value at `key` of `object`.
*
* @private
* @param {Object} [object] The object to query.
* @param {string} key The key of the property to get.
* @returns {*} Returns the property value.
*/
function getValue(object, key) {
return object == null ? undefined : object[key];
}
/**
* Checks if `value` is a host object in IE < 9.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a host object, else `false`.
*/
function isHostObject(value) {
// Many host objects are `Object` objects that can coerce to strings
// despite having improperly defined `toString` methods.
var result = false;
if (value != null && typeof value.toString != 'function') {
try {
result = !!(value + '');
} catch (e) {}
}
return result;
}
/**
* Converts `map` to its key-value pairs.
*
* @private
* @param {Object} map The map to convert.
* @returns {Array} Returns the key-value pairs.
*/
function mapToArray(map) {
var index = -1,
result = Array(map.size);
map.forEach(function(value, key) {
result[++index] = [key, value];
});
return result;
}
/**
* Creates a unary function that invokes `func` with its argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg(func, transform) {
return function(arg) {
return func(transform(arg));
};
}
/**
* Converts `set` to an array of its values.
*
* @private
* @param {Object} set The set to convert.
* @returns {Array} Returns the values.
*/
function setToArray(set) {
var index = -1,
result = Array(set.size);
set.forEach(function(value) {
result[++index] = value;
});
return result;
}
/** Used for built-in method references. */
var arrayProto = Array.prototype,
funcProto = Function.prototype,
objectProto = Object.prototype;
/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];
/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
return uid ? ('Symbol(src)_1.' + uid) : '';
}());
/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var objectToString = objectProto.toString;
/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
Symbol = root.Symbol,
Uint8Array = root.Uint8Array,
getPrototype = overArg(Object.getPrototypeOf, Object),
objectCreate = Object.create,
propertyIsEnumerable = objectProto.propertyIsEnumerable,
splice = arrayProto.splice;
/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols,
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
nativeKeys