mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-09-23 15:41:48 +08:00
Compare commits
No commits in common. "574d765c699148b9a920bebf64fedbec13b0493e" and "b7c7cdeca03eed56f0cbbf603f717d9009918c9c" have entirely different histories.
574d765c69
...
b7c7cdeca0
@ -434,85 +434,36 @@ gameKey
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
// #region 存档界面
|
||||
.group('@ui_save', '存档界面')
|
||||
.group('@ui_save', 'save')
|
||||
.register({
|
||||
id: '@save_pageUp',
|
||||
name: '向后翻页',
|
||||
name: '存档向后翻页',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
.register({
|
||||
id: '@save_pageDown',
|
||||
name: '向前翻页',
|
||||
name: '存档向前翻页',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@save_up',
|
||||
name: '选择框向上',
|
||||
name: '存档选择框向上',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_down',
|
||||
name: '选择框向下',
|
||||
name: '存档选择框向下',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_left',
|
||||
name: '选择框向左',
|
||||
name: '存档选择框向左',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_right',
|
||||
name: '选择框向右',
|
||||
name: '存档选择框向右',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
//#region 浏览地图
|
||||
.group('@ui_viewMap', '浏览地图')
|
||||
.register({
|
||||
id: '@viewMap_up_1',
|
||||
name: '下一层地图_1',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_up_2',
|
||||
name: '下一层地图_2',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_1',
|
||||
name: '上一层地图_1',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_2',
|
||||
name: '上一层地图_2',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_up_ten',
|
||||
name: '下十层地图',
|
||||
defaults: KeyCode.UpArrow,
|
||||
ctrl: true
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_ten',
|
||||
name: '上十层地图',
|
||||
defaults: KeyCode.DownArrow,
|
||||
ctrl: true
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_book',
|
||||
name: '怪物手册',
|
||||
defaults: KeyCode.KeyX
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_fly',
|
||||
name: '传送至',
|
||||
defaults: KeyCode.KeyG
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_reset',
|
||||
name: '重置视角',
|
||||
defaults: KeyCode.KeyR
|
||||
});
|
||||
// #endregion
|
||||
|
||||
@ -541,6 +492,9 @@ gameKey
|
||||
.realize('shop', () => {
|
||||
core.openQuickShop(true);
|
||||
})
|
||||
.realize('viewMap', () => {
|
||||
core.ui._drawViewMaps();
|
||||
})
|
||||
.realize('skillTree', () => {
|
||||
core.useItem('skill1', true);
|
||||
})
|
||||
|
@ -6,8 +6,7 @@ import {
|
||||
openStatistics,
|
||||
saveLoad,
|
||||
openSettings,
|
||||
ReplaySettingsUI,
|
||||
openViewMap
|
||||
ReplaySettingsUI
|
||||
} from './ui';
|
||||
|
||||
export function createAction() {
|
||||
@ -28,8 +27,5 @@ export function createAction() {
|
||||
mainUIController.open(ReplaySettingsUI, {
|
||||
loc: [420, 240, void 0, void 0, 0.5, 0.5]
|
||||
});
|
||||
})
|
||||
.realize('viewMap', () => {
|
||||
openViewMap(mainUIController, [0, 0, MAIN_WIDTH, MAIN_HEIGHT]);
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DefaultProps } from '@motajs/render-vue';
|
||||
import { SetupComponentOptions } from '@motajs/system-ui';
|
||||
import { clamp, isNil } from 'lodash-es';
|
||||
import { computed, defineComponent, onMounted, ref, watch } from 'vue';
|
||||
import { computed, defineComponent, ref, watch } from 'vue';
|
||||
import { Scroll, ScrollExpose } from './scroll';
|
||||
import { Font } from '@motajs/render-style';
|
||||
import { MotaOffscreenCanvas2D } from '@motajs/render-core';
|
||||
@ -43,23 +43,18 @@ export const FloorSelector = defineComponent<
|
||||
>((props, { emit }) => {
|
||||
const listFont = new Font(Font.defaultFamily, 12);
|
||||
|
||||
/** 当前选中楼层,不反向 */
|
||||
const now = ref(props.now ?? 0);
|
||||
/** 当前鼠标选中楼层,反向 */
|
||||
const selList = ref(0);
|
||||
|
||||
const scrollRef = ref<ScrollExpose>();
|
||||
|
||||
const floors = computed(() => props.floors.toReversed());
|
||||
const floorId = computed(() => floors.value[now.value]);
|
||||
const floorId = computed(() => props.floors[now.value]);
|
||||
const floorName = computed(() => core.floors[floorId.value].title);
|
||||
|
||||
watch(
|
||||
() => props.now,
|
||||
value => {
|
||||
if (!isNil(value)) {
|
||||
changeTo(value);
|
||||
}
|
||||
if (!isNil(value)) now.value = value;
|
||||
}
|
||||
);
|
||||
|
||||
@ -82,14 +77,12 @@ export const FloorSelector = defineComponent<
|
||||
ctx.fillRect(0, 0, 144, 200);
|
||||
};
|
||||
|
||||
const changeTo = (index: number, time: number = 500) => {
|
||||
// 取反是为了符合 2.x 的操作习惯
|
||||
const res = clamp(index, 0, floors.value.length - 1);
|
||||
const reversed = floors.value.length - res - 1;
|
||||
const changeTo = (index: number) => {
|
||||
const res = clamp(index, 0, props.floors.length - 1);
|
||||
now.value = res;
|
||||
selList.value = reversed;
|
||||
const y = reversed * 24;
|
||||
scrollRef.value?.scrollTo(y, time);
|
||||
selList.value = res;
|
||||
const y = res * 24;
|
||||
scrollRef.value?.scrollTo(y, 500);
|
||||
emit('update', now.value, floorId.value);
|
||||
emit('update:now', now.value);
|
||||
};
|
||||
@ -106,10 +99,6 @@ export const FloorSelector = defineComponent<
|
||||
emit('close');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
changeTo(now.value, 0);
|
||||
});
|
||||
|
||||
return () => (
|
||||
<container>
|
||||
<text text={floorName.value} loc={[90, 24]} anc={[0.5, 0.5]} />
|
||||
@ -127,28 +116,28 @@ export const FloorSelector = defineComponent<
|
||||
loc={[90, 70]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={() => changeFloor(10)}
|
||||
onClick={() => changeFloor(-10)}
|
||||
/>
|
||||
<text
|
||||
text="「 上移一层 」"
|
||||
loc={[90, 110]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={() => changeFloor(1)}
|
||||
onClick={() => changeFloor(-1)}
|
||||
/>
|
||||
<text
|
||||
text="「 下移一层 」"
|
||||
loc={[90, 370]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={() => changeFloor(-1)}
|
||||
onClick={() => changeFloor(1)}
|
||||
/>
|
||||
<text
|
||||
text="「 下移十层 」"
|
||||
loc={[90, 410]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={() => changeFloor(-10)}
|
||||
onClick={() => changeFloor(10)}
|
||||
/>
|
||||
<container loc={[0, 140, 144, 200]}>
|
||||
<Scroll
|
||||
@ -158,11 +147,10 @@ export const FloorSelector = defineComponent<
|
||||
zIndex={10}
|
||||
padEnd={88}
|
||||
>
|
||||
{floors.value.map((v, i, a) => {
|
||||
{props.floors.map((v, i) => {
|
||||
const floor = core.floors[v];
|
||||
const reversed = a.length - i - 1;
|
||||
const nowFloor = a.length - now.value - 1;
|
||||
const highlight = nowFloor === i || selList.value === i;
|
||||
const highlight =
|
||||
now.value === i || selList.value === i;
|
||||
const color = highlight ? '#fff' : '#aaa';
|
||||
const fill = highlight ? '#fff' : '#000';
|
||||
return (
|
||||
@ -179,8 +167,8 @@ export const FloorSelector = defineComponent<
|
||||
font={listFont}
|
||||
fillStyle={color}
|
||||
onEnter={() => enterList(i)}
|
||||
onLeave={() => enterList(nowFloor)}
|
||||
onClick={() => changeTo(reversed)}
|
||||
onLeave={() => enterList(now.value)}
|
||||
onClick={() => changeTo(i)}
|
||||
/>
|
||||
<g-circle
|
||||
stroke
|
||||
@ -188,7 +176,7 @@ export const FloorSelector = defineComponent<
|
||||
lineWidth={1}
|
||||
circle={[130, 12, 3]}
|
||||
strokeStyle={color}
|
||||
fillStyle={nowFloor === i ? fill : '#000'}
|
||||
fillStyle={now.value === i ? fill : '#000'}
|
||||
/>
|
||||
</container>
|
||||
);
|
||||
|
@ -37,8 +37,6 @@ export class BlockCacher<
|
||||
width: number;
|
||||
/** 区域高度 */
|
||||
height: number;
|
||||
/** 区域面积 */
|
||||
area: number = 0;
|
||||
/** 分块大小 */
|
||||
blockSize: number;
|
||||
/** 分块信息 */
|
||||
@ -118,7 +116,6 @@ export class BlockCacher<
|
||||
restWidth: this.width % this.blockSize,
|
||||
restHeight: this.height % this.blockSize
|
||||
};
|
||||
this.area = this.blockData.width * this.blockData.height;
|
||||
this.emit('split');
|
||||
}
|
||||
|
||||
@ -306,10 +303,7 @@ export interface ICanvasCacheItem extends IBlockCacheable {
|
||||
}
|
||||
|
||||
export class CanvasCacheItem implements ICanvasCacheItem {
|
||||
constructor(
|
||||
public canvas: MotaOffscreenCanvas2D,
|
||||
public symbol: number
|
||||
) {}
|
||||
constructor(public canvas: MotaOffscreenCanvas2D, public symbol: number) {}
|
||||
|
||||
destroy(): void {}
|
||||
}
|
||||
|
@ -1132,7 +1132,6 @@ export class Layer extends Container<ELayerEvent> {
|
||||
const length = this.backImage.length;
|
||||
const img = this.backImage[frame % length];
|
||||
need.forEach(index => {
|
||||
if (index >= this.block.area || index < 0) return;
|
||||
const x = index % width;
|
||||
const y = Math.floor(index / width);
|
||||
const sx = x * blockSize;
|
||||
|
@ -11,4 +11,3 @@ export * from './settings';
|
||||
export * from './statistics';
|
||||
export * from './statusBar';
|
||||
export * from './toolbar';
|
||||
export * from './viewmap';
|
||||
|
@ -9,7 +9,7 @@ import { waitbox, ListPage, TextContent } from '../components';
|
||||
import { DefaultProps } from '@motajs/render-vue';
|
||||
import { ItemState } from '@user/data-state';
|
||||
|
||||
export interface StatisticsDataOneFloor {
|
||||
interface StatisticsDataOneFloor {
|
||||
enemyCount: number;
|
||||
potionCount: number;
|
||||
gemCount: number;
|
||||
@ -19,7 +19,7 @@ export interface StatisticsDataOneFloor {
|
||||
mdefValue: number;
|
||||
}
|
||||
|
||||
export interface StatisticsData {
|
||||
interface StatisticsData {
|
||||
total: StatisticsDataOneFloor;
|
||||
floors: Map<FloorIds, StatisticsDataOneFloor>;
|
||||
}
|
||||
@ -75,7 +75,7 @@ const statisticsPanelProps = {
|
||||
const TotalStatistics = defineComponent<StatisticsPanelProps>(props => {
|
||||
return () => (
|
||||
<container>
|
||||
<TextContent text="" width={310}></TextContent>
|
||||
<TextContent text='' width={310}></TextContent>
|
||||
</container>
|
||||
);
|
||||
}, statisticsPanelProps);
|
||||
@ -92,99 +92,15 @@ const PotionStatistics = defineComponent<StatisticsPanelProps>(props => {
|
||||
return () => <container></container>;
|
||||
}, statisticsPanelProps);
|
||||
|
||||
export function calculateStatisticsOne(
|
||||
floorId: FloorIds,
|
||||
diff?: Map<string, number>
|
||||
) {
|
||||
core.setFlag('__statistics__', true);
|
||||
const hasDiff = !!diff;
|
||||
if (!hasDiff) {
|
||||
diff = new Map();
|
||||
const hero = core.status.hero;
|
||||
const handler: ProxyHandler<HeroStatus> = {
|
||||
set(target, p, newValue) {
|
||||
if (typeof p !== 'string') return true;
|
||||
if (typeof newValue === 'number') {
|
||||
const value = diff!.get(p) ?? 0;
|
||||
const delta =
|
||||
newValue - (target[p as keyof HeroStatus] as number);
|
||||
diff!.set(p, value + delta);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const proxy = new Proxy(hero, handler);
|
||||
core.status.hero = proxy;
|
||||
}
|
||||
core.extractBlocks(floorId);
|
||||
const statistics: StatisticsDataOneFloor = {
|
||||
enemyCount: 0,
|
||||
potionCount: 0,
|
||||
gemCount: 0,
|
||||
potionValue: 0,
|
||||
atkValue: 0,
|
||||
defValue: 0,
|
||||
mdefValue: 0
|
||||
};
|
||||
if (!diff) return statistics;
|
||||
core.status.maps[floorId].blocks.forEach(v => {
|
||||
if (v.event.cls === 'enemys' || v.event.cls === 'enemy48') {
|
||||
statistics.enemyCount++;
|
||||
} else if (v.event.cls === 'items') {
|
||||
const item = ItemState.items.get(v.event.id as AllIdsOf<'items'>);
|
||||
if (!item) return;
|
||||
if (item.cls === 'items') {
|
||||
try {
|
||||
item.itemEffectFn?.();
|
||||
} catch {
|
||||
// pass
|
||||
}
|
||||
const hp = diff.get('hp') ?? 0;
|
||||
const atk = diff.get('atk') ?? 0;
|
||||
const def = diff.get('def') ?? 0;
|
||||
const mdef = diff.get('mdef') ?? 0;
|
||||
if (hp > 0) {
|
||||
statistics.potionCount++;
|
||||
statistics.potionValue += hp;
|
||||
}
|
||||
if (atk > 0 || def > 0 || mdef > 0) {
|
||||
statistics.gemCount++;
|
||||
}
|
||||
if (atk > 0) {
|
||||
statistics.atkValue += atk;
|
||||
}
|
||||
if (def > 0) {
|
||||
statistics.defValue += def;
|
||||
}
|
||||
if (mdef > 0) {
|
||||
statistics.mdefValue += mdef;
|
||||
}
|
||||
}
|
||||
}
|
||||
diff.clear();
|
||||
});
|
||||
|
||||
if (!hasDiff) {
|
||||
core.status.hero = hero;
|
||||
window.hero = hero;
|
||||
window.flags = core.status.hero.flags;
|
||||
}
|
||||
core.removeFlag('__statistics__');
|
||||
return statistics;
|
||||
}
|
||||
|
||||
export function calculateStatistics(): StatisticsData {
|
||||
function calculateStatistics(): StatisticsData {
|
||||
core.setFlag('__statistics__', true);
|
||||
const hero = core.status.hero;
|
||||
const diff = new Map<string, number>();
|
||||
const diff: Record<string | symbol, number> = {};
|
||||
const handler: ProxyHandler<HeroStatus> = {
|
||||
set(target, p, newValue) {
|
||||
if (typeof p !== 'string') return true;
|
||||
set(_target, p, newValue) {
|
||||
if (typeof newValue === 'number') {
|
||||
const value = diff!.get(p) ?? 0;
|
||||
const delta =
|
||||
newValue - (target[p as keyof HeroStatus] as number);
|
||||
diff!.set(p, value + delta);
|
||||
diff[p] ??= 0;
|
||||
diff[p] += newValue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -194,7 +110,52 @@ export function calculateStatistics(): StatisticsData {
|
||||
|
||||
const floors = new Map<FloorIds, StatisticsDataOneFloor>();
|
||||
core.floorIds.forEach(v => {
|
||||
const statistics = calculateStatisticsOne(v, diff);
|
||||
core.extractBlocks(v);
|
||||
const statistics: StatisticsDataOneFloor = {
|
||||
enemyCount: 0,
|
||||
potionCount: 0,
|
||||
gemCount: 0,
|
||||
potionValue: 0,
|
||||
atkValue: 0,
|
||||
defValue: 0,
|
||||
mdefValue: 0
|
||||
};
|
||||
core.status.maps[v].blocks.forEach(v => {
|
||||
if (v.event.cls === 'enemys' || v.event.cls === 'enemy48') {
|
||||
statistics.enemyCount++;
|
||||
} else if (v.event.cls === 'items') {
|
||||
const item = ItemState.items.get(
|
||||
v.event.id as AllIdsOf<'items'>
|
||||
);
|
||||
if (!item) return;
|
||||
if (item.cls === 'items') {
|
||||
try {
|
||||
item.itemEffectFn?.();
|
||||
} catch {
|
||||
// pass
|
||||
}
|
||||
if (diff.hp > 0) {
|
||||
statistics.potionCount++;
|
||||
statistics.potionValue += diff.hp;
|
||||
}
|
||||
if (diff.atk > 0 || diff.def > 0 || diff.mdef > 0) {
|
||||
statistics.gemCount++;
|
||||
}
|
||||
if (diff.atk > 0) {
|
||||
statistics.atkValue += diff.atk;
|
||||
}
|
||||
if (diff.def > 0) {
|
||||
statistics.defValue += diff.def;
|
||||
}
|
||||
if (diff.mdef > 0) {
|
||||
statistics.mdefValue += diff.mdef;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(diff)) {
|
||||
diff[key] = 0;
|
||||
}
|
||||
});
|
||||
floors.set(v, statistics);
|
||||
});
|
||||
|
||||
|
@ -19,8 +19,6 @@ import {
|
||||
ReplayingToolbar
|
||||
} from './toolbar';
|
||||
import { HeroSkill } from '@user/data-state';
|
||||
import { openViewMap } from './viewmap';
|
||||
import { mainUIController } from './controller';
|
||||
|
||||
export interface ILeftHeroStatus {
|
||||
hp: number;
|
||||
@ -100,10 +98,6 @@ export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
|
||||
return [per * (n + 1), keyY, void 0, void 0, 0.5, 0.5];
|
||||
};
|
||||
|
||||
const viewMap = () => {
|
||||
openViewMap(mainUIController, [0, 0, 840, 480]);
|
||||
};
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<container loc={p.loc} hidden={p.hidden}>
|
||||
@ -112,7 +106,6 @@ export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
|
||||
loc={central(24)}
|
||||
font={font1}
|
||||
cursor="pointer"
|
||||
onClick={viewMap}
|
||||
></text>
|
||||
<text text={s.lv} loc={central(54)} font={font1}></text>
|
||||
<image image={hpIcon} loc={iconLoc(0)}></image>
|
||||
|
@ -332,8 +332,8 @@ export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
|
||||
const createMaskGradient = (ctx: CanvasRenderingContext2D) => {
|
||||
maskGradient = ctx.createLinearGradient(100, 100, 200, 0);
|
||||
maskGradient.addColorStop(0, 'rgba(255,255,255,0)');
|
||||
maskGradient.addColorStop(1, 'rgba(0,0,0,1)');
|
||||
maskGradient.addColorStop(0, '#fff');
|
||||
maskGradient.addColorStop(1, '#000');
|
||||
};
|
||||
|
||||
const createTitleGradient = (ctx: CanvasRenderingContext2D) => {
|
||||
|
@ -1,503 +0,0 @@
|
||||
import {
|
||||
ElementLocator,
|
||||
IActionEvent,
|
||||
IActionEventBase,
|
||||
IWheelEvent,
|
||||
MotaOffscreenCanvas2D
|
||||
} from '@motajs/render-core';
|
||||
import { BaseProps } from '@motajs/render-vue';
|
||||
import {
|
||||
GameUI,
|
||||
IUIMountable,
|
||||
SetupComponentOptions,
|
||||
UIComponentProps
|
||||
} from '@motajs/system-ui';
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
markRaw,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch
|
||||
} from 'vue';
|
||||
import { FloorSelector } from '../components/floorSelect';
|
||||
import {
|
||||
ILayerGroupRenderExtends,
|
||||
FloorDamageExtends,
|
||||
FloorItemDetail,
|
||||
LayerGroupAnimate,
|
||||
LayerGroup,
|
||||
LayerGroupFloorBinder
|
||||
} from '../elements';
|
||||
import { LayerGroupHalo } from '../legacy/halo';
|
||||
import { LayerGroupPortal } from '../legacy/portal';
|
||||
import { Font } from '@motajs/render-style';
|
||||
import { clamp, mean } from 'lodash-es';
|
||||
import { calculateStatisticsOne, StatisticsDataOneFloor } from './statistics';
|
||||
import { Tip, TipExpose } from '../components';
|
||||
import { useKey } from '../use';
|
||||
|
||||
export interface ViewMapProps extends UIComponentProps, BaseProps {
|
||||
loc: ElementLocator;
|
||||
floorId?: FloorIds;
|
||||
}
|
||||
|
||||
const viewMapProps = {
|
||||
props: ['loc', 'floorId', 'controller', 'instance']
|
||||
} satisfies SetupComponentOptions<ViewMapProps>;
|
||||
|
||||
export const ViewMap = defineComponent<ViewMapProps>(props => {
|
||||
const nowFloorId = core.status.floorId;
|
||||
|
||||
const layerGroupExtends: ILayerGroupRenderExtends[] = [
|
||||
new FloorDamageExtends(),
|
||||
new FloorItemDetail(),
|
||||
new LayerGroupPortal(),
|
||||
new LayerGroupHalo(),
|
||||
new LayerGroupAnimate()
|
||||
];
|
||||
|
||||
const rightFont = new Font(Font.defaultFamily, 15);
|
||||
|
||||
const viewableFloor = markRaw(
|
||||
core.floorIds.filter(v => {
|
||||
return (
|
||||
!core.floors[v].cannotViewMap &&
|
||||
!core.status?.hero?.flags?.__removed__?.includes(v)
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
const group = ref<LayerGroup>();
|
||||
const tip = ref<TipExpose>();
|
||||
const statistics = shallowRef<StatisticsDataOneFloor>();
|
||||
|
||||
const now = ref(0);
|
||||
if (props.floorId) {
|
||||
const index = viewableFloor.indexOf(props.floorId);
|
||||
if (index !== -1) now.value = index;
|
||||
}
|
||||
|
||||
const floorId = computed(() => viewableFloor[now.value]);
|
||||
|
||||
//#region 按键实现
|
||||
|
||||
const [key] = useKey();
|
||||
key.realize('@viewMap_up', () => changeFloor(1), { type: 'down-repeat' })
|
||||
.realize('@viewMap_down', () => changeFloor(-1), {
|
||||
type: 'down-repeat'
|
||||
})
|
||||
.realize('@viewMap_up_ten', () => changeFloor(10))
|
||||
.realize('@viewMap_down_ten', () => changeFloor(-10))
|
||||
.realize('@viewMap_book', () => openBook())
|
||||
.realize('@viewMap_fly', () => fly())
|
||||
.realize('@viewMap_reset', () => resetCamera())
|
||||
.realize('confirm', () => close());
|
||||
|
||||
//#region 功能函数
|
||||
|
||||
const close = () => {
|
||||
props.controller.close(props.instance);
|
||||
};
|
||||
|
||||
const format = (num?: number) => {
|
||||
return core.formatBigNumber(num ?? 0, 6);
|
||||
};
|
||||
|
||||
const changeTo = (index: number) => {
|
||||
const res = clamp(index, 0, viewableFloor.length - 1);
|
||||
now.value = res;
|
||||
};
|
||||
|
||||
const changeFloor = (delta: number) => {
|
||||
changeTo(now.value + delta);
|
||||
};
|
||||
|
||||
const openBook = () => core.openBook(true);
|
||||
|
||||
const fly = () => {
|
||||
const id = viewableFloor[now.value];
|
||||
const success = core.flyTo(id);
|
||||
if (success) close();
|
||||
else tip.value?.drawTip(`无法飞往${core.floors[id].title}`);
|
||||
};
|
||||
|
||||
const resetCamera = () => {
|
||||
group.value?.camera.reset();
|
||||
group.value?.update();
|
||||
};
|
||||
|
||||
//#region 渐变渲染
|
||||
|
||||
const topAlpha = ref(0.7);
|
||||
const bottomAlpha = ref(0.7);
|
||||
|
||||
let topGradient: CanvasGradient | null = null;
|
||||
let bottomGradient: CanvasGradient | null = null;
|
||||
|
||||
const getTopGradient = (ctx: CanvasRenderingContext2D) => {
|
||||
if (topGradient) return topGradient;
|
||||
topGradient = ctx.createLinearGradient(0, 0, 0, 64);
|
||||
topGradient.addColorStop(0, 'rgba(0,0,0,1)');
|
||||
topGradient.addColorStop(0.75, 'rgba(0,0,0,0.5)');
|
||||
topGradient.addColorStop(1, 'rgba(0,0,0,0)');
|
||||
return topGradient;
|
||||
};
|
||||
|
||||
const getBottomGradient = (ctx: CanvasRenderingContext2D) => {
|
||||
if (bottomGradient) return bottomGradient;
|
||||
bottomGradient = ctx.createLinearGradient(0, 64, 0, 0);
|
||||
bottomGradient.addColorStop(0, 'rgba(0,0,0,1)');
|
||||
bottomGradient.addColorStop(0.75, 'rgba(0,0,0,0.5)');
|
||||
bottomGradient.addColorStop(1, 'rgba(0,0,0,0)');
|
||||
return bottomGradient;
|
||||
};
|
||||
|
||||
const renderTop = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.fillStyle = getTopGradient(ctx);
|
||||
ctx.fillRect(0, 0, 480, 64);
|
||||
};
|
||||
|
||||
const renderBottom = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.fillStyle = getBottomGradient(ctx);
|
||||
ctx.fillRect(0, 0, 480, 64);
|
||||
};
|
||||
|
||||
const enterTop = () => (topAlpha.value = 0.9);
|
||||
const enterBottom = () => (bottomAlpha.value = 0.9);
|
||||
const leaveTop = () => (topAlpha.value = 0.7);
|
||||
const leaveBottom = () => (bottomAlpha.value = 0.7);
|
||||
|
||||
//#region 地图渲染
|
||||
|
||||
const renderLayer = (floorId: FloorIds) => {
|
||||
const binder = group.value?.getExtends(
|
||||
'floor-binder'
|
||||
) as LayerGroupFloorBinder;
|
||||
binder.bindFloor(floorId);
|
||||
group.value?.camera.reset();
|
||||
core.status.floorId = floorId;
|
||||
core.status.thisMap = core.status.maps[floorId];
|
||||
statistics.value = calculateStatisticsOne(floorId);
|
||||
};
|
||||
|
||||
const moveCamera = (dx: number, dy: number) => {
|
||||
const camera = group.value?.camera;
|
||||
if (!camera) return;
|
||||
camera.translate(dx / camera.scaleX, dy / camera.scaleX);
|
||||
group.value?.update();
|
||||
};
|
||||
|
||||
const scaleCamera = (scale: number, x: number, y: number) => {
|
||||
const camera = group.value?.camera;
|
||||
if (!camera) return;
|
||||
const [cx, cy] = camera.untransformed(x, y);
|
||||
camera.translate(cx, cy);
|
||||
camera.scale(scale);
|
||||
camera.translate(-cx, -cy);
|
||||
group.value?.update();
|
||||
};
|
||||
|
||||
//#region 地图交互
|
||||
|
||||
let mouseDown = false;
|
||||
let moved = false;
|
||||
let scaled = false;
|
||||
let lastMoveX = 0;
|
||||
let lastMoveY = 0;
|
||||
let lastDis = 0;
|
||||
let movement = 0;
|
||||
|
||||
const touches = new Map<number, IActionEvent>();
|
||||
|
||||
const downMap = (ev: IActionEvent) => {
|
||||
moved = false;
|
||||
lastMoveX = ev.offsetX;
|
||||
lastMoveY = ev.offsetY;
|
||||
movement = 0;
|
||||
|
||||
if (ev.touch) {
|
||||
touches.set(ev.identifier, ev);
|
||||
if (touches.size >= 2) {
|
||||
const [touch1, touch2] = touches.values();
|
||||
lastDis = Math.hypot(
|
||||
touch1.offsetX - touch2.offsetX,
|
||||
touch1.offsetY - touch2.offsetY
|
||||
);
|
||||
}
|
||||
} else {
|
||||
mouseDown = true;
|
||||
}
|
||||
};
|
||||
|
||||
const upMap = (ev: IActionEvent) => {
|
||||
if (ev.touch) {
|
||||
touches.delete(ev.identifier);
|
||||
} else {
|
||||
mouseDown = false;
|
||||
}
|
||||
if (touches.size === 0) {
|
||||
scaled = false;
|
||||
}
|
||||
};
|
||||
|
||||
const move = (ev: IActionEvent) => {
|
||||
if (moved) {
|
||||
const dx = ev.offsetX - lastMoveX;
|
||||
const dy = ev.offsetY - lastMoveY;
|
||||
movement += Math.hypot(dx, dy);
|
||||
moveCamera(dx, dy);
|
||||
}
|
||||
moved = true;
|
||||
lastMoveX = ev.offsetX;
|
||||
lastMoveY = ev.offsetY;
|
||||
};
|
||||
|
||||
const moveMap = (ev: IActionEvent) => {
|
||||
if (ev.touch) {
|
||||
if (touches.size === 0) return;
|
||||
else if (touches.size === 1) {
|
||||
// 移动
|
||||
if (scaled) return;
|
||||
move(ev);
|
||||
} else {
|
||||
// 缩放
|
||||
const [touch1, touch2] = touches.values();
|
||||
const cx = mean([touch1.offsetX, touch2.offsetX]);
|
||||
const cy = mean([touch1.offsetY, touch2.offsetY]);
|
||||
const dis = Math.hypot(
|
||||
touch1.offsetX - touch2.offsetX,
|
||||
touch1.offsetY - touch2.offsetY
|
||||
);
|
||||
const scale = dis / lastDis;
|
||||
if (!scaled) {
|
||||
lastDis = dis;
|
||||
return;
|
||||
}
|
||||
if (!isFinite(scale) || scale === 0) return;
|
||||
scaleCamera(scale, cx, cy);
|
||||
}
|
||||
} else {
|
||||
if (mouseDown) {
|
||||
move(ev);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const leaveMap = (ev: IActionEventBase) => {
|
||||
if (ev.touch) {
|
||||
touches.delete(ev.identifier);
|
||||
} else {
|
||||
mouseDown = false;
|
||||
}
|
||||
};
|
||||
|
||||
const wheelMap = (ev: IWheelEvent) => {
|
||||
if (ev.altKey) {
|
||||
const scale = ev.wheelY < 0 ? 1.1 : 0.9;
|
||||
scaleCamera(scale, ev.offsetX, ev.offsetY);
|
||||
} else if (ev.ctrlKey) {
|
||||
changeFloor(-Math.sign(ev.wheelY) * 10);
|
||||
} else {
|
||||
changeFloor(-Math.sign(ev.wheelY));
|
||||
}
|
||||
};
|
||||
|
||||
const clickMap = (ev: IActionEvent) => {
|
||||
if (movement > 5) return;
|
||||
if (ev.touch) {
|
||||
if (touches.size === 0) {
|
||||
close();
|
||||
}
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
renderLayer(floorId.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
core.status.floorId = nowFloorId;
|
||||
core.status.thisMap = core.status.maps[nowFloorId];
|
||||
});
|
||||
|
||||
watch(floorId, value => {
|
||||
renderLayer(value);
|
||||
});
|
||||
|
||||
//#region 组件树
|
||||
|
||||
return () => (
|
||||
<container loc={props.loc} nocache>
|
||||
<g-rect fillStyle="black" fill loc={[0, 0, 840, 480]} />
|
||||
<g-rect stroke zIndex={100} loc={[0, 0, 840, 480]} noevent />
|
||||
<g-line line={[180, 0, 180, 480]} lineWidth={1} />
|
||||
<g-line line={[180 + 480, 0, 180 + 480, 480]} lineWidth={1} />
|
||||
<FloorSelector
|
||||
loc={[0, 0, 180, 480]}
|
||||
floors={viewableFloor}
|
||||
v-model:now={now.value}
|
||||
onClose={close}
|
||||
/>
|
||||
<layer-group
|
||||
ref={group}
|
||||
ex={layerGroupExtends}
|
||||
loc={[180, 0, 480, 480]}
|
||||
onDown={downMap}
|
||||
onMove={moveMap}
|
||||
onUp={upMap}
|
||||
onLeave={leaveMap}
|
||||
onWheel={wheelMap}
|
||||
onClick={clickMap}
|
||||
>
|
||||
<layer layer="bg" zIndex={10}></layer>
|
||||
<layer layer="bg2" zIndex={20}></layer>
|
||||
<layer layer="event" zIndex={30}></layer>
|
||||
<layer layer="fg" zIndex={40}></layer>
|
||||
<layer layer="fg2" zIndex={50}></layer>
|
||||
</layer-group>
|
||||
<Tip
|
||||
ref={tip}
|
||||
zIndex={40}
|
||||
loc={[188, 8, 200, 32]}
|
||||
pad={[12, 6]}
|
||||
corner={16}
|
||||
/>
|
||||
<sprite
|
||||
loc={[180, 0, 480, 64]}
|
||||
render={renderTop}
|
||||
alpha={topAlpha.value}
|
||||
zIndex={10}
|
||||
cursor="pointer"
|
||||
onEnter={enterTop}
|
||||
onLeave={leaveTop}
|
||||
onClick={() => changeFloor(1)}
|
||||
/>
|
||||
<sprite
|
||||
loc={[180, 416, 480, 64]}
|
||||
render={renderBottom}
|
||||
alpha={bottomAlpha.value}
|
||||
zIndex={10}
|
||||
cursor="pointer"
|
||||
onEnter={enterBottom}
|
||||
onLeave={leaveBottom}
|
||||
onClick={() => changeFloor(-1)}
|
||||
/>
|
||||
<text
|
||||
text="上移地图"
|
||||
loc={[420, 24]}
|
||||
anc={[0.5, 0.5]}
|
||||
zIndex={20}
|
||||
noevent
|
||||
/>
|
||||
<text
|
||||
text="下移地图"
|
||||
loc={[420, 456]}
|
||||
anc={[0.5, 0.5]}
|
||||
zIndex={20}
|
||||
noevent
|
||||
/>
|
||||
<container loc={[660, 0, 180, 480]}>
|
||||
<text
|
||||
text="鼠标 / 单指拖动地图"
|
||||
font={rightFont}
|
||||
loc={[90, 24]}
|
||||
anc={[0.5, 0.5]}
|
||||
fillStyle="yellow"
|
||||
/>
|
||||
<text
|
||||
text="Alt+滚轮 / 双指缩放地图"
|
||||
font={rightFont}
|
||||
loc={[90, 48]}
|
||||
anc={[0.5, 0.5]}
|
||||
fillStyle="yellow"
|
||||
/>
|
||||
<text
|
||||
text="Ctrl+滚轮 / 滚轮切换地图"
|
||||
font={rightFont}
|
||||
loc={[90, 72]}
|
||||
anc={[0.5, 0.5]}
|
||||
fillStyle="yellow"
|
||||
/>
|
||||
<g-line line={[12, 96, 168, 96]} lineWidth={1} />
|
||||
<text
|
||||
text={`怪物数量:${statistics.value?.enemyCount}`}
|
||||
loc={[20, 120]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`血瓶数量:${statistics.value?.potionCount}`}
|
||||
loc={[20, 144]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`宝石数量:${statistics.value?.gemCount}`}
|
||||
loc={[20, 168]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`血瓶数值:${format(statistics.value?.potionValue)}`}
|
||||
loc={[20, 192]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`攻击数值:${format(statistics.value?.atkValue)}`}
|
||||
loc={[20, 216]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`防御数值:${format(statistics.value?.defValue)}`}
|
||||
loc={[20, 240]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<text
|
||||
text={`智慧数值:${format(statistics.value?.mdefValue)}`}
|
||||
loc={[20, 264]}
|
||||
anc={[0, 0.5]}
|
||||
/>
|
||||
<g-line line={[12, 292, 168, 292]} lineWidth={1} />
|
||||
<text
|
||||
text="「 怪物手册 」"
|
||||
loc={[90, 330]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={openBook}
|
||||
/>
|
||||
<text
|
||||
text="「 传送至此 」"
|
||||
loc={[90, 380]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={fly}
|
||||
/>
|
||||
<text
|
||||
text="「 重置视角 」"
|
||||
loc={[90, 430]}
|
||||
anc={[0.5, 0.5]}
|
||||
cursor="pointer"
|
||||
onClick={resetCamera}
|
||||
/>
|
||||
</container>
|
||||
</container>
|
||||
);
|
||||
}, viewMapProps);
|
||||
|
||||
export const ViewMapUI = new GameUI('view-map', ViewMap);
|
||||
|
||||
export function openViewMap(
|
||||
controller: IUIMountable,
|
||||
loc: ElementLocator,
|
||||
props?: ViewMapProps
|
||||
) {
|
||||
controller.open(ViewMapUI, {
|
||||
...props,
|
||||
loc,
|
||||
floorId: core.status.floorId
|
||||
});
|
||||
}
|
@ -101,6 +101,7 @@ export class MotaOffscreenCanvas2D extends EventEmitter<OffscreenCanvasEvent> {
|
||||
/**
|
||||
* 复制一个离屏Canvas2D对象,一般用于缓存等操作
|
||||
* @param canvas 被复制的MotaOffscreenCanvas2D对象
|
||||
* @returns 复制结果,注意复制结果是被冻结的,无法进行大小等的修改,但是可以继续绘制
|
||||
*/
|
||||
static clone(canvas: MotaOffscreenCanvas2D): MotaOffscreenCanvas2D {
|
||||
const newCanvas = new MotaOffscreenCanvas2D();
|
||||
|
@ -140,7 +140,7 @@ export class Container<E extends EContainerEvent = EContainerEvent>
|
||||
destroy(): void {
|
||||
super.destroy();
|
||||
this.children.forEach(v => {
|
||||
v.destroy();
|
||||
v.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -193,8 +193,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||
this.captureEvent(ActionType.Up, v);
|
||||
this.captureEvent(ActionType.Click, v);
|
||||
});
|
||||
[...ev.touches].forEach(v => {
|
||||
this.touchInfo.delete(v.identifier);
|
||||
});
|
||||
});
|
||||
@ -202,18 +200,14 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
ev.preventDefault();
|
||||
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||
this.captureEvent(ActionType.Up, v);
|
||||
});
|
||||
[...ev.touches].forEach(v => {
|
||||
this.touchInfo.delete(v.identifier);
|
||||
});
|
||||
});
|
||||
document.addEventListener('touchmove', ev => {
|
||||
ev.preventDefault();
|
||||
this.createTouchAction(ev, ActionType.Move).forEach(v => {
|
||||
const list = this.touchInfo.values();
|
||||
if (!list.some(vv => v.identifier === vv.identifier)) {
|
||||
return;
|
||||
}
|
||||
const touch = this.touchInfo.get(v.identifier);
|
||||
if (!touch) return;
|
||||
const temp = this.beforeHovered;
|
||||
temp.clear();
|
||||
this.beforeHovered = this.hoveredElement;
|
||||
|
@ -163,7 +163,7 @@ export class Image extends RenderItem<EImageEvent> {
|
||||
image: CanvasImageSource;
|
||||
|
||||
constructor(image: CanvasImageSource, type: RenderItemPosition = 'static') {
|
||||
super(type, false);
|
||||
super(type);
|
||||
this.image = image;
|
||||
if (image instanceof VideoFrame || image instanceof SVGElement) {
|
||||
this.size(200, 200);
|
||||
@ -177,7 +177,7 @@ export class Image extends RenderItem<EImageEvent> {
|
||||
_transform: Transform
|
||||
): void {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.drawImage(this.image, 0, 0, this.width, this.height);
|
||||
ctx.drawImage(this.image, 0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,7 @@ export const { createApp, render } = createRenderer<RenderItem, RenderItem>({
|
||||
},
|
||||
|
||||
remove: function (el: RenderItem<ERenderItemEvent>): void {
|
||||
el.destroy();
|
||||
el.remove();
|
||||
},
|
||||
|
||||
createElement: function (
|
||||
|
@ -436,13 +436,6 @@ export const gameKey = new Hotkey('gameKey', '游戏按键');
|
||||
document.addEventListener('keyup', e => {
|
||||
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
|
||||
const code = keycode(e.keyCode);
|
||||
if (
|
||||
code === KeyCode.Alt ||
|
||||
code === KeyCode.Shift ||
|
||||
code === KeyCode.Ctrl
|
||||
) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (gameKey.emitKey(code, assist, 'up', e)) {
|
||||
e.preventDefault();
|
||||
if (core.status.holdingKeys) {
|
||||
|
@ -40,8 +40,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "小绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(20 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(20 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(20 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -626,8 +626,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "中绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(40 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(40 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(40 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -729,8 +729,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "大绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(80 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(80 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(80 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -896,8 +896,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "超大绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(160 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(160 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(160 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1019,8 +1019,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "璀璨绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(320 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(320 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(320 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1050,8 +1050,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "传奇绿宝石",
|
||||
"text": ",防御+${core.values.blueGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(640 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(640 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(640 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.def += core.values.blueGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
@ -1071,8 +1071,8 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
||||
"cls": "items",
|
||||
"name": "史诗绿宝石",
|
||||
"text": ",护盾+${core.values.greenGem}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(1280 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(1280 * core.status.thisMap.ratio / (core.getFlag(\"hard\") + 1) * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"itemEffect": "core.status.hero.mdef += Math.round(1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))",
|
||||
"itemEffectTip": ",智慧+${Math.round(1280 * core.status.thisMap.ratio / core.getFlag(\"hard\") * (Mota.require('@user/data-state').getSkillLevel(12) / 20 + 1))}",
|
||||
"useItemEffect": "core.status.hero.mdef += core.values.greenGem",
|
||||
"canUseItemEffect": "true"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user