ggejs
Version:
A powerful Node.js module for interacting with the server of Goodgame Empire & Goodgame Empire: Four Kingdoms
317 lines (296 loc) • 12 kB
JavaScript
const BASIC_FIELD_TRAVEL_TIME = 600;
const GUESS_SIZE_PRECISION = 3;
const DEFAULT_SIGHT_RADIUS = 6;
const INNER_CIRCLE_DIVISOR = 2;
const TRAVEL_PREMIUM_COMMANDER_COSTS_C2 = 125;
const KINGDOM_TOOL_TRAVEL_COST_C1 = 100;
const TRAVEL_BOOST_TUTORIAL = 80;
const MAX_FALLBACK_TIME = 600;
const BARON_SPEED = 2;
const CAPITAL_CONQUER_SPEED = 5;
const CAPITAL_CONQUER_MIN_ATTACK_DISTANCE = 6;
const CAPITAL_CONQUER_MAX_ATTACK_DISTANCE = 144;
const CAPITAL_CONQUER_MIN_BIG_SIGHT_RADIUS = 30;
const METROPOL_CONQUER_SPEED = 5;
const METROPOL_CONQUER_MIN_ATTACK_DISTANCE = 6;
const METROPOL_CONQUER_MAX_ATTACK_DISTANCE = 144;
const METROPOL_CONQUER_MIN_BIG_SIGHT_RADIUS = 30;
const DEFENSE_SUPPORT_DURATION_HOURS_MAX = 99;
const DEFENSE_SUPPORT_DURATION_HOURS_FREE = 12;
const DEFENSE_SUPPORT_DURATION_HOURS_FREE_OCCUPIED = 24;
const DEFENSE_SUPPORT_DURATION_HOURS_FREE_CAPITAL_METROPOL = 72;
const DEFENSE_SUPPORT_DURATION_HOURLY_C2_COST = 275;
const MAX_SLOWDOWN_DURATION_IN_SECONDS = 43200;
const SLOWDOWN_C2_COSTS = 200;
const TRAVEL_BOOST_CHEAT = 5;
module.exports.TRAVEL_BOOST_CHEAT = TRAVEL_BOOST_CHEAT;
const HORSE_BOOST_FIELDS = 10;
module.exports.HORSE_BOOST_FIELDS = HORSE_BOOST_FIELDS;
const LOW_DISTANCE_BOOST_FIELDS = 100;
module.exports.LOW_DISTANCE_BOOST_FIELDS = LOW_DISTANCE_BOOST_FIELDS;
const ALIEN_TRAVEL_DISTANCE = 50;
const NOMAD_TRAVEL_DISTANCE = 2;
const SAMURAI_TRAVEL_DISTANCE = 2;
const FACTION_TRAVEL_DISTANCE = 5;
const ALLIANCE_INVASION_CAMP_TRAVEL_DISTANCE = 2;
const COLLECTOR_TRAVEL_DISTANCE = 50;
const TEMPSERVER_RANKSWAP_TRAVEL_DISTANCE = 25.2;
const DAIMYO_CASTLE_TRAVEL_DISTANCE = 2;
const DAIMYO_TOWNSHIP_TRAVEL_DISTANCE = 2;
const DAIMYO_TAUNT_TRAVEL_DISTANCE = 2;
const ALLIANCE_BATTLE_GROUND_RESOURCE_TOWER_DISTANCE = 10;
const ALLIANCE_BATTLE_GROUND_TOWER_DISTANCE = 25;
const WOLFKING_TRAVEL_DISTANCE = 1;
const WOLFKING_TAUNT_TRAVEL_DISTANCE = 0.5;
const PLAGUE_TRAVEL_TIME = 600;
const MAX_TOOL_SLOTS = 9;
const MAX_TOOLS_PER_SLOT = 99999;
const TESTSERVER_DEFENSE_WAIT_DIVISOR = 4;
const MAX_KINGDOM_GOODS_MOVEMENTS = 1;
const MAX_KINGDOM_ARMY_MOVEMENTS = 1;
const COMMANDER_PREMIUM = -14;
const COMMANDER_DUNGEON = -15;
const WOLFKING_COMMANDER = -213;
const COMMANDER_BOSS_DUNGEON = -45;
const COMMANDER_TREASURE = -12;
const MAX_LEVEL_FOR_LOW_LEVEL_TRAVEL_BOOST = 25;
/**
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getPlagueTravelTime = function (isTravelCheater) {
return getSpecialTravelTime(isTravelCheater, PLAGUE_TRAVEL_TIME);
}
/**
* @param {boolean} isTravelCheater
* @param {number} time
* @return {number}
*/
function getSpecialTravelTime(isTravelCheater, time) {
if (isTravelCheater) return TRAVEL_BOOST_CHEAT;
return time;
}
/**
* @param {number} armySize
* @return {number}
*/
module.exports.getArmySightRadius = function (armySize) {
return Math.max(0.6 * Math.pow(armySize, 0.4), DEFAULT_SIGHT_RADIUS);
}
/**
* @param {number} durationHours
* @param {boolean} isOccupied
* @param {boolean} isCapital
* @param {boolean} isMetropol
* @return {number}
*/
module.exports.getSupportDurationCostC2 = function (durationHours, isOccupied, isCapital, isMetropol) {
const freeHours = isCapital || isMetropol ? DEFENSE_SUPPORT_DURATION_HOURS_FREE_CAPITAL_METROPOL : isOccupied ? DEFENSE_SUPPORT_DURATION_HOURS_FREE_OCCUPIED : DEFENSE_SUPPORT_DURATION_HOURS_FREE;
return Math.max(0, (durationHours - freeHours) * DEFENSE_SUPPORT_DURATION_HOURLY_C2_COST);
}
/**
* @param {number} distance
* @param {number} amountOfUnitsAndTools
* @param {number} travelCostReduction
* @param {number} travelCostSkillReduction
* @return {number}
*/
module.exports.getTravelCostC1 = function (distance, amountOfUnitsAndTools, travelCostReduction, travelCostSkillReduction) {
const _loc5_ = (100 - travelCostReduction) * (100 - travelCostSkillReduction) / 10000;
return Math.max(0, Math.ceil(0.6 * _loc5_ * (amountOfUnitsAndTools * Math.log(distance + 1) / Math.log(2.3))));
}
/**
* @param {number} distance
* @param {number} amountOfUnitsAndTools
* @param {number} travelCostReduction
* @param {number} travelCostSkillReduction
* @param {number} attackCount
* @param {number} attackCountThreshold
* @param {number} attackCountGrowthrate
* @return {number}
*/
module.exports.getAttackTravelCostC1 = function (distance, amountOfUnitsAndTools, travelCostReduction, travelCostSkillReduction, attackCount, attackCountThreshold, attackCountGrowthrate) {
const travelCostC1 = module.exports.getTravelCostC1(distance, amountOfUnitsAndTools, travelCostReduction, travelCostSkillReduction);
if (attackCount <= attackCountThreshold) return travelCostC1;
return Math.min(Math.exp(attackCountGrowthrate * (attackCount - attackCountThreshold)) * travelCostC1, 2147483647);
}
/**
* @param {number} distance
* @param {number} amountOfUnitsAndTools
* @param {number} travelCostEQReduction
* @param {number} travelCostSkillReduction
* @return {number}
*/
module.exports.getRedeployTravelCostC1 = function (distance, amountOfUnitsAndTools, travelCostEQReduction, travelCostSkillReduction) {
return module.exports.getTravelCostC1(distance, amountOfUnitsAndTools, travelCostEQReduction, travelCostSkillReduction) / 2;
}
/**
* @param {number} distance
* @return {number}
*/
module.exports.getTravelBoostCostC2 = function (distance) {
return Math.ceil(Math.pow(distance, 0.5) * 179);
}
/**
* @param {number} travelSpeed
* @param {number} distance
* @param {number} boost
* @param {number} boostEQ
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getTravelTime = function (travelSpeed, distance, boost, boostEQ, isTravelCheater) {
return Math.floor(module.exports.getTravelTimeAsFloat(travelSpeed, distance, boost, boostEQ, isTravelCheater));
}
/**
* @param {number} travelSpeed
* @param {number} distance
* @param {number} boost
* @param {number} boostEQ
* @param {number} titleBoost
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getTravelTimeWithTitle = function (travelSpeed, distance, boost, boostEQ, titleBoost, isTravelCheater) {
return Math.floor(module.exports.getTravelTimeAsFloat(travelSpeed, distance, boost, boostEQ + titleBoost, isTravelCheater));
}
/**
* @param {number} travelSpeed
* @param {number} boost
* @param {number} boostEQ
* @return {number}
*/
function getBoostedUnitSpeed(travelSpeed, boost, boostEQ) {
const eqBoost = boostEQ / 100;
return travelSpeed / 10 / BASIC_FIELD_TRAVEL_TIME * (boost + eqBoost);
}
module.exports.getBoostedUnitSpeed = getBoostedUnitSpeed;
/**
* @param {number} travelSpeed
* @param {number} distance
* @param {number} boost
* @param {number} boostEQ
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getTravelTimeAsFloat = function (travelSpeed, distance, boost, boostEQ, isTravelCheater) {
if (isTravelCheater) return TRAVEL_BOOST_CHEAT;
return distance / getBoostedUnitSpeed(travelSpeed, boost, boostEQ);
}
/**
* @param {number} distance
* @param {number} unitCount
* @param {number} costFactorC1
* @return {number}
*/
module.exports.getHorseCostC1 = function (distance, unitCount, costFactorC1) {
return costFactorC1 * Math.ceil(0.2 * (unitCount * Math.log(distance + 1) / Math.log(2.3)));
}
/**
* @param {number} distance
* @param {number} unitCount
* @param {number} costFactorC2
* @return {number}
*/
module.exports.getHorseCostC2 = function (distance, unitCount, costFactorC2) {
const _loc4_ = Math.floor(1.5 * (-25 * Math.sqrt(distance + 60) * Math.pow(1.5, -0.0002 * Math.pow(distance + 60, 2)) + 145) * (1 + unitCount / 1100));
return Math.round(Math.max(1, _loc4_) * costFactorC2);
}
/**
* @param {number} unitSpeed
* @param {number} distance
* @param {number} boostFactor
* @param {number} horseBoost
* @param {number} percentageBoost
* @param {number} totalDistance
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getTravelTimeWithHorseAndWithoutLowLevelBoost = function (unitSpeed, distance, boostFactor, horseBoost, percentageBoost, totalDistance, isTravelCheater) {
return module.exports.getTravelTimeWithHorse(unitSpeed, distance, boostFactor, horseBoost, percentageBoost, totalDistance, isTravelCheater);
}
/**
* @param {number} unitSpeed
* @param {number} distance
* @param {number} boostFactor
* @param {number} horseBoost
* @param {number} percentageBoost
* @param {number} totalDistance
* @param {boolean} isTravelCheater
* @return {number}
*/
module.exports.getTravelTimeWithHorse = function (unitSpeed, distance, boostFactor, horseBoost, percentageBoost, totalDistance, isTravelCheater) {
if (isTravelCheater) return TRAVEL_BOOST_CHEAT;
let horseUnitBoost = NaN;
const boostedUnitSpeed = getBoostedUnitSpeed(unitSpeed, boostFactor, percentageBoost)
if (distance < LOW_DISTANCE_BOOST_FIELDS) {
horseUnitBoost = 1 + horseBoost / 100 / 10 * 60 * (Math.log(totalDistance / 2 + 1) / Math.log(8));
} else if (horseBoost > 0) {
horseUnitBoost = 1 + horseBoost / 100 / 10 * (totalDistance - HORSE_BOOST_FIELDS);
distance -= HORSE_BOOST_FIELDS;
} else {
horseUnitBoost = 1 + horseBoost / 100 / 10 * totalDistance;
}
const horseBoostedUnitSpeed = boostedUnitSpeed * horseUnitBoost;
return Math.floor(distance / horseBoostedUnitSpeed);
}
/**
* @param {number} distance
* @return {number}
*/
module.exports.getInstantSpyHorseTravelTime = function (distance) {
return Math.floor(Math.log(distance) / Math.log(10) + 1);
}
/**
* @param {number} unitSpeed
* @param {number} distance
* @param {number} boostFactor
* @param {number} horseBoost
* @param {number} boostEQ
* @param {number} totalDistance
* @param {number} titleBoost
* @param {number} skillBoost
* @param {boolean} isTravelCheater
* @param {number} lowLevelBoost
* @return {number}
*/
module.exports.getTravelTimeWithTitleAndHorse = function (unitSpeed, distance, boostFactor, horseBoost, boostEQ, totalDistance, titleBoost, skillBoost, isTravelCheater, lowLevelBoost) {
return module.exports.getTravelTimeWithHorse(unitSpeed, distance, boostFactor + lowLevelBoost, horseBoost, boostEQ + titleBoost + skillBoost, totalDistance, isTravelCheater);
}
/**
* @param {number} radius
* @param {number} circleX
* @param {number} circleY
* @param {number} startX
* @param {number} startY
* @param {number} endX
* @param {number} endY
* @return {number}
*/
module.exports.calculateSightDistance = function (radius, circleX, circleY, startX, startY, endX, endY) {
const diffX = endX - startX;
const diffY = endY - startY;
if (diffX === 0 && diffY === 0) return NaN;
const toCircleX = startX - circleX;
const toCircleY = startY - circleY;
const squaredDistance = diffX * diffX + diffY * diffY;
const b = (2 * diffX * toCircleX + 2 * diffY * toCircleY) / squaredDistance;
const c = (toCircleX * toCircleX + toCircleY * toCircleY - radius * radius) / squaredDistance;
const discriminant = b * b / 4 - c;
if (discriminant < 0) return NaN;
const t1 = -b / 2 - Math.sqrt(discriminant);
const t2 = -b / 2 + Math.sqrt(discriminant);
if (t1 < 0 && t2 < 0) return NaN;
if (t1 > 1 && t2 > 1) return NaN;
const t = Math.max(0, Math.min(t1, t2));
return t * Math.sqrt(squaredDistance);
}
/**
* @param {number} playerLevel
* @param {boolean} isGlobalServer
* @return {number}
*/
module.exports.calculateLowLevelBoost = function (playerLevel, isGlobalServer) {
if (isGlobalServer || playerLevel >= MAX_LEVEL_FOR_LOW_LEVEL_TRAVEL_BOOST) return 0;
return Math.max(0, -0.1667 * playerLevel + 4.167);
}