ggejs
Version:
A powerful Node.js module for interacting with the server of Goodgame Empire & Goodgame Empire: Four Kingdoms
194 lines (180 loc) • 8.16 kB
JavaScript
const {currencyMinutesSkipValues, tmapnodes, tmaps} = require('e4k-data').data;
const BattleParticipant = require("../structures/BattleParticipant");
const Equipment = require("../structures/Equipment");
const Gem = require("../structures/Gem");
const General = require("../structures/General");
const Good = require("../structures/Good");
const Lord = require("../structures/Lord");
const TreasureMapMapobject = require("../structures/mapobjects/TreasureMapMapobject");
const RelicEquipment = require("../structures/RelicEquipment");
const {parseMapObject} = require("../utils/MapObjectParser");
const SeasonEventsConstants = require("../utils/SeasonEventsConstants");
const NAME = "bls";
/** @type {CommandCallback<BattleLog>[]}*/
const callbacks = [];
module.exports.name = NAME;
/**
* @param {BaseClient} client
* @param {number} errorCode
* @param {Object} params
*/
module.exports.execute = function (client, errorCode, params) {
const battleLog = parseBLS(client, params);
require('.').baseExecuteCommand(client, battleLog, errorCode, params, callbacks);
}
/**
* @param {BaseClient} client
* @param {number} messageId
* @return {Promise<BattleLog>}
*/
module.exports.getBattleLogShort = function (client, messageId) {
const C2SBattleLogShortVO = {MID: messageId};
return require('.').baseSendCommand(client, NAME, C2SBattleLogShortVO, callbacks, (p) => p?.["MID"] === messageId);
}
module.exports.bls = parseBLS;
/**
* @param {BaseClient} client
* @param {{AI: Object, AL: Object, ALS: number[], DW: number, PBI: [], PI: []}} params
* @return {BattleLog}
*/
function parseBLS(client, params) {
if (!params || !params.PI) return null;
client.worldMaps._ownerInfoData.parseOwnerInfoArray(params.PI);
const pbiInfo = parsePbiInfo(client, params.PBI, params.DW === 1);
const attackerLords = parseAttackerLords(client, params, {attacker: pbiInfo.attacker});
const defenderLords = parseDefenderLords(client, params, {defender: pbiInfo.defender});
const autoSkips = parseAutoSkip(client, params);
const mapObject = parseWorldMapArea(client, params.AI);
if (mapObject instanceof TreasureMapMapobject) {
const mapSeed = String(params["MS"]).split("+").map(s => parseInt(s));
/** @type {TreasureMapMapobject} */
let treasureMapMapObject = mapObject;
treasureMapMapObject.mapId = params.AI["MID"] ?? mapSeed[3];
const tMap = tmaps.find(m => m.mapID === treasureMapMapObject.mapId);
const tMapNode = tmapnodes.find(n => n.tmapnodeID === treasureMapMapObject.nodeId);
treasureMapMapObject.isSurroundingDungeon = SeasonEventsConstants.isSurroundingDungeon(tMapNode.ownerID);
treasureMapMapObject.isEndNode = tMap.endNodeID === tMapNode.tmapnodeID;
}
return {
battleLogId: params["LID"],
messageId: params["MID"],
messageType: params["MT"],
mapobject: mapObject,
attacker: pbiInfo.attacker,
defender: pbiInfo.defender,
winner: pbiInfo.winner,
loser: pbiInfo.loser,
defWon: params.DW === 1,
honor: params["H"],
survivalRate: params["SR"],
ragePoints: params["RP"],
shapeshifterPoints: params["SSP"],
shapeshifterId: params["SSID"],
rewardEquipment: params["EQF"] == null ? null : params["EQF"][11] === 3 ? new RelicEquipment(client, params["EQF"]) : new Equipment(client, params["EQF"]),
rewardGem: params["GF"] == null ? null : new Gem(client, params["GF"]),
rewardMinuteSkips: params["MSF"] == null ? null : currencyMinutesSkipValues.find(ms => ms.MinuteSkipIndex === params["MSF"] - 1),
attackerHomeCastleId: params["AHC"],
attackerHadHospital: params["AHH"] === 1,
isAttackerHospitalFull: params["AHF"] === 1,
defenderHomeCastleId: params["DHC"],
defenderHadHospital: params["DHH"] === 1,
isDefenderHospitalFull: params["DHF"] === 1,
attackerAllianceSubscribers: params["AAS"],
defenderAllianceSubscribers: params["DAS"],
attackerHasIndividualSubscription: params["AHP"] === 1,
defenderHasIndividualSubscription: params["DHP"] === 1,
allianceName: params["N"],
attackerCommandant: attackerLords?.commandant,
attackerGeneral: attackerLords?.general,
attackerLegendSkills: attackerLords?.legendSkills,
defenderBaron: defenderLords?.baron,
defenderGeneral: defenderLords?.general,
defenderLegendSkills: defenderLords?.legendSkills,
autoSkipCooldownType: autoSkips.autoSkipCooldownType,
autoSkipMinuteSkips: autoSkips.autoSkipMinuteSkips,
autoSkipC2: autoSkips.autoSkipC2,
autoSkipSeconds: autoSkips.autoSkipSeconds,
};
}
/**
* @param {BaseClient} client
* @param {Object} data
*/
function parseWorldMapArea(client, data) {
return parseMapObject(client, [data["AT"]]).parseAreaInfoBattleLog(data);
}
/**
* @param {BaseClient} client
* @param {Array} data
* @param {boolean} deffWon
* @return {{winner: BattleParticipant, loser: BattleParticipant, attacker: BattleParticipant, defender: BattleParticipant}}
*/
function parsePbiInfo(client, data, deffWon) {
if (data == null) return undefined;
const battleParticipants = data.map(p => new BattleParticipant(client, p))
const winnerIndex = deffWon && battleParticipants[0].front === 1 || deffWon && battleParticipants[0].front === 0 ? 0 : 1;
const loserIndex = 1 - winnerIndex;
return {
winner: battleParticipants[winnerIndex],
loser: battleParticipants[loserIndex],
attacker: battleParticipants[0],
defender: battleParticipants[1],
}
}
/**
* @param {BaseClient} client
* @param {{AL: Object, ALS: number[]}} data
* @param {BattleLog} battleLog
* @return {{commandant: Lord, general: Lord | null, legendSkills: number[]}}
*/
function parseAttackerLords(client, data, battleLog) {
if (data.AL === undefined) return undefined;
const lord = new Lord(client, data.AL);
if (battleLog.attacker.playerId === client.clientUserData.playerId) {
const lord2 = client.equipments.getCommanders().find(c => c.id === lord.id);
lord.name = !!lord2 ? lord2.name : "";
}
let general = null;
if (lord.generalId != null && lord.generalId !== -1) {
general = new General(client, data.AL);
lord.generalId = general.generalId;
}
return {commandant: lord, general: general, legendSkills: data.ALS ?? []};
}
/**
* @param {BaseClient} client
* @param {{DB: Object, DLS: number[]}} data
* @param {BattleLog} battleLog
* @return {{baron: Lord, general: Lord, legendSkills: number[]}}
*/
function parseDefenderLords(client, data, battleLog) {
if (data.DB === undefined) return undefined;
const lord = new Lord(client, data.DB);
if (battleLog.defender.playerId === client.clientUserData.playerId) {
const lord2 = client.equipments.getBarons().find(b => b.id === lord.id);
lord.name = lord2 ? lord2.name : "";
}
let general = null;
if (lord.generalId != null && lord.generalId !== -1) {
general = new General(client, data.DB);
lord.generalId = general.generalId;
}
return {baron: lord, general: general, legendSkills: data.DLS ?? []};
}
/**
* @param {BaseClient} client
* @param {{ASCT: number, ASMS: [string, number][], ASC: number, ASS: number, [p:string]: any}} data
* @return {{autoSkipCooldownType: number, autoSkipMinuteSkips: Good[], autoSkipC2: number, autoSkipSeconds: number}}
*/
function parseAutoSkip(client, data) {
if (data.ASCT !== undefined) {
return {
autoSkipCooldownType: data.ASCT,
autoSkipMinuteSkips: data.ASMS.map(ms => new Good(ms)),
autoSkipC2: data.ASC,
autoSkipSeconds: data.ASS
};
} else return {
autoSkipCooldownType: -1, autoSkipMinuteSkips: [], autoSkipC2: -1, autoSkipSeconds: -1
};
}