+ );
};
export default AllyConfig;
diff --git a/src/BattleField/EnemySelect/index.jsx b/src/BattleField/EnemySelect/index.jsx
index f73536b..53bce62 100644
--- a/src/BattleField/EnemySelect/index.jsx
+++ b/src/BattleField/EnemySelect/index.jsx
@@ -1,76 +1,62 @@
-import React, { useState } from 'react';
-import useGlobalStore from '../../GlobalStore';
-import { ENEMY_COLLECTION } from '../../GlobalStore';
-import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
-import Icon from '../../comps/Icon';
-import css from './css.module.css';
+import React, { useState } from "react";
+import useGlobalStore from "../../GlobalStore";
+import { ENEMY_COLLECTION } from "../../GlobalStore";
+import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
+import Icon from "../../comps/Icon";
+import css from "./css.module.css";
const FoeSelect = () => {
- const { removeEnemyByType, addEnemy, selectedEnemy } = useGlobalStore();
- const [open, setOpen] = useState(false);
+ const { removeEnemyByType, addEnemy, selectedEnemy } = useGlobalStore();
+ const [open, setOpen] = useState(false);
- const getFoeCount = (enemyType) => {
- const pool = selectedEnemy.filter((foe) => foe.type === enemyType);
- return pool?.length;
- };
+ const getFoeCount = (enemyType) => {
+ const pool = selectedEnemy.filter((foe) => foe.type === enemyType);
+ return pool?.length;
+ };
- return (
- <>
-
- {ENEMY_COLLECTION?.map((el) => {
- const count = getFoeCount(el.type);
- return (
-
-
-
-
-
-
0
- ? css.btn
- : css.disabledBtn
- }
- onClick={() =>
- removeEnemyByType(el.type)
- }
- >
-
-
-
0 ? '#f50' : '#555',
- }}
- >
- {count}
-
-
addEnemy(el)}
- >
-
-
-
-
- );
- })}
+ return (
+ <>
+
+ {open && (
+
+ {ENEMY_COLLECTION?.map((el) => {
+ const count = getFoeCount(el.type);
+ return (
+
+
+
- )}
- {open && (
-
setOpen(false)}>
- )}
- >
- );
+
+
0 ? css.btn : css.disabledBtn}
+ onClick={() => removeEnemyByType(el.type)}
+ >
+
+
+
0 ? "#f50" : "#555",
+ }}
+ >
+ {count}
+
+
addEnemy({ ...el })}>
+
+
+
+
+ );
+ })}
+
+ )}
+ {open &&
setOpen(false)}>
}
+ >
+ );
};
export default FoeSelect;
diff --git a/src/GlobalStore/AttackModifier.js b/src/GlobalStore/AttackModifier.js
index 3b16b98..44fee03 100644
--- a/src/GlobalStore/AttackModifier.js
+++ b/src/GlobalStore/AttackModifier.js
@@ -1,22 +1,16 @@
-//加伤条件:
-//无条件加伤【重锤掌握】
-//基于命中差值【精准打击】
-//基于最终伤害【萎靡】【宿敌】
-//基于特定效果【背刺】
-
//增伤计算步骤
-// 1.提升命中
-// 2.提升符号数量
-// 3.提升符号伤害
-// 4.提升最终伤害
+// 1.提升命中 【夹击】
+// 2.提升符号数量 【绝境一击】【身躯大师】
+// 3.提升符号伤害【身躯大师】
+// 4.提升最终伤害【萎靡】【宿敌】【重锤掌握】
//定义DMG_SETP 1-4 来归类计算过程
const MODIFIER_TYPE = {
- NO_CONDITION: 'NO_CONDITION',
- STATUS: 'STATUS',
- DIFF_ATTACK_ROLL: 'DIFF_ATTACK_ROLL',
- DIFF_DMG: 'DIFF_DMG',
+ NO_CONDITION: "NO_CONDITION",
+ STATUS: "STATUS",
+ DIFF_ATTACK_ROLL: "DIFF_ATTACK_ROLL",
+ DIFF_DMG: "DIFF_DMG",
};
const masterVesselCalculator = (tagInput) => {};
@@ -28,69 +22,58 @@ const nemesisDamageType = () => {};
const courageCalc = () => {};
const cqcCalc = () => {
- //根据距离加伤0-4
+ //根据距离加伤0-4
};
-const MOD_STEP_1 = [
- { name: 'DARKNESS', step: 1, modifier: -1 },
- { name: 'HINDERING', step: 1, modifier: -1 }, //困难地形
- { name: 'CROSS_ALLY', step: 1, modifier: -1 }, //穿盟友
- { name: 'FLANKING', step: 1, modifier: 1 }, //夹击
- { name: 'TRICK_SHOT', step: 1, modifier: -1 }, //狡诈射击
- { name: 'MASTER_WORK', step: 1, modifier: 1 }, //武器升级
-];
+export const DMG_STEP_1 = {
+ DARKNESS: { modifier: -1 },
+ HINDERING: { modifier: -1 }, //困难地形
+ CROSS_ALLY: { modifier: -1 }, //穿盟友
+ FLANKING: { modifier: 1 }, //夹击
+ TRICK_SHOT: { modifier: -1 }, //狡诈射击
+ MASTER_WORK: { modifier: 1 }, //武器升级
+};
-const MOD_STEP_2 = [
- {
- name: 'COURAGE',
- step: 2,
- modifier: { shield: 1, book: 1, burst: 0 },
- },
- {
- name: 'DEAD_END',
- step: 2,
- modifier: { shield: 4, book: 0, burst: 0 },
- },
- {
- name: 'MASTER_OF_THE_VESSEL',
- step: 2,
- modifier: { shield: 0, book: 0, burst: 1 }, //这里是符号数量 +1
- },
-];
+export const DMG_STEP_2 = {
+ COURAGE: {
+ modifier: { shield: 1, book: 1, burst: 0 },
+ },
+ DEAD_END: {
+ modifier: { shield: 4, book: 0, burst: 0 },
+ },
+ MASTER_OF_THE_VESSEL: {
+ modifier: { shield: 0, book: 0, burst: 1 },
+ },
+};
-const MOD_STEP_3 = [
- {
- name: 'MASTER_OF_THE_VESSEL',
- step: 3,
- modifier: { shield: 1, book: 1, burst: 1 }, //这里是符号伤害 +1
- },
-];
+export const DMG_STEP_3 = {
+ MASTER_OF_THE_VESSEL: {
+ modifier: { shield: 1, book: 1, burst: 1 }, //这里是符号伤害 +1
+ },
+};
-const MOD_STEP_4 = [
- { name: 'DEVASTATING', dmg_type: 'PHYSICAL', step: 4, dmg: 2 },
- {
- name: 'BACKSTAB',
- require: {
- type: MODIFIER_TYPE.STATUS,
- value: 'FLANKING',
- },
- dmg_type: 'PHYSICAL',
- step: 4,
- dmg: 2,
+export const DMG_STEP_4 = {
+ DEVASTATING: { dmg_type: "PHYSICAL", dmg: 2 },
+ BACKSTAB: {
+ require: {
+ type: MODIFIER_TYPE.STATUS,
+ value: "FLANKING",
},
- { name: 'TRICK_SHOT', dmg_type: 'PHYSICAL', step: 4, dmg: 3 },
- { name: 'CQC', dmg_type: 'PHYSICAL', step: 4, dmg: cqcCalc },
- {
- name: 'PRECISE_STRIKE',
- require: {
- type: MODIFIER_TYPE.DIFF_ATTACK_ROLL,
- value: 4,
- },
- dmg_type: 'IRRERUCEABLE',
- step: 4,
- dmg: 5,
+ dmg_type: "PHYSICAL",
+
+ dmg: 2,
+ },
+ TRICK_SHOT: { dmg_type: "PHYSICAL", dmg: 3 },
+ CQC: { dmg_type: "PHYSICAL", dmg: cqcCalc },
+ PRECISE_STRIKE: {
+ require: {
+ type: MODIFIER_TYPE.DIFF_ATTACK_ROLL,
+ value: 4,
},
- { name: 'HAMMER_HELM', dmg_type: 'PHYSICAL', step: 4, dmg: 1 }, //重锤掌握
- { name: 'WILT', dmg_type: 'IRRERUCEABLE', step: 4, dmg: 2 },
- { name: 'NEMESIS', dmg_type: nemesisDamageType, step: 4, dmg: 2 },
-];
+ dmg_type: "IRRERUCEABLE",
+ dmg: 5,
+ },
+ HAMMER_HELM: { dmg_type: "PHYSICAL", dmg: 1 },
+ WILT: { dmg_type: "IRRERUCEABLE", dmg: 2 },
+ NEMESIS: { dmg_type: nemesisDamageType, dmg: 2 },
+};
diff --git a/src/GlobalStore/calculator.js b/src/GlobalStore/calculator.js
new file mode 100644
index 0000000..b5e2a09
--- /dev/null
+++ b/src/GlobalStore/calculator.js
@@ -0,0 +1,128 @@
+import {
+ DMG_STEP_1,
+ DMG_STEP_2,
+ DMG_STEP_3,
+ DMG_STEP_4,
+} from "./AttackModifier";
+
+const isValid = ({ enemy, preset }) => {
+ if (!enemy) {
+ console.error("Please target an enemy first");
+ return false;
+ }
+
+ if (!(preset.diceA && preset.diceB)) {
+ console.error("Please roll both your die");
+ return false;
+ }
+
+ if (!(preset.symbol_shield && preset.symbol_book && preset.symbol_burst)) {
+ console.error("Please chose symbol ability");
+ return false;
+ }
+
+ return true;
+};
+
+export const calculate = ({ enemy, preset, userInput }) => {
+ //先校验合法
+ const valid = isValid({ enemy, preset });
+ if (!valid) return;
+
+ const hit_step = []; //1.命中增幅
+ const symbel_number_step = []; //符号数量增幅
+ const symbol_damage_step = []; //符号伤害增幅
+ const final_damage_step = []; //最终伤害增幅
+
+ const loopPlace = (arr) => {
+ arr?.forEach((st) => {
+ if (DMG_STEP_1?.[st]) {
+ hit_step.push(st);
+ }
+ if (DMG_STEP_2?.[st]) {
+ symbel_number_step.push(st);
+ }
+ if (DMG_STEP_3?.[st]) {
+ symbol_damage_step.push(st);
+ }
+ if (DMG_STEP_4?.[st]) {
+ final_damage_step.push(st);
+ }
+ });
+ };
+ //数据准备
+ loopPlace(enemy.status);
+ loopPlace(preset.weapon_upgrade);
+ loopPlace(preset.field_status);
+ loopPlace(preset.discripline);
+
+ //1.计算命中
+ if (preset.empower?.base === 6) {
+ //黑骰子大失败
+ alert("attack missed");
+ return;
+ }
+
+ let attackRoll = preset.diceA.base + preset.diceB.base;
+ hit_step?.forEach((md) => {
+ attackRoll += DMG_STEP_1[md].modifier;
+ });
+ console.log("=== attack roll ===", attackRoll);
+ let def = enemy.def;
+ if (attackRoll < def) {
+ alert("attack missed");
+ return;
+ }
+
+ //2.计算符号数量
+ let totalShield = preset.diceA.shield + preset.diceB.shield;
+ let totalBook = preset.diceA.book + preset.diceB.book;
+ let totalBurst = preset.diceA.burst + preset.diceB.burst;
+
+ if (preset.empower) {
+ totalShield += preset.empower.shield;
+ totalBook += preset.empower.book;
+ totalBurst += preset.empower.burst;
+ }
+ symbel_number_step?.forEach((sn) => {
+ totalShield += DMG_STEP_2[sn].modifier.shield;
+ totalBook += DMG_STEP_2[sn].modifier.book;
+ totalBurst += DMG_STEP_2[sn].modifier.burst;
+ });
+ console.log("=== shield book burst ===", totalShield, totalBook, totalBurst);
+
+ //3.计算符号伤害 { shield: 2, dmg: 3, type: "PHYSICAL" },
+ const shield_unit = preset.symbol_shield.shield;
+ let shield_dmg = preset.symbol_shield.dmg;
+
+ const book_unit = preset.symbol_book.book;
+ let book_dmg = preset.symbol_book.dmg;
+
+ const burst_unit = preset.symbol_burst.burst;
+ let burst_dmg = preset.symbol_burst.dmg;
+ const burst_dmg_type = preset.symbol_burst.type;
+
+ symbol_damage_step?.forEach((sd) => {
+ shield_dmg += DMG_STEP_3[sd].modifier.shield;
+ book_dmg += DMG_STEP_3[sd].modifier.book;
+ burst_dmg += DMG_STEP_3[sd].modifier.burst;
+ });
+
+ let physical_symbol_dmg =
+ Number.parseInt(totalShield / shield_unit) * shield_dmg;
+ let magic_symbol_dmg = Number.parseInt(totalBook / book_unit) * book_dmg;
+ let burst_damge = Number.parseInt(totalBurst / burst_unit) * burst_dmg;
+ if (burst_dmg_type === "PHYSICAL") {
+ physical_symbol_dmg += burst_damge;
+ } else {
+ magic_symbol_dmg += burst_damge;
+ }
+ console.log("=== symbol dmg ===", physical_symbol_dmg, magic_symbol_dmg);
+
+ //4.计算最终伤害
+
+ return {
+ physical: 0,
+ magic: 0,
+ };
+};
diff --git a/src/GlobalStore/index.js b/src/GlobalStore/index.js
index 4dace31..6d1aec1 100644
--- a/src/GlobalStore/index.js
+++ b/src/GlobalStore/index.js
@@ -1,20 +1,9 @@
-import { create } from 'zustand';
-import { uid } from 'uid';
-import { ENEMY_COLLECTION } from './EnemyCollection';
-import { WEAPON_CONFIG } from './WeaponConfig';
-import { DICE_COLOR_SET } from './DiceColorSet';
-
-// const flattenCollection = () => {
-// let result = [];
-// console.log(ENEMY_COLLECTION);
-// Object.keys(ENEMY_COLLECTION)?.forEach((key) =>
-// result.push({
-// type: key,
-// ...ENEMY_COLLECTION[key],
-// })
-// );
-// return result;
-// };
+import { create } from "zustand";
+import { uid } from "uid";
+import { ENEMY_COLLECTION } from "./EnemyCollection";
+import { WEAPON_CONFIG } from "./WeaponConfig";
+import { DICE_COLOR_SET } from "./DiceColorSet";
+import { calculate } from "./calculator";
// {
// activeEnemy:{},
@@ -29,77 +18,92 @@ import { DICE_COLOR_SET } from './DiceColorSet';
// }
const useGlobalStore = create((set) => {
- const addEnemy = (enemy) => {
- set((state) => {
- const se = [...state.selectedEnemy];
- se.push({
- id: uid(),
- ...enemy,
- });
- return { selectedEnemy: se };
- });
- };
+ const addEnemy = (enemy) => {
+ set((state) => {
+ const se = [...state.selectedEnemy];
+ se.push({
+ id: uid(),
+ ...enemy,
+ });
+ return { selectedEnemy: se };
+ });
+ };
+
+ const removeEnemyByType = (enemyType) => {
+ set(({ selectedEnemy }) => {
+ const se = [...selectedEnemy];
+ const foeIndex = se.findIndex((foe) => foe.type === enemyType);
+ if (foeIndex !== -1) {
+ se.splice(foeIndex, 1);
+ return { selectedEnemy: se };
+ }
+ });
+ };
- const removeEnemyByType = (enemyType) => {
- set(({ selectedEnemy }) => {
- const se = [...selectedEnemy];
- const foeIndex = se.findIndex((foe) => foe.type === enemyType);
- if (foeIndex !== -1) {
- se.splice(foeIndex, 1);
- return { selectedEnemy: se };
- }
- });
- };
+ const removeEnemyById = (enemyId) => {
+ set(({ selectedEnemy }) => {
+ const se = [...selectedEnemy];
+ const foeIndex = se.findIndex((foe) => foe.id === enemyId);
+ if (foeIndex !== -1) {
+ se.splice(foeIndex, 1);
+ return { selectedEnemy: se };
+ }
+ });
+ };
- const removeEnemyById = (enemyId) => {
- set(({ selectedEnemy }) => {
- const se = [...selectedEnemy];
- const foeIndex = se.findIndex((foe) => foe.id === enemyId);
- if (foeIndex !== -1) {
- se.splice(foeIndex, 1);
- return { selectedEnemy: se };
- }
- });
- };
+ const setActiveEnemy = (enemy) => {
+ set(() => ({ activeEnemy: enemy }));
+ };
- const setActiveEnemy = (enemy) => {
- set(() => ({ activeEnemy: enemy }));
- };
+ const setActiveAlly = (allyName) => {
+ set(() => ({ activeAlly: allyName }));
+ };
- const setActiveAlly = (allyName) => {
- set(() => ({ activeAlly: allyName }));
- };
+ const updateEnemyStatus = ({ id, status }) => {
+ set(({ selectedEnemy }) => {
+ const se = [...selectedEnemy];
+ const target = se.find((foe) => foe.id === id);
+ target.status = status;
+ return { selectedEnemy: se };
+ });
+ };
- const updateEnemyStatus = ({ id, status }) => {
- set(({ selectedEnemy }) => {
- const se = [...selectedEnemy];
- const target = se.find((foe) => foe.id === id);
- target.status = status;
- return { selectedEnemy: se };
- });
- };
+ const updateAllySave = (data) => {
+ set(({ activeAlly, allySave }) => ({
+ allySave: { ...allySave, [activeAlly]: data },
+ }));
+ };
- const updateAllySave = (data) => {
- set(({ activeAlly, allySave }) => ({
- allySave: { ...allySave, [activeAlly]: data },
- }));
- };
+ const calculateDamage = () => {
+ set(({ activeEnemy, activeAlly, allySave }) => ({
+ totalDamge: calculate({
+ enemy: activeEnemy,
+ preset: allySave[activeAlly].preset,
+ userInput: allySave[activeAlly].userInput,
+ }),
+ }));
+ };
- return {
- allySave: {},
- activeEnemy: null,
- setActiveEnemy,
- activeAlly: '',
- setActiveAlly,
- selectedEnemy: [],
- addEnemy,
- removeEnemyByType,
- removeEnemyById,
- updateEnemyStatus,
- updateAllySave,
- };
+ return {
+ totalDamge: {
+ physical: 0,
+ magic: 0,
+ },
+ allySave: {},
+ activeEnemy: null,
+ setActiveEnemy,
+ activeAlly: "",
+ setActiveAlly,
+ selectedEnemy: [],
+ addEnemy,
+ removeEnemyByType,
+ removeEnemyById,
+ updateEnemyStatus,
+ updateAllySave,
+ calculateDamage,
+ };
});
export { ENEMY_COLLECTION, WEAPON_CONFIG, DICE_COLOR_SET };
-export const ALLY_COLLECTION = ['REMI', 'NIGHTINGALE', 'ROOK', 'ZEKE'];
+export const ALLY_COLLECTION = ["REMI", "NIGHTINGALE", "ROOK", "ZEKE"];
export default useGlobalStore;
diff --git a/src/comps/Dice/BlackDice.jsx b/src/comps/Dice/BlackDice.jsx
index c3a9596..7bc1846 100644
--- a/src/comps/Dice/BlackDice.jsx
+++ b/src/comps/Dice/BlackDice.jsx
@@ -1,82 +1,88 @@
-import React from 'react';
-import css from './css.module.css';
-import Icon from '../Icon';
+import React from "react";
+import css from "./css.module.css";
+import Icon from "../Icon";
const PRESET = {
- 1: {
- shield: 2,
- book: 2,
- },
- 2: {
- shield: 1,
- book: 3,
- },
- 3: {
- shield: 3,
- book: 1,
- },
- 4: {
- shield: 4,
- book: 0,
- },
- 5: {
- shield: 0,
- book: 4,
- },
- 6: {
- shield: 0,
- book: 0,
- },
+ 1: {
+ shield: 2,
+ book: 2,
+ burst: 0,
+ },
+ 2: {
+ shield: 1,
+ book: 3,
+ burst: 0,
+ },
+ 3: {
+ shield: 3,
+ book: 1,
+ burst: 0,
+ },
+ 4: {
+ shield: 4,
+ book: 0,
+ burst: 0,
+ },
+ 5: {
+ shield: 0,
+ book: 4,
+ burst: 0,
+ },
+ 6: {
+ shield: 0,
+ book: 0,
+ burst: 0,
+ },
};
const BlackDice = ({ width = 90, value = 6, onChange }) => {
- return (
-
onChange?.(PRESET[value])}
- >
- {value === 6 && (
-
-
-
- )}
-
-
- {[1, 3, 4].includes(value) && (
-
- )}
- {[2, 5].includes(value) && (
-
- )}
-
-
- {[1, 2, 3, 4].includes(value) && (
-
- )}
- {value === 5 && }
-
-
- {value === 4 && }
- {[1, 2, 3, 5].includes(value) && (
-
- )}
-
-
- {[1, 2, 5].includes(value) && (
-
- )}
- {[3, 4].includes(value) && (
-
- )}
-
+ return (
+
onChange?.(PRESET[value])}
+ >
+ {value === 6 && (
+
+
- );
+ )}
+
+
+ {[1, 3, 4].includes(value) && (
+
+ )}
+ {[2, 5].includes(value) && (
+
+ )}
+
+
+ {[1, 2, 3, 4].includes(value) && (
+
+ )}
+ {value === 5 && }
+
+
+ {value === 4 && }
+ {[1, 2, 3, 5].includes(value) && (
+
+ )}
+
+
+ {[1, 2, 5].includes(value) && (
+
+ )}
+ {[3, 4].includes(value) && (
+
+ )}
+
+
+ );
};
export default BlackDice;
diff --git a/src/comps/Dice/preset.js b/src/comps/Dice/preset.js
index aea3cb1..44ec4d6 100644
--- a/src/comps/Dice/preset.js
+++ b/src/comps/Dice/preset.js
@@ -72,7 +72,7 @@ let DICE_SET = {
10: {
shield: 1,
book: 2,
- burst: 0,
+ burst: 1,
},
},
};
diff --git a/src/comps/Icon/index.jsx b/src/comps/Icon/index.jsx
index b2470cb..4bdf434 100644
--- a/src/comps/Icon/index.jsx
+++ b/src/comps/Icon/index.jsx
@@ -1,114 +1,113 @@
let Icon = {};
Icon.Shield = ({ size, color, style }) => {
- return (
-
- );
+ return (
+
+ );
};
Icon.Book = ({ size, color, style }) => {
- return (
-
- );
+ return (
+
+ );
};
Icon.Burst = ({ size, color, style }) => {
- return (
-
- );
+ return (
+
+ );
};
Icon.Skull = ({ size, color, style }) => {
- return (
-
- );
+ return (
+
+ );
};
Icon.Status = ({ size, color, style }) => {
- return (
-
- );
+ return (
+
+ );
};
export default Icon;