fix:添加数据统计和显示对吸血额外伤害的支持

This commit is contained in:
ShakeFlower 2026-03-15 16:39:12 +08:00
parent 894fb88950
commit 09d95280d3
6 changed files with 169 additions and 64 deletions

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "ES2016",
"target": "ES2017",
"checkJs": true,
"noImplicitAny": false
}

View File

@ -440,9 +440,10 @@ control.prototype._initStatistics = function (totalTime) {
'money': 0,
'exp': 0,
'battleDamage': 0,
'damagePerFloor': {},
'poisonDamage': 0,
'extraDamage': 0,
'vampireExtraLoss': 0,
'damagePerFloor': {},
'moveDirectly': 0,
'ignoreSteps': 0,
'oneDefEffect': 0,
@ -450,6 +451,29 @@ control.prototype._initStatistics = function (totalTime) {
}
}
/**
* @param {'battleDamage'|'poisonDamage'|'extraDamage'|'vampireExtraLoss'} key
* @param {number} value
* @param {string} [floorId]
*/
control.prototype.addFloorStatistics = function (key, value, floorId) {
if (!floorId) floorId = core.status.floorId;
const statistics = core.status.hero.statistics;
if (key !== 'battleDamage' && key !== 'poisonDamage' && key !== 'extraDamage' &&
key !== 'vampireExtraLoss'
) return;
if (!statistics.damagePerFloor) {
statistics.damagePerFloor = {};
}
if (!statistics.damagePerFloor[floorId]) {
statistics.damagePerFloor[floorId] = {};
}
if (!statistics.damagePerFloor[floorId][key]) {
statistics.damagePerFloor[floorId][key] = 0;
}
statistics.damagePerFloor[floorId][key] += value;
}
// ------ 自动寻路,人物行走 ------ //
////// 清除自动寻路路线 //////
@ -1181,13 +1205,9 @@ control.prototype.checkBlock = function () {
if (!core.status.hero.statistics.damagePerFloor) {
core.status.hero.statistics.damagePerFloor = {};
}
if (!core.status.hero.statistics.damagePerFloor[floorId]) {
core.status.hero.statistics.damagePerFloor[floorId] = {
battleDamage: 0,
extraDamage: 0,
};
if (core.control.addFloorStatistics) {
core.control.addFloorStatistics("extraDamage", damage, floorId);
}
core.status.hero.statistics.damagePerFloor[floorId].extraDamage += damage;
if (core.status.hero.hp <= 0) {
core.status.hero.hp = 0;
core.updateStatusBar(false, true);
@ -1199,7 +1219,6 @@ control.prototype.checkBlock = function () {
}
let actions = [];
const ambushAction = this._checkBlock_ambush(core.status.checkBlock.ambush[loc]);
if (ambushAction.length > 0) core.push(actions, ambushAction);
@ -1385,7 +1404,8 @@ control.prototype.getEnemyValueString = function(name, blockId, x, y, floorId) {
const colorMap = {
hp: '#55ff55', atk: '#ff5555',
def: '#5555ff', money: '#ffff55', exp: '#ffaa33',
criticalDamage: '#B22222', defDamage: '#1E90FF'
criticalDamage: '#B22222', defDamage: '#1E90FF',
vampireDiff:'#f20c00',
}
switch (name) {
case "damage":
@ -1424,6 +1444,12 @@ control.prototype.getEnemyValueString = function(name, blockId, x, y, floorId) {
case "defDamage":
const defDamage = core.enemys.getDefDamage(blockId, 1, x, y, floorId);
return { text: defDamage, color: colorMap.defDamage };
case "vampireDiff":
const info = { text: "", color: colorMap.vampireDiff };
if (!core.enemys.getVampireExtraLoss) return info;
const loss = core.enemys.getVampireExtraLoss(blockId, x, y, floorId);
if (loss != null) info.text = `+${loss}`;
return info;
case "special":
const specialData = core.getLocalStorage('specialIconData', {});
const special = core.enemys.getEnemyValue(blockId, 'special', x, y, floorId);

View File

@ -417,6 +417,38 @@ enemys.prototype.getMdefDamage = function (enemy, k, x, y, floorId) {
return nowDamage - nextDamage;
}
/**
* 计算和吸血怪物当前的战斗伤害比最低战斗伤害高多少。返回null说明打不过或怪物不吸血
* @param {string|Enemy} enemy
* @param {number} [x]
* @param {number} [y]
* @param {string} [floorId]
* @param {{hp:number,atk:number,def:number,mdef:number}} [heroStatus] 未填时默认使用角色当前属性计算
* @returns {null|number}
*/
enemys.prototype.getVampireExtraLoss = function (enemy, x, y, floorId, heroStatus) {
if (typeof enemy == 'string') enemy = core.getEnemyValue(enemy, null, x, y, floorId);
if (!core.enemys.hasSpecial(enemy, 11)) return null;
if (!heroStatus) heroStatus = {
hp: core.status.hero.hp, atk: core.status.hero.atk,
def: core.status.hero.def, mdef: core.status.hero.mdef,
}
let damageInfo = core.enemys.getDamageInfo(enemy, heroStatus, x, y, floorId);
const initDamage = damageInfo.damage;
if (damageInfo == null) return null;
// 二分HP
let start = 1,
end = 100 * damageInfo.damage;
while (start < end) {
let mid = Math.floor((start + end) / 2);
heroStatus.hp = mid;
damageInfo = core.enemys.getDamageInfo(enemy, heroStatus, x, y, floorId);
if (damageInfo != null && damageInfo.damage < heroStatus.hp) end = mid;
else start = mid + 1;
}
return initDamage - start;
}
enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) {
if (enemy == null) return null;
if (typeof enemy == 'string') enemy = core.getEnemyValue(enemy, null, x, y, floorId);

View File

@ -309,25 +309,29 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
return;
}
// 记录统计数据
const statistics = core.status.hero.statistics;
statistics.battleDamage += damage;
core.control.addFloorStatistics("battleDamage", damage);
statistics.battle++;
// 1防收益
const defDamage = core.enemys.getDefDamage(enemy, -1, x, y, floorId);
if (typeof defDamage === "number") core.status.hero.statistics.oneDefEffect -= defDamage;
const mdefDamage = core.enemys.getMdefDamage(enemy, -1, x, y, floorId);
if (typeof mdefDamage === "number") core.status.hero.statistics.oneMdefEffect -= mdefDamage;
if (typeof defDamage === "number") statistics.oneDefEffect -= defDamage;
// 扣减体力值并记录统计数据
// 1护盾收益
const mdefDamage = core.enemys.getMdefDamage(enemy, -1, x, y, floorId);
if (typeof mdefDamage === "number") statistics.oneMdefEffect -= mdefDamage;
// 吸血额外伤害,必须放在实际扣减角色体力值之前,否则算出来是错的
const vampireExtraLoss = core.enemys.getVampireExtraLoss(enemy, x, y, floorId);
if (vampireExtraLoss !== null) {
statistics.vampireExtraLoss += vampireExtraLoss;
core.control.addFloorStatistics("vampireExtraLoss", vampireExtraLoss);
}
// 扣减体力值
core.status.hero.hp -= damage;
core.status.hero.statistics.battleDamage += damage;
core.status.hero.statistics.battle++;
if (!core.status.hero.statistics.damagePerFloor) {
core.status.hero.statistics.damagePerFloor = {};
}
if (!core.status.hero.statistics.damagePerFloor[floorId]) {
core.status.hero.statistics.damagePerFloor[floorId] = {
battleDamage: 0,
extraDamage: 0,
};
}
core.status.hero.statistics.damagePerFloor[floorId].battleDamage += damage;
// 计算当前怪物的支援怪物
// guard:一个形如[[1, 1, 'greenSlime'], [[2, 2, 'redSlime']]]的数组
@ -1604,6 +1608,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 检查中毒状态的扣血和死亡
if (core.hasFlag('poison')) {
core.status.hero.statistics.poisonDamage += core.values.poisonDamage;
if (core.control.addFloorStatistics) {
core.control.addFloorStatistics("poisonDamage", core.values.poisonDamage);
}
core.status.hero.hp -= core.values.poisonDamage;
if (core.status.hero.hp <= 0) {
core.status.hero.hp = 0;
@ -1666,6 +1673,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
var damage = ignoreSteps * core.values.poisonDamage;
if (damage >= core.status.hero.hp) return false;
core.status.hero.statistics.poisonDamage += damage;
if (core.control.addFloorStatistics) {
core.control.addFloorStatistics("poisonDamage", damage);
}
core.status.hero.hp -= damage;
}

View File

@ -5770,7 +5770,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
'atk': core.control.getStatusLabel('atk'), 'def': core.control.getStatusLabel('def'),
'money': core.control.getStatusLabel('money'), 'exp': core.control.getStatusLabel('exp'),
'criticalDamage': '临界减伤', 'defDamage': '1防减伤', 'special': '特殊属性',
'notBomb': '不可炸',
'notBomb': '不可炸', 'vampireDiff': '吸血额外受伤'
}
class DisplayInfoBtn extends RoundBtn {
@ -5853,6 +5853,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
btn.infoName = infoName;
const name = infoNameMap[infoName];
btn.text = name;
if (name.length >= 5) {
if (!btn.config) btn.config = {};
btn.config.font = "12px Verdana";
}
}
else {
btn.infoName = null;
@ -5945,6 +5949,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
btn4 = new DisplayInfoBtn(50, 200, 75, 20, 'rightup', 1),
btn5 = new DisplayInfoBtn(50, 225, 75, 20, 'rightup', 2),
btn6 = new DisplayInfoBtn(50, 250, 75, 20, 'rightup', 3);
/** 一行显示几个选项 */
const ROW_INFONAME = 6;
const infoNameList = Object.keys(infoNameMap);
const l = infoNameList.length;
@ -5961,17 +5967,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.control.updateStatusBar(); // 手动刷新一下地图显伤
}
}
const ROW_INFONAME = 6;
for (let i = 0; i < ROW_INFONAME; i++) {
const tempBtn = new RoundBtn(200, 100 + i * 25, 80, 20, infoNameMap[infoNameList[i]], { fillStyle: 'Azure' });
tempBtn.disable = true;
advanceDisplayMenu.registerBtn('temp' + i, tempBtn, setNewInfo(infoNameList[i]));
}
for (let i = ROW_INFONAME; i < l; i++) {
const tempBtn = new RoundBtn(300, 100 + (i - ROW_INFONAME) * 25, 80, 20, infoNameMap[infoNameList[i]], { fillStyle: 'Azure' });
for (let i = 0; i < l; i++) {
const name = infoNameMap[infoNameList[i]];
const config = {
fillStyle: 'Azure',
font: name.length >= 5 ? "12px Verdana" : "14px Verdana",
}
const x = (i >= ROW_INFONAME) ? 300 : 200;
const y = 100 + 25 * ((i >= ROW_INFONAME) ? (i - ROW_INFONAME) : i);
const tempBtn = new RoundBtn(x, y, 80, 20, name, config);
tempBtn.disable = true;
advanceDisplayMenu.registerBtn('temp' + i, tempBtn, setNewInfo(infoNameList[i]));
}
const change = function (btn) {
return function () {
if (btn.infoName) {
@ -9852,7 +9860,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}
/**
* @param {{total:number} & {[itemId:string]:{[floorId:string]:number}}} obj1
* @param {{total:number; [itemId:string]:{[floorId:string]:number}}} obj1
* @param {{total:number, [itemId:string]:number}} obj2
*/
function addCountToFormer(obj1, obj2, floorId) {
@ -9866,7 +9874,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}
/**
* @typedef {{total:number,[floorId:string]:number}} ObjSTAT
* @typedef {{total:number;[floorId:string]:number}} ObjSTAT
* @typedef {{toolsCount:ObjSTAT,gemsCount:ObjSTAT,
* equipsCount:ObjSTAT,enemysCount:ObjSTAT,
* enemys:enemys,items:items,
@ -9876,6 +9884,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
* @param {string[]} floorList 要统计的楼层的列表
*/
function getFloorListStat(floorList) {
const statistics = core.status.hero.statistics;
const damagePerFloor = statistics.damagePerFloor;
/** @type {STAT} */
const stat = {
toolsCount: { total: 0, },
@ -9884,10 +9894,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
enemysCount: { total: 0, },
enemys: { count: 0, money: 0, exp: 0, point: 0, },
items: { count: 0, hp: 0, atk: 0, def: 0, mdef: 0, },
battleDamage: { total: 0 },
extraDamage: { total: 0 },
battleDamage: { total: statistics.battleDamage },
extraDamage: { total: statistics.extraDamage },
poisonDamage: { total: statistics.poisonDamage },
vampireExtraLoss: { total: statistics.vampireExtraLoss },
};
const damagePerFloor = core.status.hero.statistics.damagePerFloor;
floorList.forEach(floorId => {
if (!statistics[floorId]) statistics[floorId] = getFloorStat(floorId);
addToFormer(stat.enemys, statistics[floorId].enemys);
@ -9897,14 +9908,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
addCountToFormer(stat.equipsCount, statistics[floorId].equipsCount, floorId);
addCountToFormer(stat.enemysCount, statistics[floorId].enemysCount, floorId);
if (damagePerFloor[floorId]) {
const battleDamage = damagePerFloor[floorId].battleDamage || 0;
const extraDamage = damagePerFloor[floorId].extraDamage || 0;
stat.battleDamage[floorId] = battleDamage;
stat.battleDamage["total"] += battleDamage;
stat.extraDamage[floorId] = extraDamage;
stat.extraDamage["total"] += extraDamage;
["battleDamage","extraDamage","poisonDamage","vampireExtraLoss"].forEach(key=>{
stat[key][floorId] = damagePerFloor[floorId]?.[key] || 0;
});
}
});
console.log(stat);
return stat;
}
@ -10035,7 +10044,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}
itemList = [...doorNameList.sort(sortFunc), ...itemNameList.sort(sortFunc)];
}
else if (this.mode === "damage") itemList = ["battleDamage", "extraDamage"];
else if (this.mode === "damage") {
itemList = ["battleDamage", "extraDamage"];
if (core.status.hero.statistics.poisonDamage > 0) itemList.push("poisonDamage");
if (core.status.hero.statistics?.vampireExtraLoss > 0) itemList.push("vampireExtraLoss");
}
else itemList = Object.keys(count).filter(item => item !== "total").sort(sortFunc);
return itemList;
}
@ -10084,9 +10097,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.getBlockById(id).event.name || "";
}
else {
name = (id === "battleDamage") ? "战斗伤害" :
(id === "extraDamage") ? "地图伤害" : "";
if (id === "battleDamage") name = "战斗伤害";
else if (id === "extraDamage") name = "地图伤害";
else if (id === "poisonDamage") name = "中毒伤害";
else if (id === "vampireExtraLoss") name = "吸血额外伤害";
}
console.log(count[id]);
if (count[id]==null) debugger;
total = count[id].total || 0;
}
core.ui.strokeRect(ctx, 20, 155 + 25 * i, 80, 25, "black");
@ -10110,8 +10127,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (!this.stat) return;
const { x, y, w, h, zIndex, name, stat } = this;
const ctx = core.createCanvas(name, x, y, w, h, zIndex);
const { enemys, items, toolsCount, gemsCount, equipsCount,
enemysCount, battleDamage, extraDamage } = stat;
const { enemys, items, toolsCount, gemsCount, equipsCount, enemysCount,
battleDamage, extraDamage, poisonDamage, vampireExtraLoss } = stat;
const enemyText = `给定地图中共有怪物${enemys.count}个` +
(enemys.money > 0 ? `,总金币${enemys.money}.` : '') +
(enemys.exp > 0 ? `,总经验${enemys.exp}` : '') +
@ -10130,7 +10147,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (this.mode === "items") count = gemsCount;
else if (this.mode === "equips") count = equipsCount;
else if (this.mode === "enemys") count = enemysCount;
else if (this.mode === "damage") count = { battleDamage, extraDamage };
else if (this.mode === "damage") count = { battleDamage, extraDamage, poisonDamage, vampireExtraLoss };
this.itemList = this.getItemList(count);
this.drawTable(ctx, count);
super.drawContent();
@ -10142,17 +10159,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
const { name, x, y, w, h, zIndex } = this;
const ctx = this.createCanvas(name, x, y, w, h, zIndex);
const statistics = core.status.hero.statistics;
const str = "当前总步数:" + core.status.hero.steps + ",当前游戏时长:" + core.formatTime(statistics.currTime)
+ ",总游戏时长" + core.formatTime(statistics.totalTime)
+ "。瞬间移动次数:" + statistics.moveDirectly + ",共计少走" + statistics.ignoreSteps + "步。"
+ "\n\n总计通过血瓶恢复生命值为" + core.formatBigNumber(statistics.hp) + "点。\n\n"
+ "总计打死了" + statistics.battle + "个怪物,得到了" + core.formatBigNumber(statistics.money) + "金币," + core.formatBigNumber(statistics.exp) + "点经验。\n\n"
+ "受到的总伤害为" + core.formatBigNumber(statistics.battleDamage + statistics.poisonDamage + statistics.extraDamage)
+ ",其中战斗伤害" + core.formatBigNumber(statistics.battleDamage) + "点"
+ (core.flags.statusBarItems.indexOf('enableDebuff') >= 0 ? (",中毒伤害" + core.formatBigNumber(statistics.poisonDamage) + "点") : "")
+ ",领域/夹击/阻击/血网伤害" + core.formatBigNumber(statistics.extraDamage) + "点。\n\n"
+ "1防御累计减伤为" + core.formatBigNumber(statistics.oneDefEffect || 0)
+ ",1护盾累计减伤为" + core.formatBigNumber(statistics.oneMdefEffect || 0) + "。";
const str = `当前总步数:${core.status.hero.steps},当前游戏时长:${core.formatTime(statistics.currTime)},总游戏时长${core.formatTime(statistics.totalTime)}。瞬间移动次数:${statistics.moveDirectly},共计少走${statistics.ignoreSteps}步。
总计通过血瓶恢复生命值为${core.formatBigNumber(statistics.hp)}点。
总计打死了${statistics.battle}个怪物,得到了${core.formatBigNumber(statistics.money)}金币,${core.formatBigNumber(statistics.exp)}点经验。
受到的总伤害为${core.formatBigNumber(statistics.battleDamage + statistics.poisonDamage + statistics.extraDamage)},其中战斗伤害${core.formatBigNumber(statistics.battleDamage)}点${core.flags.statusBarItems.indexOf('enableDebuff') >= 0 ? `,中毒伤害${core.formatBigNumber(statistics.poisonDamage)}点` : ""},领域/夹击/阻击/血网伤害${core.formatBigNumber(statistics.extraDamage)}点。
${statistics["vampireExtraLoss"] > 0 ? `吸血怪物累计对你造成超出最低伤害的额外伤害${core.formatBigNumber(statistics["vampireExtraLoss"])}点。` : ``}
${statistics.hasOwnProperty("oneDefEffect") ? `1防御累计减伤为${core.formatBigNumber(statistics.oneDefEffect || 0)}` : ""}${statistics.hasOwnProperty("oneMdefEffect") ? `,1护盾累计减伤为${core.formatBigNumber(statistics.oneMdefEffect || 0)}` : ""}。
`;
core.drawTextContent(ctx, str, {
left: 30, top: 20, color: "black", maxWidth: 360, fontSize: 14
});
@ -10284,7 +10300,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
["itemStat", itemStatBtn, changeMode(itemStatBtn, "items")],
["equipStat", equipStatBtn, changeMode(equipStatBtn, "equips")],
["enemyStat", enemyStatBtn, changeMode(enemyStatBtn, "enemys")],
["damageStat", damageStatBtn, changeMode(enemyStatBtn, "damage")],
["damageStat", damageStatBtn, changeMode(damageStatBtn, "damage")],
["itemDown", itemDownBtn, () => floorStatisticsTextMenu.itemPageDown()],
["itemUp", itemUpBtn, () => floorStatisticsTextMenu.itemPageUp()],
["floorDown", floorDownBtn, () => floorStatisticsTextMenu.floorPageDown()],

21
runtime.d.ts vendored
View File

@ -196,6 +196,8 @@ type HeroStatus = {
[floorId: string]: {
battleDamage?: number;
extraDamage?: number
poisonDamage?: number;
vampireExtraLoss?: number;
}
}
currTime: number
@ -206,6 +208,7 @@ type HeroStatus = {
money: number
moveDirectly: number
poisonDamage: number
vampireExtraLoss: number
start?: number
totalTime: number,
oneDefEffect: number,
@ -1014,6 +1017,12 @@ interface control {
* @param type 重新设置指定类型的已注册resize事件
*/
resize(type?:string): void
/**
* 291改新增函数,在楼层数据统计中添加指定项目的值
*/
addFloorStatistics(key: 'battleDamage' | 'poisonDamage' | 'extraDamage' | 'vampireExtraLoss',
value: number, floorId?: string): void
}
/**@file events.js将处理所有和事件相关的操作。 */
@ -1665,6 +1674,18 @@ interface enemys {
*/
getMdefDamage(enemy: string | Enemy, k?: number, x?: number, y?: number, floorId?: string): number
/**
* 计算和吸血怪物当前的战斗伤害比最低战斗伤害高多少。返回null说明打不过或怪物不吸血
* @param {string|Enemy} enemy
* @param {number} [x]
* @param {number} [y]
* @param {string} [floorId]
* @param {{hp:number,atk:number,def:number,mdef:number}} [heroStatus] 未填时默认使用角色当前属性计算
* @returns {null|number}
*/
getVampireExtraLoss(enemy: string | Enemy, x?: number, y?: number,
floorId?: string, heroStatus?: { hp: number, atk: number, def: number, mdef: number })
/**
* 获得某张地图的敌人集合,用于手册绘制
* @example core.getCurrentEnemys('MT0') // 主塔0层的敌人集合