fix: 设置

This commit is contained in:
unanmed 2024-02-02 20:21:17 +08:00
parent a825b268bc
commit c61e789ddf
11 changed files with 253 additions and 208 deletions

View File

@ -24,8 +24,6 @@ type EmitFn<F extends (...params: any) => any> = (
...params: Parameters<F> ...params: Parameters<F>
) => any; ) => any;
console.log(1);
export class EventEmitter<T extends EmitableEvent = {}> { export class EventEmitter<T extends EmitableEvent = {}> {
protected events: { protected events: {
[P in keyof T]?: Listener<T[P]>[]; [P in keyof T]?: Listener<T[P]>[];

View File

@ -40,8 +40,6 @@ export interface HotkeyJSON {
assist: number; assist: number;
} }
console.log(2);
export class Hotkey extends EventEmitter<HotkeyEvent> { export class Hotkey extends EventEmitter<HotkeyEvent> {
static list: Hotkey[]; static list: Hotkey[];

View File

@ -48,7 +48,7 @@ function BooleanSetting(props: SettingComponentProps) {
size="large" size="large"
onClick={changeValue} onClick={changeValue}
> >
{item.value ? '开启' : '关闭'} {item.value ? '关闭' : '开启'}
</Button> </Button>
</div> </div>
); );
@ -56,24 +56,51 @@ function BooleanSetting(props: SettingComponentProps) {
function NumberSetting(props: SettingComponentProps) { function NumberSetting(props: SettingComponentProps) {
const { setting, displayer, item } = props; const { setting, displayer, item } = props;
const changeValue = () => { const changeValue = (value: number) => {
setting.setValue(displayer.selectStack.join('.'), !item.value); if (typeof value !== 'number') return;
setting.setValue(displayer.selectStack.join('.'), value);
displayer.update(); displayer.update();
}; };
return ( return (
<div class="editor-number"> <div class="editor-number">
<span> </span> <div class="editor-number-input">
<InputNumber <span> </span>
class="number-input" <InputNumber
size="large" class="number-input"
keyboard={true} size="large"
min={item.step?.[0] ?? 0} // keyboard={true}
max={item.step?.[1] ?? 100} min={item.step?.[0] ?? 0}
step={item.step?.[2] ?? 1} max={item.step?.[1] ?? 100}
value={item.value as number} step={item.step?.[2] ?? 1}
onChange={changeValue} value={item.value as number}
></InputNumber> onChange={value => changeValue(value as number)}
></InputNumber>
</div>
<div class="editor-number-button">
<Button
class="number-button"
type="primary"
onClick={() =>
changeValue(
(item.value as number) - (item.step?.[2] ?? 1)
)
}
>
</Button>
<Button
class="number-button"
type="primary"
onClick={() =>
changeValue(
(item.value as number) + (item.step?.[2] ?? 1)
)
}
>
</Button>
</div>
</div> </div>
); );
} }

View File

@ -124,6 +124,7 @@ export class MotaSetting extends EventEmitter<SettingEvent> {
} }
const old = setting.value as boolean | number; const old = setting.value as boolean | number;
setting.value = value; setting.value = value;
this.emit('valueChange', key, value, old); this.emit('valueChange', key, value, old);
} }
@ -472,7 +473,7 @@ mainSetting
'小地图楼传缩放', '小地图楼传缩放',
300, 300,
COM.Number, COM.Number,
[50, 50, 1000] [50, 1000, 50]
) )
); );

View File

@ -23,174 +23,182 @@ export function getEnemy(
return enemy; return enemy;
} }
export function canBattle(
x: number,
y: number,
floorId: FloorIds = core.status.floorId
) {
const enemy = getEnemy(x, y, floorId);
const { damage } = enemy.calDamage();
return damage < core.status.hero.hp;
}
export function battle(
x: number,
y: number,
force: boolean = false,
callback?: () => void
) {
core.saveAndStopAutomaticRoute();
const enemy = getEnemy(x, y);
// 非强制战斗
if (!canBattle(x, y) && !force && !core.status.event.id) {
core.stopSound();
core.playSound('操作失败');
core.drawTip('你打不过此怪物!', enemy.id);
return core.clearContinueAutomaticRoute(callback);
}
// 自动存档
if (!core.status.event.id) core.autosave(true);
// 战前事件
// 战后事件
afterBattle(enemy, x, y);
callback?.();
}
export function afterBattle(enemy: DamageEnemy, x?: number, y?: number) {
const floorId = core.status.floorId;
const special = enemy.info.special;
// 播放战斗动画
let animate: AnimationIds = 'hand';
// 检查当前装备是否存在攻击动画
const equipId = core.getEquip(0);
if (equipId && (core.material.items[equipId].equip || {}).animate)
animate = core.material.items[equipId].equip.animate;
// 检查该动画是否存在SE如果不存在则使用默认音效
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
// 战斗伤害
const info = enemy.calDamage(core.status.hero);
const damage = info.damage;
// 判定是否致死
if (damage >= core.status.hero.hp) {
core.status.hero.hp = 0;
core.updateStatusBar(false, true);
core.events.lose('战斗失败');
return;
}
// 扣减体力值并记录统计数据
core.status.hero.hp -= damage;
core.status.hero.statistics.battleDamage += damage;
core.status.hero.statistics.battle++;
// 智慧之源
if (special.includes(14) && flags.hard === 2) {
core.addFlag(
'inte_' + floorId,
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
);
core.status.hero.mdef -=
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
}
// 极昼永夜
if (special.includes(22)) {
flags[`night_${floorId}`] ??= 0;
flags[`night_${floorId}`] -= enemy.enemy.night!;
}
if (special.includes(23)) {
flags[`night_${floorId}`] ??= 0;
flags[`night_${floorId}`] += enemy.enemy.day;
}
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
// core.plugin.study.declineStudiedSkill();
// }
// 如果是融化怪,需要特殊标记一下
if (special.includes(25) && has(x) && has(y)) {
flags[`melt_${floorId}`] ??= {};
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
}
// 获得金币
const money = enemy.enemy.money;
core.status.hero.money += money;
core.status.hero.statistics.money += money;
// 获得经验
const exp = enemy.enemy.exp;
core.status.hero.exp += exp;
core.status.hero.statistics.exp += exp;
const hint =
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
core.drawTip(hint, enemy.id);
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
core.setFlag('blade', false);
}
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
core.setFlag('shield', false);
}
// 事件的处理
const todo: MotaEvent = [];
// 战后事件
if (has(core.status.floorId)) {
const loc = `${x},${y}` as LocString;
todo.push(...(core.floors[core.status.floorId].afterBattle[loc] ?? []));
}
todo.push(...(enemy.enemy.afterBattle ?? []));
// 如果事件不为空,将其插入
if (todo.length > 0) core.insertAction(todo, x, y);
if (has(x) && has(y)) {
core.drawAnimate(animate, x, y);
core.removeBlock(x, y);
} else core.drawHeroAnimate(animate);
// 如果已有事件正在处理中
if (core.status.event.id == null) core.continueAutomaticRoute();
else core.clearContinueAutomaticRoute();
}
export function getCurrentEnemys(floorId = core.status.floorId) {
floorId = floorId || core.status.floorId;
const enemys: CurrentEnemy[] = [];
const used: Record<string, DamageEnemy[]> = {};
ensureFloorDamage(floorId);
const floor = core.status.maps[floorId];
floor.enemy.list.forEach(v => {
if (!(v.id in used)) {
const e = new DamageEnemy(v.enemy);
e.calAttribute();
e.getRealInfo();
e.calDamage();
const curr: CurrentEnemy = {
enemy: e,
onMapEnemy: [v]
};
enemys.push(curr);
used[v.id] = curr.onMapEnemy;
} else {
used[v.id].push(v);
}
});
return enemys.sort((a, b) => {
const ad = a.enemy.calDamage().damage;
const bd = b.enemy.calDamage().damage;
return ad - bd;
});
}
function init() { function init() {
core.enemys.canBattle = function canBattle(
x: number,
y: number,
floorId: FloorIds = core.status.floorId
) {
const enemy = getEnemy(x, y, floorId);
const { damage } = enemy.calDamage();
return damage < core.status.hero.hp;
};
core.events.battle = function battle(
x: number,
y: number,
force: boolean = false,
callback?: () => void
) {
core.saveAndStopAutomaticRoute();
const enemy = getEnemy(x, y);
// 非强制战斗
if (!core.canBattle(x, y) && !force && !core.status.event.id) {
core.stopSound();
core.playSound('操作失败');
core.drawTip('你打不过此怪物!', enemy.id);
return core.clearContinueAutomaticRoute(callback);
}
// 自动存档
if (!core.status.event.id) core.autosave(true);
// 战前事件
// 战后事件
core.afterBattle(enemy, x, y);
callback?.();
};
core.events.afterBattle = function afterBattle(
enemy: DamageEnemy,
x?: number,
y?: number
) {
const floorId = core.status.floorId;
const special = enemy.info.special;
// 播放战斗动画
let animate: AnimationIds = 'hand';
// 检查当前装备是否存在攻击动画
const equipId = core.getEquip(0);
if (equipId && (core.material.items[equipId].equip || {}).animate)
animate = core.material.items[equipId].equip.animate;
// 检查该动画是否存在SE如果不存在则使用默认音效
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
// 战斗伤害
const info = enemy.calDamage(core.status.hero);
const damage = info.damage;
// 判定是否致死
if (damage >= core.status.hero.hp) {
core.status.hero.hp = 0;
core.updateStatusBar(false, true);
core.events.lose('战斗失败');
return;
}
// 扣减体力值并记录统计数据
core.status.hero.hp -= damage;
core.status.hero.statistics.battleDamage += damage;
core.status.hero.statistics.battle++;
// 智慧之源
if (special.includes(14) && flags.hard === 2) {
core.addFlag(
'inte_' + floorId,
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
);
core.status.hero.mdef -=
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
}
// 极昼永夜
if (special.includes(22)) {
flags[`night_${floorId}`] ??= 0;
flags[`night_${floorId}`] -= enemy.enemy.night!;
}
if (special.includes(23)) {
flags[`night_${floorId}`] ??= 0;
flags[`night_${floorId}`] += enemy.enemy.day;
}
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
// core.plugin.study.declineStudiedSkill();
// }
// 如果是融化怪,需要特殊标记一下
if (special.includes(25) && has(x) && has(y)) {
flags[`melt_${floorId}`] ??= {};
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
}
// 获得金币
const money = enemy.enemy.money;
core.status.hero.money += money;
core.status.hero.statistics.money += money;
// 获得经验
const exp = enemy.enemy.exp;
core.status.hero.exp += exp;
core.status.hero.statistics.exp += exp;
const hint =
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
core.drawTip(hint, enemy.id);
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
core.setFlag('blade', false);
}
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
core.setFlag('shield', false);
}
// 事件的处理
const todo: MotaEvent = [];
// 战后事件
if (has(core.status.floorId)) {
const loc = `${x},${y}` as LocString;
todo.push(
...(core.floors[core.status.floorId].afterBattle[loc] ?? [])
);
}
todo.push(...(enemy.enemy.afterBattle ?? []));
// 如果事件不为空,将其插入
if (todo.length > 0) core.insertAction(todo, x, y);
if (has(x) && has(y)) {
core.drawAnimate(animate, x, y);
core.removeBlock(x, y);
} else core.drawHeroAnimate(animate);
// 如果已有事件正在处理中
if (core.status.event.id == null) core.continueAutomaticRoute();
else core.clearContinueAutomaticRoute();
};
core.enemys.getCurrentEnemys = function getCurrentEnemys(
floorId = core.status.floorId
) {
floorId = floorId || core.status.floorId;
const enemys: CurrentEnemy[] = [];
const used: Record<string, DamageEnemy[]> = {};
ensureFloorDamage(floorId);
const floor = core.status.maps[floorId];
floor.enemy.list.forEach(v => {
if (!(v.id in used)) {
const e = new DamageEnemy(v.enemy);
e.calAttribute();
e.getRealInfo();
e.calDamage();
const curr: CurrentEnemy = {
enemy: e,
onMapEnemy: [v]
};
enemys.push(curr);
used[v.id] = curr.onMapEnemy;
} else {
used[v.id].push(v);
}
});
return enemys.sort((a, b) => {
const ad = a.enemy.calDamage().damage;
const bd = b.enemy.calDamage().damage;
return ad - bd;
});
};
core.events._sys_battle = function (data: Block, callback?: () => void) { core.events._sys_battle = function (data: Block, callback?: () => void) {
// 检查战前事件 // 检查战前事件
const floor = core.floors[core.status.floorId]; const floor = core.floors[core.status.floorId];
@ -215,7 +223,7 @@ function init() {
core.insertAction(beforeBattle, data.x, data.y, callback); core.insertAction(beforeBattle, data.x, data.y, callback);
} }
} else { } else {
battle(data.x, data.y, false, callback); core.battle(data.x, data.y, false, callback);
} }
}; };
@ -234,8 +242,14 @@ function init() {
y, y,
prefix prefix
) as LocArr; ) as LocArr;
battle(ex, ey, true, core.doAction); core.battle(ex, ey, true, core.doAction);
} }
}; };
} }
loading.once('coreInit', init); loading.once('coreInit', init);
declare global {
interface Enemys {
getCurrentEnemys(floorId: FloorIds): CurrentEnemy[];
}
}

View File

@ -14,11 +14,7 @@ Mota.register('class', 'EventEmitter', EventEmitter);
Mota.register('class', 'IndexedEventEmitter', IndexedEventEmitter); Mota.register('class', 'IndexedEventEmitter', IndexedEventEmitter);
Mota.register('class', 'Range', Range); Mota.register('class', 'Range', Range);
// ----- 函数注册 // ----- 函数注册
Mota.register('fn', 'battle', battle.battle);
Mota.register('fn', 'getEnemy', battle.getEnemy); Mota.register('fn', 'getEnemy', battle.getEnemy);
Mota.register('fn', 'afterBattle', battle.afterBattle);
Mota.register('fn', 'canBattle', battle.canBattle);
Mota.register('fn', 'getCurrentEnemys', battle.getCurrentEnemys);
// ----- 变量注册 // ----- 变量注册
Mota.register('var', 'enemySpecials', specials); Mota.register('var', 'enemySpecials', specials);
Mota.register('var', 'hook', hook); Mota.register('var', 'hook', hook);

View File

@ -25,11 +25,12 @@ const MAX_ROTATE = 0.5;
const FRAG_TIMING = linear(); const FRAG_TIMING = linear();
export function init() { export function init() {
const fn = Mota.requireAll('fn'); Mota.rewrite(core.events, 'afterBattle', 'add', (_, enemy, x, y) => {
Mota.rewrite(fn, 'afterBattle', 'add', (_, enemy, x, y) => {
// 打怪特效 // 打怪特效
const setting = Mota.require('var', 'mainSetting'); const setting = Mota.require('var', 'mainSetting');
if (setting.getValue('screen.frag') && has(x) && has(y)) { console.log(setting.getValue('fx.frag'));
if (setting.getValue('fx.frag') && has(x) && has(y)) {
const frame = core.status.globalAnimateStatus % 2; const frame = core.status.globalAnimateStatus % 2;
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = 32; canvas.width = 32;

View File

@ -29,7 +29,7 @@ export function getDetailedEnemy(
return typeof func === 'string' ? func : func(enemy); return typeof func === 'string' ? func : func(enemy);
}; };
const special: [string, string, string][] = enemy.enemy.special.map(vv => { const special: [string, string, string][] = enemy.enemy.special.map(vv => {
const s = Mota.Plugin.require('special_g').special[vv]; const s = Mota.require('var', 'enemySpecials')[vv];
return [ return [
fromFunc(s.name, enemy.enemy), fromFunc(s.name, enemy.enemy),
fromFunc(s.desc, enemy.enemy), fromFunc(s.desc, enemy.enemy),

View File

@ -110,11 +110,7 @@ interface EventData {
* @param x * @param x
* @param y * @param y
*/ */
afterBattle( afterBattle(enemyId: any, x?: number, y?: number): void;
enemyId: AllIdsOf<'enemys' | 'enemy48'>,
x?: number,
y?: number
): void;
/** /**
* *

View File

@ -83,7 +83,7 @@ const special = (() => {
}; };
const show = s.slice(0, 2).map(v => { const show = s.slice(0, 2).map(v => {
const s = Mota.Plugin.require('special_g').specials[v]; const s = Mota.require('var', 'enemySpecials')[v];
return [fromFunc(s.name, enemy.enemy), s.color]; return [fromFunc(s.name, enemy.enemy), s.color];
}); });
if (s.length > 2) show.push(['...', 'white']); if (s.length > 2) show.push(['...', 'white']);

View File

@ -58,6 +58,7 @@
:item="selectedItem" :item="selectedItem"
:displayer="displayer" :displayer="displayer"
:setting="setting" :setting="setting"
:update="update"
></component> ></component>
</div> </div>
</div> </div>
@ -67,7 +68,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, onUnmounted, shallowRef } from 'vue'; import { computed, onMounted, onUnmounted, ref, shallowRef } from 'vue';
import { import {
mainSetting, mainSetting,
MotaSetting, MotaSetting,
@ -78,11 +79,9 @@ import {
} from '../core/main/setting'; } from '../core/main/setting';
import settingText from '../data/settings.json'; import settingText from '../data/settings.json';
import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue'; import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue';
import { keycode, splitText } from '../plugin/utils'; import { splitText } from '../plugin/utils';
import Scroll from '../components/scroll.vue'; import Scroll from '../components/scroll.vue';
import { isMobile } from '../plugin/use'; import { isMobile } from '../plugin/use';
import { sleep } from 'mutate-animate';
import { KeyCode } from '../plugin/keyCodes';
import { gameKey } from '@/core/main/init/hotkey'; import { gameKey } from '@/core/main/init/hotkey';
import { GameUi } from '@/core/main/custom/ui'; import { GameUi } from '@/core/main/custom/ui';
import { mainUi } from '@/core/main/init/ui'; import { mainUi } from '@/core/main/init/ui';
@ -98,10 +97,12 @@ const setting = props.info ?? mainSetting;
const text = props.text ?? (settingText as SettingText); const text = props.text ?? (settingText as SettingText);
const display = shallowRef<SettingDisplayInfo[]>([]); const display = shallowRef<SettingDisplayInfo[]>([]);
const selectedItem = computed(() => display.value.at(-1)?.item); const selectedItem = computed(() => display.value.at(-1)?.item);
const update = ref(false);
const displayer = new SettingDisplayer(setting, text); const displayer = new SettingDisplayer(setting, text);
displayer.on('update', (stack, dis) => { displayer.on('update', (stack, dis) => {
display.value = dis; display.value = dis;
update.value = !update.value;
}); });
display.value = displayer.displayInfo; display.value = displayer.displayInfo;
@ -276,15 +277,28 @@ onUnmounted(() => {
.setting-info::v-deep(.editor-number) { .setting-info::v-deep(.editor-number) {
display: flex; display: flex;
flex-direction: row; flex-direction: column;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
padding: 0 10% 0 5%; padding: 0 10% 0 5%;
.number-input { .number-input,
.number-button {
font-size: 80%; font-size: 80%;
width: 40%; width: 40%;
} }
.number-button {
height: 100%;
}
.editor-number-button {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-around;
margin-top: 10px;
}
} }
.setting-info { .setting-info {