UNPKG

ggejs

Version:

A powerful JavaScript library for interacting with the server of Goodgame Empire: Four Kingdoms

438 lines (437 loc) 15.8 kB
const flankBonus = [0, 0.7, 1, 1.3]; const waveUnlockLevels = [0, 13, 26, 51]; const wallWodIdsVillages = [503, 504, 505]; const gateWodIdsVillages = [452, 453, 469]; const unitSlotFlankUnlockLevels = [0, 13]; const toolSlotFlankUnlockLevels = [0, 37]; const unitSlotFrontUnlockLevels = [0, 0, 26]; const toolSlotFrontUnlockLevels = [0, 11, 37]; /** * @param {boolean} defeatedLWall * @param {boolean} defeatedMWall * @param {boolean} defeatedRWall * @returns {number} */ module.exports.getFlankBonus = function (defeatedLWall = false, defeatedMWall = false, defeatedRWall = false) { return flankBonus[(defeatedLWall ? 1 : 0) + (defeatedMWall ? 1 : 0) + (defeatedRWall ? 1 : 0)]; } /** * @param {number} side * @param {number} defenderLevel * @param {number} flankBonus * @param {number} frontBonus * @returns {number} */ module.exports.getAmountSoldiers = function (side, defenderLevel, flankBonus = 0, frontBonus = 0) { return side === 1 ? module.exports.getAmountSoldiersMiddle(defenderLevel, frontBonus) : module.exports.getAmountSoldiersFlank(defenderLevel, flankBonus); } /** * @param {number} defenderLevel * @param {number} flankBonus * @returns {number} */ module.exports.getAmountSoldiersFlank = function (defenderLevel, flankBonus = 0) { return Math.ceil(module.exports.getMaxAttackers(defenderLevel) * 0.2 * (1 + flankBonus / 100)); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getAmountSoldiersFlankWithoutBonus = function (defenderLevel) { return Math.ceil(module.exports.getMaxAttackers(defenderLevel) * 0.2); } /** * @param {number} defenderLevel * @param {number} frontBonus * @returns {number} */ module.exports.getAmountSoldiersMiddle = function (defenderLevel, frontBonus = 0) { return Math.ceil((module.exports.getMaxAttackers(defenderLevel) - module.exports.getAmountSoldiersFlankWithoutBonus(defenderLevel) * 2) * (1 + frontBonus / 100)); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getMinSoldiers = function (defenderLevel) { return Math.floor(module.exports.getMaxAttackers(defenderLevel) * 0.1); } /** * @param {number} level * @returns {number} */ module.exports.getMaxDamagedBuildings = function (level) { return Math.round(0.179 * Math.exp((level - 4) * 0.199)); } /** * @param {number} defenderLevel * @param {number} toolFlankBonus * @returns {number} */ module.exports.getTotalAmountToolsFlank = function (defenderLevel, toolFlankBonus = 0) { return module.exports.getTotalAmountTools(0, defenderLevel, toolFlankBonus); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getTotalAmountToolsMiddle = function (defenderLevel) { return module.exports.getTotalAmountTools(1, defenderLevel, 0); } /** * @param {number} side * @param {number} defenderLevel * @param {number} toolFlankBonus * @returns {number} */ module.exports.getTotalAmountTools = function (side, defenderLevel, toolFlankBonus = 0) { if (side === 1) { if (defenderLevel < 11) return 10; if (defenderLevel < 37) return 20; if (defenderLevel < 50) return 30; if (defenderLevel < 69) return 40; return 50; } if (defenderLevel < 37) return 10; if (defenderLevel < 50) return 20; if (defenderLevel < 69) return 30; return Math.ceil(40 + toolFlankBonus); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getMaxAttackers = function (defenderLevel) { if (defenderLevel <= 69) return Math.min(260, 5 * defenderLevel + 8); return 320; } /** * @param {number} attackerCumulatedLevel * @param {number} defenderLevel * @param {number} effectBonus * @param {number} effectModifier * @returns {number} */ module.exports.getMaxUnitsInReinforcementWave = function (attackerCumulatedLevel, defenderLevel, effectBonus, effectModifier) { const maxUnits = Math.sqrt(attackerCumulatedLevel) * 20 + 50 + defenderLevel * 20 + effectBonus; return Math.round(maxUnits * effectModifier); } /** * @param {number} attackerLevel * @returns {number} */ module.exports.getMaxLevelDif1 = function (attackerLevel) { return Math.max(5, Math.round(0.002 * attackerLevel * attackerLevel + 0.17 * attackerLevel + 3)); } /** * @param {number} attackerLevel * @returns {number} */ module.exports.getMaxLevelDif2 = function (attackerLevel) { return Math.max(5, Math.round(0.0015 * attackerLevel * attackerLevel + 0.12 * attackerLevel + 3)); } /** * @param {number} attackerHonor * @param {number} defenderHonor * @param {number} attackerLevel * @param {number} defenderLevel * @param {boolean} attackerWon * @returns {number} */ module.exports.getHonorChange = function (attackerHonor, defenderHonor, attackerLevel, defenderLevel, attackerWon) { let winnerHonor = 0; let loserHonor = 0; if (attackerLevel > defenderLevel + module.exports.getMaxLevelDif2(attackerLevel)) { if (attackerLevel > defenderLevel + module.exports.getMaxLevelDif1(attackerLevel)) { return (defenderLevel - attackerLevel) * 3; } return 0; } if (!attackerWon) { winnerHonor = defenderHonor; loserHonor = attackerHonor; } else { winnerHonor = attackerHonor; loserHonor = defenderHonor; } return Math.round(Math.max((loserHonor - winnerHonor) / 7 + 100, 0)); } /** * @param {number} attackerHonor * @param {number} defenderHonor * @param {number} attackerLevel * @param {number} defenderLevel * @param {number} titleBoost * @param {number} researchHonorBoost * @param {number} attackerHonorBoost * @param {boolean} attackerWon * @returns {number} */ module.exports.getHonorChangeWithBoost = function (attackerHonor, defenderHonor, attackerLevel, defenderLevel, titleBoost, researchHonorBoost, attackerHonorBoost, attackerWon) { return Math.round(module.exports.getHonorChange(attackerHonor, defenderHonor, attackerLevel, defenderLevel, attackerWon) * (1 + (attackerHonorBoost + researchHonorBoost + titleBoost) / 100)); } /** * @param {number} moral * @returns {number} */ module.exports.getMoralBonus = function (moral) { return moral >= 0 ? 2 - 1 / (1 + Math.abs(moral) / 250) : 1 / (1 + Math.abs(moral) / 250); } /** * @param {number} honorOfPlayer * @returns {number} */ module.exports.getFameBonusForHonor = function (honorOfPlayer) { if (honorOfPlayer === 0) return 0; return Math.min(1, (2 * Math.exp(0.00115 * honorOfPlayer) + (0.012 * honorOfPlayer + 1)) / 100); } /** * @param {number} level * @param {boolean} conquerAttack * @returns {number} */ module.exports.getMaxWaveCount = function (level, conquerAttack = false) { const waveCount = getUnlockCountByLevel(waveUnlockLevels, level); return conquerAttack ? waveCount + 2 : waveCount; } /** * @param {number} level * @param {boolean} conquerAttack * @param {number} additionalWaves * @returns {number} */ module.exports.getMaxWaveCountWithBonus = function (level, conquerAttack = false, additionalWaves = 0) { return module.exports.getMaxWaveCount(level, conquerAttack) + additionalWaves; } /** * @param {AttackType} attackType * @returns {boolean} */ module.exports.isConquerAttack = function (attackType) { switch (attackType - 1) { case 0: case 1: case 2: case 4: case 5: case 6: case 7: case 8: return true; default: return false; } } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getSurvivingDefenderRate = function (defenderLevel) { return Math.max(0.1, (-0.25 * defenderLevel * defenderLevel + 104) / 100); } /** * @param {number}dungeonLevel * @returns {number} */ module.exports.getXpForAttackingDungeon = function (dungeonLevel) { return Math.round(Math.max(1, Math.pow(0.5 * dungeonLevel, 1.1))); } /** * @param {number} amountOfKilledEnemyUnits * @param {number} amountOfKilledPeasants * @returns {number} */ module.exports.getXpForPlayerBattle = function (amountOfKilledEnemyUnits, amountOfKilledPeasants) { return Math.round(Math.max(1, 0.05 * amountOfKilledEnemyUnits + 0.005 * amountOfKilledPeasants)); } /** * @param {number} attackerLevel * @param defenderLevel * @returns {boolean} * @private */ isTargetLowLevelProtected = function (attackerLevel, defenderLevel) { if (defenderLevel <= 10) return attackerLevel > defenderLevel + 5; return false; } /** * @param {number} attackerLevel * @param {number} defenderLevel * @param {number} defenderPlayerId * @returns {boolean} */ module.exports.isLowLevelProtectionActive = function (attackerLevel, defenderLevel, defenderPlayerId) { return isTargetLowLevelProtected(attackerLevel, defenderLevel) && defenderPlayerId > -1; } /** * @param {number} attackerLevel * @returns {number} */ module.exports.getMinTargetLevelForFindEnemyCastle = function (attackerLevel) { return Math.max(5, attackerLevel - Math.max(5, Math.round(0.002 * attackerLevel * attackerLevel + 0.17 * attackerLevel + 3)) + 1); } /** * @param {number} attackerLevel * @returns {number} */ module.exports.getMaxTargetLevelForFindEnemyCastle = function (attackerLevel) { return Math.round(attackerLevel * 1.3); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getMaxUnitCountWallByLevelForVillages = function (defenderLevel) { if (defenderLevel >= 70) return 320; if (defenderLevel >= 51) return 260; return 200; } /** * @param {number} defenderLevel * @param {boolean} isWall * @returns {number} */ module.exports.getWallOrGateWodIdForVillages = function (defenderLevel, isWall) { if (defenderLevel >= 69) { if (isWall) return wallWodIdsVillages[2]; return gateWodIdsVillages[2]; } if (defenderLevel >= 50) { if (isWall) return wallWodIdsVillages[1]; return gateWodIdsVillages[1]; } if (isWall) return wallWodIdsVillages[0]; return gateWodIdsVillages[0]; } /** * @param {number} buildingBonus * @param {number} defenderToolsBonus * @param {number} defenderBaronBonus * @param {number} defenderSkillBonus * @param {number} attackerToolsBonus * @param {number} attackerLordBonus * @param {number} attackerSkillBonus * @returns {number} */ module.exports.getDefenseBonus = function (buildingBonus, defenderToolsBonus, defenderBaronBonus, defenderSkillBonus, attackerToolsBonus, attackerLordBonus, attackerSkillBonus) { return 1 + Math.max(0, buildingBonus + defenderToolsBonus + defenderBaronBonus + defenderSkillBonus - attackerLordBonus - attackerToolsBonus - attackerSkillBonus) / 100; } /** * @param {number} defWall * @param {number} defGate * @param {number} defMoat * @returns {number} */ module.exports.getTotalDefenseBonus = function (defWall, defGate, defMoat) { return defWall * defGate * defMoat; } /** * @param {number} moralBonus * @param {number} islandTitleBonus * @param {number} highestFameTitleBonus * @param {number} allianceAttackStrengthBuffBonus * @param {number} kingstowerBonus * @returns {number} */ module.exports.getAttackBonus = function (moralBonus, islandTitleBonus, highestFameTitleBonus, allianceAttackStrengthBuffBonus, kingstowerBonus) { return moralBonus + islandTitleBonus + highestFameTitleBonus + allianceAttackStrengthBuffBonus + kingstowerBonus; } /** * @param {number} flankFactor * @param {number} attackBonus * @param {number} attackerGemBonus * @param {number} attackerSkillBonus * @param {number} attackerLordTypeBonus * @param {number} attackerLordOffensiveTypeBonus * @param {number} attackerLordAttackBonus * @param {number} attackerLordYardBonus * @param {number} attackerSkillTypeBonus * @param {number} offTypeToolsBonus * @returns {number} */ module.exports.getAttackTypeSpecificBonus = function (flankFactor, attackBonus, attackerGemBonus, attackerSkillBonus, attackerLordTypeBonus, attackerLordOffensiveTypeBonus, attackerLordAttackBonus, attackerLordYardBonus, attackerSkillTypeBonus, offTypeToolsBonus) { return flankFactor * (attackBonus + attackerGemBonus + attackerSkillBonus + Math.max(-1, (attackerLordTypeBonus + attackerLordOffensiveTypeBonus + attackerLordAttackBonus + attackerLordYardBonus + attackerSkillTypeBonus) / 100) + offTypeToolsBonus); } /** * @param {number} defFactor * @param {number} defMoral * @param {number} defenderGemBonus * @param {number} defenderSkillBonus * @param {number} defenderLordTypeBonus * @param {number} defenderAllianceBuff * @param {number} defenderLordDefenseBonus * @param {number} defenderLordYardBonus * @param {number} defenderSkillTypeBonus * @param {number} defTypeToolsBonus * @returns {number} */ module.exports.getDefenseTotalTypeSpecificBonus = function (defFactor, defMoral, defenderGemBonus, defenderSkillBonus, defenderLordTypeBonus, defenderAllianceBuff, defenderLordDefenseBonus, defenderLordYardBonus, defenderSkillTypeBonus, defTypeToolsBonus) { return defFactor * (defMoral + defenderGemBonus + defenderSkillBonus) * (1 + Math.max(-1, (defenderLordTypeBonus + defenderAllianceBuff + defenderLordDefenseBonus + defenderLordYardBonus + defenderSkillTypeBonus) / 100 + defTypeToolsBonus)); } /** * @param {number} attMelee * @param {number} attRange * @param {number} defMelee * @param {number} defRange * @returns {[number,number]} */ module.exports.getDefenseValues = function (attMelee, attRange, defMelee, defRange) { const attTotal = attMelee + attRange; const meleePerc = attTotal !== 0 ? attMelee / attTotal : 0.5; const rangePerc = 1 - meleePerc; if (attMelee < defMelee * meleePerc && attRange > defRange * rangePerc) { defRange = Math.round((1 - attMelee / defMelee) * defRange); defMelee = attMelee; } else if (attMelee > defMelee * meleePerc && attRange < defRange * rangePerc) { defMelee = Math.round((1 - attRange / defRange) * defMelee); defRange = attRange; } else { defMelee = Math.round(defMelee * meleePerc); defRange = Math.round(defRange * rangePerc); } return [defMelee, defRange]; } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getUnitSlotCountFlank = function (defenderLevel) { return getUnlockCountByLevel(unitSlotFlankUnlockLevels, defenderLevel); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getToolSlotCountFlank = function (defenderLevel) { return getUnlockCountByLevel(toolSlotFlankUnlockLevels, defenderLevel); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getUnitSlotCountFront = function (defenderLevel) { return getUnlockCountByLevel(unitSlotFrontUnlockLevels, defenderLevel); } /** * @param {number} defenderLevel * @returns {number} */ module.exports.getToolSlotCountFront = function (defenderLevel) { return getUnlockCountByLevel(toolSlotFrontUnlockLevels, defenderLevel); } /** * @param {number[]} array * @param {number} level * @returns {number} */ getUnlockCountByLevel = function (array, level) { let unlockCount = 1; let index = array.length - 1; while (index >= 0) { if (level >= array[index]) { unlockCount = index + 1; break; } index--; } return unlockCount; }