HumanBreak/src/game/state/item.ts

147 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-08-01 21:39:33 +08:00
import EventEmitter from 'eventemitter3';
import type { Hero } from './hero';
2024-08-04 16:19:21 +08:00
import { GameState, gameStates } from './state';
2024-08-01 21:39:33 +08:00
import { loading } from '../game';
2024-08-04 16:19:21 +08:00
type EffectFn = (state: GameState, hero: Hero<any>) => void;
type CanUseEffectFn = (state: GameState, hero: Hero<any>) => boolean;
2024-08-01 21:39:33 +08:00
interface ItemStateEvent {
use: [hero: Hero<any>];
}
export class ItemState<
I extends AllIdsOf<'items'> = AllIdsOf<'items'>
> extends EventEmitter<ItemStateEvent> {
static items: Map<AllIdsOf<'items'>, ItemState> = new Map();
id: I;
cls: ItemClsOf<I>;
name: string;
text?: string;
hideInToolBox: boolean;
hideInReplay: boolean;
/** 即捡即用效果 */
itemEffect?: string;
/** 即捡即用道具捡过之后的提示 */
itemEffectTip?: string;
/** 使用道具时执行的事件 */
useItemEvent?: MotaEvent;
/** 使用道具时执行的代码 */
useItemEffect?: string;
/** 能否使用道具 */
canUseItemEffect?: string | boolean;
private noRoute: boolean = false;
itemEffectFn?: EffectFn;
useItemEffectFn?: EffectFn;
canUseItemEffectFn?: CanUseEffectFn;
constructor(id: I) {
super();
const items = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a;
this.id = id;
const item = items[id];
this.cls = item.cls;
this.name = item.name;
this.text = item.text;
this.hideInToolBox = item.hideInToolBox;
this.hideInReplay = item.hideInReplay;
this.itemEffect = item.itemEffect;
this.itemEffectTip = item.itemEffectTip;
this.useItemEvent = item.useItemEvent;
this.useItemEffect = item.useItemEffect;
this.canUseItemEffect = item.canUseItemEffect;
this.compileFunction();
this.compileEvent();
}
private compileFunction() {
if (this.itemEffect) {
this.itemEffectFn = new Function(
`state`,
this.itemEffect
) as EffectFn;
}
if (this.useItemEffect) {
this.useItemEffectFn = new Function(
`state`,
this.useItemEffect
) as EffectFn;
}
if (this.canUseItemEffect) {
if (typeof this.canUseItemEffect === 'boolean') {
this.canUseItemEffectFn = () =>
this.canUseItemEffect as boolean;
} else {
this.useItemEffectFn = new Function(
`state`,
this.canUseItemEffect
) as CanUseEffectFn;
}
}
}
private compileEvent() {
// todo
}
/**
* 使
2024-08-04 16:19:21 +08:00
* @param hero 使
2024-08-01 21:39:33 +08:00
*/
use(hero: Hero<any>): boolean {
if (!this.canUse(hero)) return false;
if (!gameStates.now) return false;
2024-08-04 16:19:21 +08:00
const state = gameStates.now;
2024-08-01 21:39:33 +08:00
this.useItemEffectFn?.(state, hero);
if (this.useItemEvent) core.insertAction(this.useItemEvent);
2024-08-04 16:19:21 +08:00
if (!this.noRoute) {
2024-08-04 19:57:39 +08:00
core.status.route.push(`item:${this.id}`);
2024-08-04 16:19:21 +08:00
}
2024-08-01 21:39:33 +08:00
hero.addItem(this.id, -1);
this.emit('use', hero);
return true;
}
/**
* 使
* @param hero 使
*/
canUse(hero: Hero<any>, num: number = 1): boolean {
if (num <= 0) return false;
if (hero.itemCount(this.id) < num) return false;
if (!gameStates.now) return false;
2024-08-04 16:19:21 +08:00
return !!this.canUseItemEffectFn?.(gameStates.now, hero);
2024-08-01 21:39:33 +08:00
}
/**
* 使
*/
markNoRoute() {
this.noRoute = true;
}
/**
*
* @param id id
*/
static item<I extends AllIdsOf<'items'>>(id: I): ItemState<I> | undefined {
return this.items.get(id) as ItemState<I>;
}
}
loading.once('coreInit', () => {
for (const key of Object.keys(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a)) {
ItemState.items.set(
key as AllIdsOf<'items'>,
new ItemState(key as AllIdsOf<'items'>)
);
}
});