forked from akanyan/STARTLINER
feat: partial support for patches
This commit is contained in:
@ -15,6 +15,7 @@ import { listen } from '@tauri-apps/api/event';
|
||||
import ModList from './ModList.vue';
|
||||
import ModStore from './ModStore.vue';
|
||||
import OptionList from './OptionList.vue';
|
||||
import PatchList from './PatchList.vue';
|
||||
import ProfileList from './ProfileList.vue';
|
||||
import StartButton from './StartButton.vue';
|
||||
import { invoke } from '../invoke';
|
||||
@ -55,14 +56,26 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
fetch_promise.then(async () => {
|
||||
await invoke('install_package', {
|
||||
key: 'segatools-mu3hook',
|
||||
force: false,
|
||||
});
|
||||
await invoke('install_package', {
|
||||
key: 'segatools-chusanhook',
|
||||
force: false,
|
||||
});
|
||||
const promises = [];
|
||||
promises.push(
|
||||
invoke('install_package', {
|
||||
key: 'segatools-mu3hook',
|
||||
force: false,
|
||||
})
|
||||
);
|
||||
promises.push(
|
||||
invoke('install_package', {
|
||||
key: 'segatools-chusanhook',
|
||||
force: false,
|
||||
})
|
||||
);
|
||||
promises.push(
|
||||
invoke('install_package', {
|
||||
key: 'mempatcher-mempatcher',
|
||||
force: false,
|
||||
})
|
||||
);
|
||||
await Promise.all(promises);
|
||||
});
|
||||
});
|
||||
|
||||
@ -163,7 +176,10 @@ listen<{ message: string; header: string }>('invoke-error', (event) => {
|
||||
<div class="grow"></div>
|
||||
|
||||
<div class="flex gap-4">
|
||||
<div class="flex" v-if="currentTab !== 3">
|
||||
<div
|
||||
class="flex"
|
||||
v-if="[0, 1, 2].includes(currentTab as number)"
|
||||
>
|
||||
<InputIcon class="self-center mr-2">
|
||||
<i class="pi pi-search" />
|
||||
</InputIcon>
|
||||
@ -240,13 +256,7 @@ listen<{ message: string; header: string }>('invoke-error', (event) => {
|
||||
</footer>
|
||||
</TabPanel>
|
||||
<TabPanel :value="4">
|
||||
CHUNITHM patches are not implemented yet.<br />Use
|
||||
<a
|
||||
href="https://patcher.two-torial.xyz/"
|
||||
target="_blank"
|
||||
style="text-decoration: underline"
|
||||
>patcher.two-torial.xyz</a
|
||||
>
|
||||
<PatchList />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
<div v-if="currentTab === 5 || currentTab === 3">
|
||||
|
@ -62,7 +62,10 @@ const iconSrc = computed(() => {
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
v-if="hasFeature(pkg, Feature.Mu3IO)"
|
||||
v-if="
|
||||
hasFeature(pkg, Feature.Mu3IO) ||
|
||||
hasFeature(pkg, Feature.ChuniIO)
|
||||
"
|
||||
v-tooltip="'IO'"
|
||||
class="pi pi-wrench ml-1 text-green-400"
|
||||
>
|
||||
@ -73,6 +76,16 @@ const iconSrc = computed(() => {
|
||||
class="pi pi-credit-card ml-1 text-purple-400"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
hasFeature(pkg, Feature.Mempatcher) ||
|
||||
hasFeature(pkg, Feature.GameDLL) ||
|
||||
hasFeature(pkg, Feature.AmdDLL)
|
||||
"
|
||||
v-tooltip="'DLL'"
|
||||
class="pi pi-cog ml-1 text-red-400"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
v-if="showNamespace && pkg?.namespace"
|
||||
class="text-sm opacity-75"
|
||||
|
@ -7,6 +7,7 @@ const general = useGeneralStore();
|
||||
defineProps({
|
||||
title: String,
|
||||
collapsed: Boolean,
|
||||
alwaysFound: Boolean,
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -14,7 +15,7 @@ defineProps({
|
||||
<Fieldset
|
||||
:legend="title"
|
||||
:toggleable="true"
|
||||
v-show="general.cfgCategories.has(title ?? '')"
|
||||
v-show="general.cfgCategories.has(title ?? '') || alwaysFound"
|
||||
:collapsed="collapsed"
|
||||
>
|
||||
<div class="flex w-full flex-col gap-1">
|
||||
|
@ -9,6 +9,7 @@ const props = defineProps({
|
||||
title: String,
|
||||
tooltip: String,
|
||||
dangerousTooltip: String,
|
||||
greytext: String,
|
||||
});
|
||||
|
||||
const searched = computed(() => {
|
||||
@ -38,6 +39,12 @@ const searched = computed(() => {
|
||||
class="pi pi-exclamation-circle ml-2 text-red-500"
|
||||
v-tooltip="dangerousTooltip"
|
||||
></span>
|
||||
<span
|
||||
v-if="greytext"
|
||||
style="font-size: 0.65rem"
|
||||
class="ml-2 text-gray-400"
|
||||
>{{ greytext }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
|
34
src/components/PatchEntry.vue
Normal file
34
src/components/PatchEntry.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup lang="ts">
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
import ToggleSwitch from 'primevue/toggleswitch';
|
||||
import OptionRow from './OptionRow.vue';
|
||||
import { usePrfStore } from '../stores';
|
||||
|
||||
const prf = usePrfStore();
|
||||
|
||||
const toggleUnary = (key: string, val: boolean) => {
|
||||
if (val) {
|
||||
prf.current!.data.patches[key] = 'Enabled';
|
||||
} else {
|
||||
delete prf.current!.data.patches[key];
|
||||
}
|
||||
};
|
||||
|
||||
defineProps({
|
||||
id: String,
|
||||
name: String,
|
||||
tooltip: String,
|
||||
type: String,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OptionRow :title="name" :tooltip="tooltip" :greytext="id">
|
||||
<ToggleSwitch
|
||||
v-if="type === undefined"
|
||||
:model-value="prf.current!.data.patches[id!] !== undefined"
|
||||
@update:model-value="(v: boolean) => toggleUnary(id!, v)"
|
||||
/>
|
||||
<InputNumber v-else class="number-input" />
|
||||
</OptionRow>
|
||||
</template>
|
54
src/components/PatchList.vue
Normal file
54
src/components/PatchList.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, ref } from 'vue';
|
||||
import * as path from '@tauri-apps/api/path';
|
||||
import OptionCategory from './OptionCategory.vue';
|
||||
import OptionRow from './OptionRow.vue';
|
||||
import PatchEntry from './PatchEntry.vue';
|
||||
import { invoke } from '../invoke';
|
||||
import { usePrfStore } from '../stores';
|
||||
import { Patch } from '../types';
|
||||
|
||||
const prf = usePrfStore();
|
||||
|
||||
prf.reload();
|
||||
|
||||
const gamePatches: Ref<Patch[]> = ref([]);
|
||||
const amdPatches: Ref<Patch[]> = ref([]);
|
||||
|
||||
invoke('list_patches', { target: prf.current!.data.sgt.target }).then(
|
||||
(patches) => {
|
||||
gamePatches.value = patches as Patch[];
|
||||
}
|
||||
);
|
||||
|
||||
(async () => {
|
||||
const amd = await path.join(
|
||||
prf.current!.data.sgt.target,
|
||||
'../amdaemon.exe'
|
||||
);
|
||||
amdPatches.value = (await invoke('list_patches', {
|
||||
target: amd,
|
||||
})) as Patch[];
|
||||
})();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OptionCategory title="chusanApp.exe" always-found>
|
||||
<PatchEntry
|
||||
v-for="p in gamePatches"
|
||||
:id="p.id"
|
||||
:title="p.name"
|
||||
:tooltip="p.tooltip"
|
||||
:type="p.type"
|
||||
/>
|
||||
</OptionCategory>
|
||||
<OptionCategory title="amdaemon.exe" always-found>
|
||||
<PatchEntry
|
||||
v-for="p in amdPatches"
|
||||
:id="p.id"
|
||||
:title="p.name"
|
||||
:tooltip="p.tooltip"
|
||||
:type="p.type"
|
||||
/>
|
||||
</OptionCategory>
|
||||
</template>
|
14
src/types.ts
14
src/types.ts
@ -30,6 +30,10 @@ export enum Feature {
|
||||
Mu3Hook = 1 << 3,
|
||||
Mu3IO = 1 << 4,
|
||||
ChusanHook = 1 << 5,
|
||||
ChuniIO = 1 << 6,
|
||||
Mempatcher = 1 << 7,
|
||||
GameDLL = 1 << 8,
|
||||
AmdDLL = 1 << 9,
|
||||
}
|
||||
|
||||
export type Status =
|
||||
@ -54,6 +58,9 @@ export interface ProfileData {
|
||||
bepinex: BepInExConfig;
|
||||
mu3_ini: Mu3IniConfig | undefined;
|
||||
keyboard: KeyboardConfig | undefined;
|
||||
patches: {
|
||||
[key: string]: 'Enabled' | { Number: number } | { Hex: Int8Array };
|
||||
};
|
||||
}
|
||||
|
||||
export interface SegatoolsConfig {
|
||||
@ -149,3 +156,10 @@ export interface Dirs {
|
||||
data_dir: string;
|
||||
cache_dir: string;
|
||||
}
|
||||
|
||||
export interface Patch {
|
||||
id: string;
|
||||
name: string;
|
||||
tooltip: string;
|
||||
type: undefined | 'number';
|
||||
}
|
||||
|
Reference in New Issue
Block a user