diff --git a/src/Mods/SecExp/buildings/secBarracks.tw b/src/Mods/SecExp/buildings/secBarracks.tw index 68eafd2d0e995692a2a421a198d873ea577e6c5a..4a2cfd031e97600452b2b4f06ebd196c69968e19 100644 --- a/src/Mods/SecExp/buildings/secBarracks.tw +++ b/src/Mods/SecExp/buildings/secBarracks.tw @@ -154,7 +154,7 @@ Your current maximum number of units is <<print App.SecExp.battle.maxUnits()>> ( <br>Mercenaries are not allowed inside the arcology. You will not be able to recruit mercenary units. <</if>> <div class="tab-bar"> - <<if $arcologyUpgrade.drones == 1>> + <<if $arcologyUpgrade.drones === 1>> <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Bots')" id="tab Bots">Security Drones</button> <</if>> <<if $SecExp.edicts.defense.militia >= 1>> @@ -169,7 +169,7 @@ Your current maximum number of units is <<print App.SecExp.battle.maxUnits()>> ( <div id="Bots" class="tab-content"> <div class="content"> <<set _secBotsCost = 500, _secBotsUpgradeCost = 250>> - <<= App.SecExp.getUnit("bots").describe()>> <br> + <<includeDOM App.SecExp.unit.describe($SecExp.units.bots, "bots")>> <br> <<if $SecExp.units.bots.active == 1>> <<if $SecExp.units.bots.maxTroops > $SecExp.units.bots.troops>> <<link "Replenish the unit" "secBarracks">> @@ -233,7 +233,7 @@ Your current maximum number of units is <<print App.SecExp.battle.maxUnits()>> ( <<set _sL = $SecExp.units.slaves.squads.length>> <<for _i = 0; _i < _sL; _i++>> <<capture _i>> - <<= App.SecExp.getUnit("slaves", _i).describe()>> <br> + <br> <<includeDOM App.SecExp.unit.describe($SecExp.units.slaves.squads[_i], "slaves")>> <br> Rename unit <<textbox "$SecExp.units.slaves.squads[_i].platoonName" $SecExp.units.slaves.squads[_i].platoonName "secBarracks">> | <<link "Disband the unit" "secBarracks">> <<set $menials += $SecExp.units.slaves.squads[_i].troops>> @@ -296,7 +296,7 @@ Your current maximum number of units is <<print App.SecExp.battle.maxUnits()>> ( <<set _mL = $SecExp.units.militia.squads.length>> <<for _i = 0; _i < _mL; _i++>> <<capture _i>> - <<= App.SecExp.getUnit("militia", _i).describe()>> <br> + <br> <<includeDOM App.SecExp.unit.describe($SecExp.units.militia.squads[_i], "militia")>> <br> Rename unit <<textbox "$SecExp.units.militia.squads[_i].platoonName" $SecExp.units.militia.squads[_i].platoonName "secBarracks">> | <<link "Disband the unit" "secBarracks">> <<set $SecExp.units.militia.free += $SecExp.units.militia.squads[_i].troops>> @@ -350,7 +350,7 @@ Your current maximum number of units is <<print App.SecExp.battle.maxUnits()>> ( <<set _meL = $SecExp.units.mercs.squads.length>> <<for _i = 0; _i < _meL; _i++>> <<capture _i>> - <<= App.SecExp.getUnit("mercs", _i).describe()>> <br> + <br> <<includeDOM App.SecExp.unit.describe($SecExp.units.mercs.squads[_i], "mercs")>> <br> Rename unit <<textbox "$SecExp.units.mercs.squads[_i].platoonName" $SecExp.units.mercs.squads[_i].platoonName "secBarracks">> | <<link "Disband the unit" "secBarracks">> <<set $SecExp.units.mercs.free += $SecExp.units.mercs.squads[_i].troops>> diff --git a/src/Mods/SecExp/events/attackOptions.js b/src/Mods/SecExp/events/attackOptions.js index a084ae861fd2ebf389d0135626b371b618d16526..02487d4adcee211b76912029e17e8196db75d984 100644 --- a/src/Mods/SecExp/events/attackOptions.js +++ b/src/Mods/SecExp/events/attackOptions.js @@ -8,6 +8,17 @@ App.Events.attackOptions = class attackOptions extends App.Events.BaseEvent { } execute(node) { + /** Display's the deploy menu for the unit. + * @param {FC.SecExp.PlayerHumanUnitData} [input] the unit to be checked. + * @returns {HTMLDivElement} + */ + const deployMenu = function(input, type) { + let el = document.createElement("div"); + if (input.active === 1 && input.troops > 0) { + App.UI.DOM.appendNewElement("div", el, App.SecExp.unit.describe(input, type, true)); + } + return el; + }; if (typeof V.SecExp.settings.unitDescriptions === "undefined") { V.SecExp.settings.unitDescriptions = 0; } @@ -343,15 +354,10 @@ App.Events.attackOptions = class attackOptions extends App.Events.BaseEvent { const tabBar = new App.UI.Tabs.TabBar("SlaveInteract"); - tabBar.addTab("Bots", "bots", App.SecExp.unit.deployMenu(V.SecExp.units.bots, "bots")); - if (V.SecExp.units.militia.squads.length > 0) { - tabBar.addTab("Militia", "militia", militia()); - } - if (V.SecExp.units.slaves.squads.length > 0) { - tabBar.addTab("Slaves", "slaves", slaves()); - } - if (V.SecExp.units.mercs.squads.length > 0) { - tabBar.addTab("Mercs", "mercs", mercs()); + for (const u of App.SecExp.unit.list()) { + if (u !== 'bots' && V.SecExp.units[u].squads.length > 0 || u === 'bots' && V.SecExp.units[u]) { + tabBar.addTab(capFirstChar(u), u, unitTab(u)); + } } node.append(tabBar.render()); @@ -380,29 +386,13 @@ App.Events.attackOptions = class attackOptions extends App.Events.BaseEvent { return node; - function militia() { - const frag = new DocumentFragment(); - frag.append(toggleLongDesc()); - for (let i = 0; i < V.SecExp.units.militia.squads.length; i++) { - frag.append(App.SecExp.unit.deployMenu(V.SecExp.units.militia.squads[i], "militia", i)); - } - return frag; - } - - function slaves() { + function unitTab(type) { const frag = new DocumentFragment(); frag.append(toggleLongDesc()); - for (let i = 0; i < V.SecExp.units.slaves.squads.length; i++) { - frag.append(App.SecExp.unit.deployMenu(V.SecExp.units.slaves.squads[i], "slaves", i)); - } - return frag; - } - - function mercs() { - const frag = new DocumentFragment(); - frag.append(toggleLongDesc()); - for (let i = 0; i < V.SecExp.units.mercs.squads.length; i++) { - frag.append(App.SecExp.unit.deployMenu(V.SecExp.units.mercs.squads[i], "mercs", i)); + if (type !== 'bots') { + V.SecExp.units[type].squads.forEach(s => frag.append(deployMenu(s, type))); + } else { + frag.append(deployMenu(V.SecExp.units[type], type)); } return frag; } diff --git a/src/Mods/SecExp/js/Unit.js b/src/Mods/SecExp/js/Unit.js index 3cf54a27debaf07c2cfb20024483c6820ad4cc1a..3c2eac9a7659955da1d2790fd7be6bbef1db5ec4 100644 --- a/src/Mods/SecExp/js/Unit.js +++ b/src/Mods/SecExp/js/Unit.js @@ -2,15 +2,14 @@ App.SecExp.unit = (function() { return { list, bulkUpgrade, - fixBroken, gen:generate, - deployMenu, humanUpgradeList, - genID, - replenish, replenishAll, isDeployed, - humanSquads + describe, + humanSquads, + genID, + replenish }; function base(string, operation = 'print', value = 0) { @@ -27,11 +26,11 @@ App.SecExp.unit = (function() { if (operation === 'print') { return target; } else if (operation === 'add') { - target += value; + return target += value; } else if (operation === 'remove') { - target -= value; + return target -= value; } else if (operation === 'set') { - target = value; + return target = value; } else if (operation === 'can upgrade') { if (string === 'bots') { return V.cash >= 500; @@ -48,6 +47,7 @@ App.SecExp.unit = (function() { return ['bots', 'slaves', 'militia', 'mercs']; } + /** Creates a bulk upgrade link for the unit that is passed. * @param {object} [unit] the unit to be checked. */ @@ -71,31 +71,31 @@ App.SecExp.unit = (function() { let cost = 0; const equipUpgradeCost = 250; if (x.maxTroops < 50) { - cost += 5000 + (((50 - x.maxTroops) /10) * equipUpgradeCost * (x.equip + x.commissars + x.cyber + x.SF)); + cost -= 5000 + (((50 - x.maxTroops) /10) * equipUpgradeCost * (x.equip + x.commissars + x.cyber + x.SF)); } if (x.equip < 3) { - cost += (equipUpgradeCost * x.maxTroops + 1000) * (3 - x.equip); + cost -= (equipUpgradeCost * x.maxTroops + 1000) * (3 - x.equip); } if (x.commissars < 2) { - cost += (equipUpgradeCost * x.maxTroops + 1000) * (2 - x.commissars); + cost -= (equipUpgradeCost * x.maxTroops + 1000) * (2 - x.commissars); } if ((V.prostheticsUpgrade >= 2 || V.researchLab.advCombatPLimb === 1) && x.cyber === 0) { - cost += equipUpgradeCost * x.maxTroops + 2000; + cost -= equipUpgradeCost * x.maxTroops + 2000; } if (x.medics === 0) { - cost += equipUpgradeCost * x.maxTroops + 1000; + cost -= equipUpgradeCost * x.maxTroops + 1000; } if (V.SF.Toggle && V.SF.Active >= 1 && x.SF === 0) { - cost += equipUpgradeCost * x.maxTroops + 5000; + cost -= equipUpgradeCost * x.maxTroops + 5000; } - return Math.ceil(cost *= 1.1); + return Math.ceil(cost * 1.1); } const price = unit.map(getCost).reduce((acc, cur) => acc + cur, 0); - if (price > 0) { + if (price !== 0) { el.append(App.UI.DOM.link(`Bulk upgrade for ${cashFormat(price)}`, () => { unit.map(upgradeUnit).reduce((acc, cur) => acc + cur, 0); - cashX(-price, "securityExpansion"); + cashX(price, "securityExpansion"); App.UI.reload(); } )); @@ -103,35 +103,6 @@ App.SecExp.unit = (function() { return el; } - - /** Repairs unit if needed. - * @param {string} [unit] unit type - * @param {object} [squad] the unit to be checked. - */ - function fixBroken(unit, squad) { - squad.SF = squad.SF || 0; - if (!jsDef(squad.ID)) { - squad.ID = genID(); - } - squad.cyber = squad.cyber || 0; - squad.commissars = squad.commissars || 0; - squad.maxTroops = squad.maxTroops || 30; - squad.troops = Math.clamp(squad.troops, 0, squad.maxTroops); - squad.training = Math.clamp(squad.training, 0, 100); - if (V.SF.Active < 1) { - squad.SF = 0; - } - if (squad.platoonName.contains('undefined')) { - if (unit === 'slaves') { - squad.platoonName = squad.platoonName.replace('undefined', 'slave platoon'); - } else if (unit === 'militia') { - squad.platoonName = squad.platoonName.replace('undefined', "citizens' platoon"); - } else if (unit === 'mercs') { - squad.platoonName = squad.platoonName.replace('undefined', 'mercenary platoon'); - } - } - } - /** Creates the requested unit object. * @param {string} [type] the unit type to be created. * @param {object} [updater] previous variables to check against. @@ -181,35 +152,6 @@ App.SecExp.unit = (function() { return newUnit; } - /** Display's the deploy menu for the unit. - * @param {FC.SecExp.PlayerHumanUnitData} input the unit to be checked. - * @param {FC.SecExp.PlayerHumanUnitType} type - */ - function deployMenu(input, type, count = 0) { - let el = document.createElement("div"), options = document.createElement("div"); - const canDeploy = input.isDeployed === 0 && App.SecExp.battle.deployableUnits() > 0; - - if (input.active === 1 && input.troops > 0) { - if (type === "bots") { - $(el).append(App.SecExp.getUnit("bots").describe()); - } else { - $(el).append(App.SecExp.getUnit(type, count).describe()); - } - options = document.createElement("div"); - options.append(App.UI.DOM.link(`${canDeploy ? 'Deploy' : 'Remove'} the unit`, () => { - input.isDeployed = canDeploy ? 1 : 0; - V.SecExp.war.saveValid = 0; - App.UI.reload(); - } - )); - } - el.append(options); - return el; - } - - /** Prints a list of upgrades that can be applied to the passed human unit. - * @param {FC.SecExp.PlayerHumanUnitData} input the human unit to be checked. - */ function humanUpgradeList(input) { const equipUpgradeCost = 250; let el = document.createElement("div"), options = document.createElement("div"); @@ -314,43 +256,6 @@ App.SecExp.unit = (function() { return el; } - /** Generate a unit ID for a new unit - * @returns {number} - */ - function genID() { - return Math.max( - App.SecExp.unit.humanSquads().map(u => u.ID).reduce((acc, cur) => Math.max(acc, cur), 0) - ) + 1; - } - - function replenish(squad, type) { - const oldTroops = squad.troops; - - if (base(type) >= squad.maxTroops - squad.troops) { - if (type === "slaves") { - V.menials -= (squad.maxTroops - squad.troops); - } else if (type === "militia") { - V.SecExp.units.militia.free -= (squad.maxTroops - squad.troops); - } else if (type === "mercs") { - V.SecExp.units.mercs.free -= (squad.maxTroops - squad.troops); - } - squad.troops = squad.maxTroops; - } else { - if (type === "slaves") { - squad.troops += V.menials; - V.menials = 0; - } else if (type === "militia") { - squad.troops += V.SecExp.units.militia.free; - V.SecExp.units.militia.free = 0; - } else if (type === "mercs") { - squad.troops += V.SecExp.units.mercs.free; - V.SecExp.units.mercs.free = 0; - } - } - const expLoss = (squad.troops - oldTroops) / squad.troops; - squad.training -= squad.training * expLoss; - } - function replenishAll() { let el = document.createElement("div"); let woundedUnit = []; @@ -392,6 +297,187 @@ App.SecExp.unit = (function() { return (V.SecExp.war.type.includes("Attack") && unit.isDeployed === 1) || (V.SecExp.war.type.includes("Rebellion") && unit.active === 1 && !V.SecExp.war.rebellingID.includes(unit.ID)); } + /** + * @param {FC.SecExp.PlayerUnitData} input + */ + function describe(input, unitType, inBattle = false) { + const brief = V.SecExp.settings.unitDescriptions; + let el = new DocumentFragment(); + + if (inBattle) { + const canDeploy = input.isDeployed === 0 && App.SecExp.battle.deployableUnits() > 0; + el.append(App.UI.DOM.link(`(${canDeploy ? 'Deploy' : 'Recall'}) `, () => { + input.isDeployed = canDeploy ? 1 : 0; + V.SecExp.war.saveValid = 0; + App.UI.reload(); + } + )); + } + + if (unitType !== "bots") { + App.UI.DOM.appendNewElement("span", el,`${input.platoonName}`, "bold"); + App.UI.DOM.appendNewElement("span", el, `${!brief ? ``:`. `} `); + if (brief === 0) { + if (input.battlesFought > 1) { + el.append(`has participated in ${input.battlesFought} battles and is ready to face the enemy once more at your command. `); + } else if (input.battlesFought === 1) { + el.append(`is ready to face the enemy once more at your command. `); + } else { + el.append(`is ready to face the enemy in battle. `); + } + el.append(`Its ${input.troops} men and women are `); + + if (unitType === "militia") { + el.append(`all proud citizens of your arcology, willing to put their lives on the line to protect their home. `); + } else if (unitType === "slaves") { + el.append(`slaves in your possession, tasked with the protection of their owner and their arcology. `); + } else if (unitType === "mercs") { + el.append(`mercenaries contracted to defend the arcology against external threats. `); + } + } else { + el.append(`Battles fought: ${input.battlesFought}. `); + } + } else { + if (brief === 0) { + App.UI.DOM.appendNewElement("span", el,`The drone unit is made up of ${input.troops} drones. All of which are assembled in an ordered formation in front of you, absolutely silent and ready to receive their orders. `); + } else { + App.UI.DOM.appendNewElement("span", el,`Drone squad. `); + } + } + + if (brief === 0) { + if (input.troops < input.maxTroops) { + el.append(`The unit is not at its full strength of ${input.maxTroops} operatives. `); + } + } else { + el.append(`Unit size: ${input.troops}/${input.maxTroops}. `); + } + + if (brief === 0) { + if (unitType !== "bots") { + if (input.equip === 0) { + el.append(`They are issued with simple, yet effective equipment: firearms, a few explosives and standard uniforms, nothing more. `); + } else if (input.equip === 1) { + el.append(`They are issued with good, modern equipment: firearms, explosives and a few specialized weapons like sniper rifles and machine guns. They also carry simple body armor. `); + } else if (input.equip === 2) { + el.append(`They are issued with excellent, high tech equipment: modern firearms, explosives, specialized weaponry and modern body armor. They are also issued with modern instruments like night vision and portable radars. `); + } else { + el.append(`They are equipped with the best the modern world has to offer: modern firearms, explosives, specialized weaponry, experimental railguns, adaptive body armor and high tech recon equipment. `); + } + } else { + if (input.equip === 0) { + el.append(`They are equipped with light weaponry, mainly anti-riot nonlethal weapons. Not particularly effective in battle. `); + } else if (input.equip === 1) { + el.append(`They are equipped with light firearms, not an overwhelming amount of firepower, but with their mobility good enough to be effective. `); + } else if (input.equip === 2) { + el.append(`They are equipped with powerful, modern firearms and simple armor mounted around their frames. They do not make for a pretty sight, but on the battlefield they are a dangerous weapon. `); + } else { + el.append(`They are equipped with high energy railguns and adaptive armor. They are a formidable force on the battlefield, even for experienced soldiers. `); + } + } + } else { + el.append(`Equipment quality: `); + if (input.equip === 0) { + el.append(`basic. `); + } else if (input.equip === 1) { + el.append(`average. `); + } else if (input.equip === 2) { + el.append(`high. `); + } else { + el.append(`advanced. `); + } + } + + if (unitType !== "bots") { + if (brief === 0) { + if (input.training <= 33) { + el.append(`They lack the experience to be considered professionals, but `); + if (unitType === "militia") { + el.append(`their eagerness to defend the arcology makes up for it. `); + } else if (unitType === "slaves") { + el.append(`their eagerness to prove themselves makes up for it. `); + } else if (unitType === "mercs") { + el.append(`they're trained more than enough to still be an effective unit. `); + } + } else if (input.training <= 66) { + el.append(`They have trained `); + if (input.battlesFought > 0) { + el.append(`and fought `); + } + el.append(`enough to be considered disciplined, professional soldiers, ready to face the battlefield. `); + } else { + el.append(`They are consummate veterans, with a wealth of experience and perfectly trained. On the battlefield they are a well oiled war machine capable of facing pretty much anything. `); + } + + if (input.loyalty < 10) { + el.append(`The unit is extremely disloyal. Careful monitoring of their activities and relationships should be implemented. `); + } else if (input.loyalty < 33) { + el.append(`Their loyalty is low. Careful monitoring of their activities and relationships is advised. `); + } else if (input.loyalty < 66) { + el.append(`Their loyalty is not as high as it can be, but they are not actively working against their arcology owner. `); + } else if (input.loyalty < 90) { + el.append(`Their loyalty is high and strong. The likelihood of this unit betraying the arcology is low to non-existent. `); + } else { + el.append(`The unit is fanatically loyal. They would prefer death over betrayal. `); + } + + if (input.cyber > 0) { + el.append(`The soldiers of the unit have been enhanced with numerous cyberaugmentations which greatly increase their raw power. `); + } + if (input.medics > 0) { + el.append(`The unit has a dedicated squad of medics that will follow them in battle. `); + } + if (V.SF.Toggle && V.SF.Active >= 1 && input.SF > 0) { + el.append(`The unit has "advisors" from ${V.SF.Lower} that will help the squad remain tactically aware and active. `); + } + } else { + App.UI.DOM.appendNewElement("span", el, `Training: `); + if (input.training <= 33) { + el.append(`low. `); + } else if(input.training <= 66) { + el.append(`medium. `); + } else { + el.append(`high. `); + } + + el.append(`Loyalty: `); + if (input.loyalty < 10) { + el.append(`extremely disloyal. `); + } else if (input.loyalty < 33) { + el.append(`low. `); + } else if (input.loyalty < 66) { + el.append(`medium. `); + } else if (input.loyalty < 90) { + el.append(`high. `); + } else { + el.append(`fanatical. `); + } + + if (jsDef(input.cyber) && input.cyber > 0) { + App.UI.DOM.appendNewElement("div", el, `Cyberaugmentations applied. `); + } + if (jsDef(input.medics) && input.medics > 0) { + el.append(`Medical squad attached. `); + } + if (V.SF.Toggle && V.SF.Active >= 1 && jsDef(input.SF) && input.SF > 0) { + el.append(`${capFirstChar(V.SF.Lower || "the special force")} "advisors" attached. `); + } + } + } + + if (!input.active) { + App.UI.DOM.appendNewElement("div", el, `This unit has lost too many operatives `); + if (jsDef(input.battlesFought)) { + el.append(`in the ${input.battlesFought} it fought `); + } + el.append(`and can no longer be considered a unit at all. `); + } + return el; + } + + /** Prints a list of upgrades that can be applied to the passed human unit. + * @param {FC.SecExp.PlayerHumanUnitData} input the human unit to be checked. + */ function humanSquads() { let array = []; for (const unit of list().slice(1)) { @@ -401,11 +487,48 @@ App.SecExp.unit = (function() { } return array; } + + /** Generate a unit ID for a new unit + * @returns {number} + */ + function genID() { + return Math.max( + App.SecExp.unit.humanSquads().map(u => u.ID).reduce((acc, cur) => Math.max(acc, cur), 0) + ) + 1; + } + + function replenish(squad, type) { + const oldTroops = squad.troops; + + if (base(type) >= squad.maxTroops - squad.troops) { + if (type === "slaves") { + V.menials -= (squad.maxTroops - squad.troops); + } else if (type === "militia") { + V.SecExp.units.militia.free -= (squad.maxTroops - squad.troops); + } else if (type === "mercs") { + V.SecExp.units.mercs.free -= (squad.maxTroops - squad.troops); + } + squad.troops = squad.maxTroops; + } else { + if (type === "slaves") { + squad.troops += V.menials; + V.menials = 0; + } else if (type === "militia") { + squad.troops += V.SecExp.units.militia.free; + V.SecExp.units.militia.free = 0; + } else if (type === "mercs") { + squad.troops += V.SecExp.units.mercs.free; + V.SecExp.units.mercs.free = 0; + } + } + const expLoss = (squad.troops - oldTroops) / squad.troops; + squad.training -= squad.training * expLoss; + } })(); /** Player unit factory - get a unit based on its type and index - * @param {PlayerHumanUnitType} type - "Bots", "Militia", "Slaves", "Mercs", or "SF" - * @param {number} [index] - must be supplied if type is not "Bots" + * @param {string} type - "bots", "militia", "slaves", "mercs", or "SF" + * @param {number} [index] - must be supplied if type is not "bots" * @returns {App.SecExp.Unit} */ App.SecExp.getUnit = function(type, index) { @@ -802,12 +925,6 @@ App.SecExp.Unit = class SecExpUnit { throw "derive me"; } - /** @abstract - * @returns {string} */ - describe() { - throw "derive me"; - } - /** @abstract * @returns {string} */ printStats() { @@ -838,10 +955,6 @@ App.SecExp.DroneUnit = class SecExpDroneUnit extends App.SecExp.Unit { return this._baseUnit.hp * this._data.troops; } - describe() { - return App.SecExp.describeUnit(this._data, "Bots"); - } - printStats() { let r = []; r.push(`<br>Security drones base attack: ${this._baseUnit.attack} (After modifiers: ${Math.trunc(this.attack)})`); @@ -886,10 +999,6 @@ App.SecExp.HumanUnit = class SecExpHumanUnit extends App.SecExp.Unit { return singleTroopHp * this._data.troops; } - describe() { - return App.SecExp.describeUnit(this._data, this._descType); - } - printStats() { let r = []; r.push(`<br>${this._descType} base attack: ${this._baseUnit.attack} (After modifiers: ${Math.trunc(this.attack)})`); @@ -999,177 +1108,6 @@ App.SecExp.IrregularUnit = class SecExpEnemyUnit extends App.SecExp.Unit { } }; -App.SecExp.describeUnit = (function() { - return description; - - /** - * @param {FC.SecExp.PlayerUnitData} input - * @param {string} unitType - */ - function description(input, unitType = '') { - let r = ``; const brief = V.SecExp.settings.unitDescriptions; - - if (unitType !== "Bots") { - r += `<br><strong>${input.platoonName}</strong>${!brief ? ``:`. `} `; - if (brief === 0) { - if (input.battlesFought > 1) { - r += `has participated in ${input.battlesFought} battles and is ready to face the enemy once more at your command. `; - } else if (input.battlesFought === 1) { - r += `is ready to face the enemy once more at your command. `; - } else { - r += `is ready to face the enemy in battle. `; - } - r += `<br>Its ${input.troops} men and women are `; - - if (unitType === "Militia") { - r += `all proud citizens of your arcology, willing to put their lives on the line to protect their home. `; - } else if (unitType === "Slaves") { - r += `slaves in your possession, tasked with the protection of their owner and their arcology. `; - } else if (unitType === "Mercs") { - r += `mercenaries contracted to defend the arcology against external threats. `; - } - } else { - r += `Battles fought: ${input.battlesFought}. `; - } - } else { - if (brief === 0) { - r += `<br>The drone unit is made up of ${input.troops} drones. All of which are assembled in an ordered formation in front of you, absolutely silent and ready to receive their orders.`; - } else { - r += `<br>Drone squad.`; - } - } - - if (brief === 0) { - if (input.troops < input.maxTroops) { - r += `The unit is not at its full strength of ${input.maxTroops} operatives. `; - } - } else { - r += `Unit size: ${input.troops}/${input.maxTroops}.`; - } - - if (brief === 0) { - if (unitType !== "Bots") { - if (input.equip === 0) { - r += `They are issued with simple, yet effective equipment: firearms, a few explosives and standard uniforms, nothing more. `; - } else if (input.equip === 1) { - r += `They are issued with good, modern equipment: firearms, explosives and a few specialized weapons like sniper rifles and machine guns. They also carry simple body armor. `; - } else if (input.equip === 2) { - r += `They are issued with excellent, high tech equipment: modern firearms, explosives, specialized weaponry and modern body armor. They are also issued with modern instruments like night vision and portable radars. `; - } else { - r += `They are equipped with the best the modern world has to offer: modern firearms, explosives, specialized weaponry, experimental railguns, adaptive body armor and high tech recon equipment. `; - } - } else { - if (input.equip === 0) { - r += `They are equipped with light weaponry, mainly anti-riot nonlethal weapons. Not particularly effective in battle. `; - } else if (input.equip === 1) { - r += `They are equipped with light firearms, not an overwhelming amount of firepower, but with their mobility good enough to be effective. `; - } else if (input.equip === 2) { - r += `They are equipped with powerful, modern firearms and simple armor mounted around their frames. They do not make for a pretty sight, but on the battlefield they are a dangerous weapon. `; - } else { - r += `They are equipped with high energy railguns and adaptive armor. They are a formidable force on the battlefield, even for experienced soldiers. `; - } - } - } else { - r += `Equipment quality: `; - if (input.equip === 0) { - r += `basic. `; - } else if (input.equip === 1) { - r += `average. `; - } else if (input.equip === 2) { - r += `high. `; - } else { - r += `advanced. `; - } - } - - if (unitType !== "Bots") { - if (brief === 0) { - if (input.training <= 33) { - r += `They lack the experience to be considered professionals, but `; - if (unitType === "Militia") { - r += `their eagerness to defend the arcology makes up for it. `; - } else if (unitType === "Slaves") { - r += `their eagerness to prove themselves makes up for it. `; - } else if (unitType === "Mercs") { - r += `they're trained more than enough to still be an effective unit. `; - } - } else if (input.training <= 66) { - r += `They have trained `; - if (input.battlesFought > 0) { - r += `and fought `; - } - r += `enough to be considered disciplined, professional soldiers, ready to face the battlefield. `; - } else { - r += `They are consummate veterans, with a wealth of experience and perfectly trained. On the battlefield they are a well oiled war machine capable of facing pretty much anything. `; - } - - if (input.loyalty < 10) { - r += `The unit is extremely disloyal. Careful monitoring of their activities and relationships should be implemented. `; - } else if (input.loyalty < 33) { - r += `Their loyalty is low. Careful monitoring of their activities and relationships is advised. `; - } else if (input.loyalty < 66) { - r += `Their loyalty is not as high as it can be, but they are not actively working against their arcology owner. `; - } else if (input.loyalty < 90) { - r += `Their loyalty is high and strong. The likelihood of this unit betraying the arcology is low to non-existent. `; - } else { - r += `The unit is fanatically loyal. They would prefer death over betrayal. `; - } - - if (input.cyber > 0) { - r += `The soldiers of the unit have been enhanced with numerous cyberaugmentations which greatly increase their raw power. `; - } - if (input.medics > 0) { - r += `The unit has a dedicated squad of medics that will follow them in battle. `; - } - if (V.SF.Toggle && V.SF.Active >= 1 && input.SF > 0) { - r += `The unit has "advisors" from ${V.SF.Lower} that will help the squad remain tactically aware and active. `; - } - } else { - r += `\nTraining: `; - if (input.training <= 33) { - r += `low. `; - } else if(input.training <= 66) { - r += `medium. `; - } else { - r += `high. `; - } - - r += `Loyalty: `; - if (input.loyalty < 10) { - r += `extremely disloyal. `; - } else if (input.loyalty < 33) { - r += `low. `; - } else if (input.loyalty < 66) { - r += `medium. `; - } else if (input.loyalty < 90) { - r += `high. `; - } else { - r += `fanatical. `; - } - - if (jsDef(input.cyber) && input.cyber > 0) { - r += `\nCyberaugmentations applied. `; - } - if (jsDef(input.medics) && input.medics > 0) { - r += `Medical squad attached. `; - } - if (V.SF.Toggle && V.SF.Active >= 1 && jsDef(input.SF) && input.SF > 0) { - r += `${capFirstChar(V.SF.Lower || "the special force")} "advisors" attached. `; - } - } - } - - if (!input.active) { - r += `<br>This unit has lost too many operatives `; - if (jsDef(input.battlesFought)) { - r += `in the ${input.battlesFought} it fought `; - } - r += `and can no longer be considered a unit at all.`; - } - return r; - } -})(); - App.SecExp.mercenaryAvgLoyalty = function() { return _.mean(V.SecExp.units.mercs.squads.filter((u) => u.active === 1).map((u) => u.loyalty)); }; diff --git a/src/Mods/SecExp/js/reportingRelatedFunctions.js b/src/Mods/SecExp/js/reportingRelatedFunctions.js index 146c5e9a3f0b622c2639d8229fc02693c6af1a56..2fac243ffa602958b7fa05afc9739e760cf42e07 100644 --- a/src/Mods/SecExp/js/reportingRelatedFunctions.js +++ b/src/Mods/SecExp/js/reportingRelatedFunctions.js @@ -493,25 +493,25 @@ App.SecExp.commanderEffectiveness = function(passage) { defMod += 0.05; tacChance += 0.15; } else if (TotalIntelligence > 15) { - atkMod += 0.5; + atkMod += 0.05; defMod += 0.05; tacChance += 0.10; - } else if (!CareerGivesBonus || TotalIntelligence < -50) { - atkMod -= 0.15; - defMod -= 0.15; - tacChance -= 0.30; - } else if (TotalIntelligence < -50) { - atkMod -= 0.15; - defMod -= 0.10; - tacChance -= 0.25; - } else if (!CareerGivesBonus || TotalIntelligence < -15) { + } else if (!CareerGivesBonus && TotalIntelligence < -15) { atkMod -= 0.10; defMod -= 0.10; - tacChance -= 0.20; + tacChance -= 0.15; } else if (TotalIntelligence < -15) { - atkMod -= 0.10; + atkMod -= 0.05; defMod -= 0.05; - tacChance -= 0.15; + tacChance -= 0.10; + } else if (!CareerGivesBonus && TotalIntelligence < -50) { + atkMod -= 0.35; + defMod -= 0.35; + tacChance -= 0.50; + } else if (TotalIntelligence < -50) { + atkMod -= 0.25; + defMod -= 0.25; + tacChance -= 0.35; } // does she get wounded? if (slave.skill.combat === 1) { @@ -1081,4 +1081,4 @@ App.SecExp.humanLoyaltyChanges = function(input, type) { } return el; -} +}; diff --git a/src/Mods/SecExp/js/secExpBC.js b/src/Mods/SecExp/js/secExpBC.js index 74d5742d1c33c63fb17aa88a28eb58ec3cd75280..573b017f3156e23c2936b8d63f9d921aaeb9f01e 100644 --- a/src/Mods/SecExp/js/secExpBC.js +++ b/src/Mods/SecExp/js/secExpBC.js @@ -41,7 +41,7 @@ App.SecExp.generalBC = function() { V.SecExp.edicts.limitImmigration = V.SecExp.edicts.limitImmigration || V.limitImmigration || 0; V.SecExp.edicts.openBorders = V.SecExp.edicts.openBorders || V.openBorders || 0; V.SecExp.edicts.weaponsLaw = V.weaponsLaw || Math.clamp(V.SecExp.edicts.weaponsLaw, 0, 3) || 3; - + V.SecExp.edicts.defense.soldierWages = V.SecExp.edicts.defense.soldierWages || V.soldierWages || 1; V.SecExp.edicts.defense.slavesOfficers = V.SecExp.edicts.defense.slavesOfficers || V.slavesOfficers || 0; V.SecExp.edicts.defense.discountMercenaries = V.SecExp.edicts.defense.discountMercenaries || V.discountMercenaries || 0; @@ -105,6 +105,35 @@ App.SecExp.generalBC = function() { App.SecExp.unit.gen('mercs', { count: V.createdMercUnits, killed: V.mercTotalCasualties, squads: V.mercUnits, free: V.mercFreeManpower }); + + for (const unit of App.SecExp.unit.list().slice(1)) { + V.SecExp.units[unit].squads.forEach(u => { + u.SF = u.SF || 0; + if (!jsDef(u.ID)) { + u.ID = genID(); + } + u.cyber = u.cyber || 0; + u.commissars = u.commissars || 0; + u.maxTroops = u.maxTroops || 30; + u.troops = Math.clamp(u.troops, 0, u.maxTroops); + u.training = Math.clamp(u.training, 0, 100); + if (V.SF.Active < 1) { + u.SF = 0; + } + + if (u.platoonName.contains('undefined')) { + if (unit === 'slaves') { + u.platoonName = u.platoonName.replace('undefined', 'slave platoon'); + } else if (unit === 'militia') { + u.platoonName = u.platoonName.replace('undefined', "citizens' platoon"); + } else if (unit === 'mercs') { + u.platoonName = u.platoonName.replace('undefined', 'mercenary platoon'); + } + } + u.equip = u.equip || 0; + }); + } + if (V.SecExp.units.mercs.free === 0) { if (V.mercenaries === 1) { V.SecExp.units.mercs.free = 15; @@ -113,12 +142,6 @@ App.SecExp.generalBC = function() { } } - for (const unit of App.SecExp.unit.list().slice(1)) { - for (const squad of V.SecExp.units[unit].squads) { - App.SecExp.unit.fixBroken(unit, squad); - } - } - if (V.SecExp.defaultNames) { V.SecExp.units.slaves.defaultName = V.SecExp.defaultNames.slaves; V.SecExp.units.militia.defaultName = V.SecExp.defaultNames.milita || V.SecExp.defaultNames.militia; diff --git a/src/Mods/SecExp/js/securityReport.js b/src/Mods/SecExp/js/securityReport.js index c7cd4628362f4c7808bf52d9163ad4c9f7a2aafe..bce45e3573f0fb7ec5d3eec59e1c28c8b29e0a22 100644 --- a/src/Mods/SecExp/js/securityReport.js +++ b/src/Mods/SecExp/js/securityReport.js @@ -446,10 +446,8 @@ App.SecExp.securityReport = function() { } if (activeUnits > 0) { // loyalty and training - for (const unit of App.SecExp.unit.list().slice(1)) { - for (const squad of V.SecExp.units[unit].squads) { - r.push(App.SecExp.humanLoyaltyChanges(squad, unit)); - } + for (const squad of App.SecExp.unit.humanSquads()) { + r.push(App.SecExp.humanLoyaltyChanges(squad)); } } } diff --git a/src/gui/options/options.js b/src/gui/options/options.js index edf361c57cbf7d6031da2786d3634674ffdfe74b..d171e8d615c2e562b9ae1d6b7d5b3284907b8e87 100644 --- a/src/gui/options/options.js +++ b/src/gui/options/options.js @@ -435,10 +435,7 @@ App.UI.optionsPassage = function() { ["random", [100]], ]); - for (const squad of App.SecExp.unit.humanSquads()) { - squad.loyalty = numberGenerator(); - } - + App.SecExp.unit.humanSquads().forEach(u => u.loyalty = numberGenerator()); function numberGenerator() { const range = numberMap.get(level); if (range[1]) { diff --git a/src/uncategorized/manageArcology.tw b/src/uncategorized/manageArcology.tw index 643804723487af5c1023bd6bbfa5d5100bf10f7f..6de18cc776189e21fc39e42739a13c24775098de 100644 --- a/src/uncategorized/manageArcology.tw +++ b/src/uncategorized/manageArcology.tw @@ -548,7 +548,7 @@ <<else>> You won <<print num($SecExp.battles.victories)>> of them, while the enemy managed to gain the upper hand in the other <<print num($SecExp.battles.losses)>>. <</if>> - During all battles you lost a total of <<print num(App.SecExp.unit.list().slice(1).reduce((acc, cur) => {return acc + V.SecExp.units[cur].dead;}, 0))>> men, while scoring a total of <<print num($SecExp.core.totalKills)>> kills. + During all battles you lost a total of <<print num(App.SecExp.unit.list().slice(1).reduce((acc, cur) => acc + V.SecExp.units[cur].dead, 0))>> men, while scoring a total of <<print num($SecExp.core.totalKills)>> kills. <</if>> <<if $SecExp.settings.rebellion.enabled === 1 && _countRebellions > 0>> Your arcology was involved in <<print num(_countRebellions)>> rebellions. You won <<print num($SecExp.rebellions.victories)>> of them, while the rebels defeated your forces in <<print num($SecExp.rebellions.losses)>>.