Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aquabox improvements #99

Merged
merged 12 commits into from
Jan 5, 2025
12 changes: 10 additions & 2 deletions AquaNet/src/components/settings/ChuniSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
let USERBOX_SETUP_TEXT = t("userbox.new.setup");

let USERBOX_ENABLED = useLocalStorage("userboxNew", false);
let USERBOX_PROFILE_ENABLED = useLocalStorage("userboxNewProfile", false);
let USERBOX_INSTALLED = false;
let USERBOX_SUPPORT = "webkitGetAsEntry" in DataTransferItem.prototype;

Expand Down Expand Up @@ -155,9 +156,9 @@
</div>
{:else}
<div class="chuni-userbox-container">
<ChuniUserplateComponent on:click={() => userboxSelected = "nameplateId"} chuniCharacter={userbox.characterId} chuniLevel={userbox.level} chuniRating={userbox.playerRating / 100}
<ChuniUserplateComponent on:click={() => userboxSelected = "nameplateId"} chuniCharacter={userbox.characterId} chuniLevel={userbox.level.toString()} chuniRating={userbox.playerRating / 100}
chuniNameplate={userbox.nameplateId} chuniName={userbox.userName} chuniTrophyName={allItems.trophy[userbox.trophyId].name}></ChuniUserplateComponent>
<ChuniPenguinComponent classPassthrough="chuni-penguin-float" chuniWear={userbox.avatarWear} chuniHead={userbox.avatarHead} chuniBack={userbox.avatarBack}
<ChuniPenguinComponent chuniWear={userbox.avatarWear} chuniHead={userbox.avatarHead} chuniBack={userbox.avatarBack}
chuniFront={userbox.avatarFront} chuniFace={userbox.avatarFace} chuniItem={userbox.avatarItem}
chuniSkin={userbox.avatarSkin}></ChuniPenguinComponent>
</div>
Expand Down Expand Up @@ -219,6 +220,13 @@
<span class="desc">{t(`userbox.new.activate_desc`)}</span>
</label>
</div>
<div class="field boolean" style:margin-top="1em">
<input type="checkbox" bind:checked={USERBOX_PROFILE_ENABLED.value} id="newUserboxProfile">
<label for="newUserboxProfile">
<span class="name">{t("userbox.new.activate_profile")}</span>
<span class="desc">{t(`userbox.new.activate_profile_desc`)}</span>
</label>
</div>
{/if}
{#if USERBOX_SUPPORT}
<p>
Expand Down
47 changes: 34 additions & 13 deletions AquaNet/src/components/settings/userbox/ChuniPenguin.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
{/await}

<!-- Arms (surfboard) -->
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 80, 0, 110, 100, 0.75) then imageURL}
<img class="chuni-penguin-arm-left chuni-penguin-arm" src={imageURL} alt="Left Arm">
{/await}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 80, 0, 110, 100, 0.75) then imageURL}
<img class="chuni-penguin-arm-right chuni-penguin-arm" src={imageURL} alt="Right Arm">
{/await}

Expand Down Expand Up @@ -77,8 +77,11 @@
</div>
<div class="chuni-penguin-feet">
<!-- Feet -->
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 0, 410, 167, 80, 0.75) then imageURL}
<img src={imageURL} alt="Feet">
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 0, 410, 85, 80, 0.75) then imageURL}
<img src={imageURL} alt="Foot">
{/await}
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 85, 410, 85, 80, 0.75) then imageURL}
<img src={imageURL} alt="Foot">
{/await}
</div>
</div>
Expand All @@ -88,7 +91,7 @@
0%
transform: translate(-50%, 0%) translate(0%, -50%)
50%
transform: translate(-50%, 10px) translate(0%, -50%)
transform: translate(-50%, 5px) translate(0%, -50%)
100%
transform: translate(-50%, 0%) translate(0%, -50%)
@keyframes chuniPenguinArmLeft
Expand All @@ -108,11 +111,19 @@

img
-webkit-user-drag: none
user-select: none

.chuni-penguin
height: 512px
aspect-ratio: 1/2
position: relative
pointer-events: none

&.chuni-penguin-float
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)

.chuni-penguin-body, .chuni-penguin-feet
transform: translate(-50%, -50%)
Expand All @@ -122,21 +133,31 @@
.chuni-penguin-body
top: 50%
z-index: 1
animation: chuniPenguinBodyBob 2s infinite cubic-bezier(0.45, 0, 0.55, 1)
animation: chuniPenguinBodyBob 1s infinite cubic-bezier(0.45, 0, 0.55, 1)
.chuni-penguin-feet
top: 82.5%
top: 80%
z-index: 0
width: 175px
display: flex
justify-content: center

img
margin-left: auto
margin-right: auto

.chuni-penguin-arm
transform-origin: 95% 10%
transform-origin: 40% 10%
position: absolute
top: 40%
z-index: 2
.chuni-penguin-arm-left
left: 0%
animation: chuniPenguinArmLeft 1.5s infinite cubic-bezier(0.45, 0, 0.55, 1)
left: 15%
transform: translate(-50%, 0)
animation: chuniPenguinArmLeft 1s infinite cubic-bezier(0.45, 0, 0.55, 1) 0.5s
.chuni-penguin-arm-right
left: 70%
animation: chuniPenguinArmRight 1.5s infinite cubic-bezier(0.45, 0, 0.55, 1)
left: 95%
transform: translate(-50%, 0) scaleX(-1)
animation: chuniPenguinArmRight 1s infinite cubic-bezier(0.45, 0, 0.55, 1) 0.5s

.chuni-penguin-accessory
transform: translate(-50%, -50%)
Expand All @@ -149,7 +170,7 @@
.chuni-penguin-beak
top: 29.5%
.chuni-penguin-wear
top: 57.5%
top: 60%
.chuni-penguin-head
top: 7.5%
z-index: 10
Expand Down
31 changes: 20 additions & 11 deletions AquaNet/src/components/settings/userbox/ChuniUserplate.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@

const DDSreader = new DDS(ddsDB);

export var chuniLevel: number = 1
export var chuniLevel: string = "╳"
export var chuniName: string = "AquaDX"
export var chuniRating: number = 1.23
export var chuniNameplate: number = 1
export var chuniCharacter: number = 0
export var chuniTrophyName: string = "NEWCOMER"
</script>
{#await DDSreader?.getFile(`nameplate:${chuniNameplate.toString().padStart(8, "0")}`) then nameplateURL}
{#await DDSreader?.getFile(`nameplate:${chuniNameplate.toString().padStart(8, "0")}`, `nameplate:00000001`) then nameplateURL}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div on:click class="chuni-nameplate" style:background={`url(${nameplateURL})`}>
{#await DDSreader?.getFile(`characterThumbnail:${chuniCharacter.toString().padStart(6, "0")}`) then characterThumbnailURL}
{#await DDSreader?.getFile(`characterThumbnail:${chuniCharacter.toString().padStart(6, "0")}`, `characterThumbnail:000000`) then characterThumbnailURL}
<img class="chuni-character" src={characterThumbnailURL} alt="Character">
{/await}
{#await DDSreader?.getFileFromSheet("surfboard:CHU_UI_title_rank_00_v10.dds", 5, 5 + (75 * 2), 595, 64) then trophyURL}
<div class="chuni-trophy">
{chuniTrophyName}
<img src={trophyURL} class="chuni-trophy-bg" alt="Trophy">
</div>
<img src={trophyURL} class="chuni-trophy-bg" alt="Trophy">
{/await}
<div class="chuni-user-info">
<div class="chuni-user-name">
Expand Down Expand Up @@ -57,7 +57,7 @@
cursor: pointer

.chuni-trophy
width: 410px
width: 390px
height: 45px
background-position: center
background-size: cover
Expand All @@ -74,14 +74,21 @@
font-family: sans-serif
font-weight: bold

overflow-x: hidden
white-space: nowrap
text-overflow: ellipsis

z-index: 1
text-shadow: 0 1px white
margin: 0 10px

img
width: 100%
height: 100%
position: absolute
z-index: -1
img.chuni-trophy-bg
width: 410px
height: 45px
position: absolute
top: 40px
right: 25px
z-index: -1

.chuni-character
position: absolute
Expand Down Expand Up @@ -115,9 +122,11 @@
.chuni-user-name
flex: 1 0 65%
box-shadow: 0 1px 0 #ccc
white-space: nowrap
text-overflow: ellipsis

.chuni-user-level
font-size: 2em
font-size: 1.5em
margin-left: 10px

.chuni-user-name-text
Expand Down
2 changes: 2 additions & 0 deletions AquaNet/src/libs/i18n/en_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ export const EN_REF_USERBOX = {
'userbox.new.activate_update': 'Update AquaBox (game files required)',
'userbox.new.activate': 'Use AquaBox',
'userbox.new.activate_desc': 'Enable displaying UserBoxes with their nameplate & avatar',
'userbox.new.activate_profile': 'Use AquaBox on profiles',
'userbox.new.activate_profile_desc': 'Enable displaying UserBoxes with their nameplate & avatar on profile pages',
'userbox.new.error.invalidFolder': 'The folder you selected is invalid. Ensure that your game\'s version is Lumi or newer and that the "A001" option pack is present.'
}

Expand Down
2 changes: 2 additions & 0 deletions AquaNet/src/libs/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ export const USERBOX = {
get('/api/v2/game/chu3/user-box', {}),
setUserBox: (d: { field: string, value: number | string }) =>
post(`/api/v2/game/chu3/user-detail-set`, d),
getUserProfile: (username: string): Promise<UserBox> =>
get(`/api/v2/game/chu3/user-detail`, {username})
}

export const CARD = {
Expand Down
1 change: 1 addition & 0 deletions AquaNet/src/libs/userbox/userbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export async function userboxFileProcess(folder: FileSystemEntry, progressUpdate
if (dataFolder)
await scanOptionFolder(dataFolder, progressUpdate);
useLocalStorage("userboxNew", false).value = true;
useLocalStorage("userboxNewProfile", false).value = true;
location.reload();

return null
Expand Down
61 changes: 61 additions & 0 deletions AquaNet/src/pages/UserHome.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,41 @@
d!.user.rival = isAdd
}).catch(e => error = e.message).finally(() => isLoading = false)
}

/* Aquabox */

import { userboxFileProcess, ddsDB, initializeDb } from "../libs/userbox/userbox"
import ChuniPenguinComponent from "../components/settings/userbox/ChuniPenguin.svelte"
import ChuniUserplateComponent from "../components/settings/userbox/ChuniUserplate.svelte";
import {
type UserBox,
type UserItem,
} from "../libs/generalTypes";
import { USERBOX } from "../libs/sdk";

let USERBOX_ACTIVE = useLocalStorage("userboxNewProfile", false);
let USERBOX_INSTALLED = false;

let userbox: UserBox;
let allItems: Record<string, Record<string, { name: string }>> = {};

if (game == "chu3" && USERBOX_ACTIVE.value) {
indexedDB.databases().then(async (dbi) => {
let databaseExists = dbi.some(db => db.name == "userboxChusanDDS");
if (databaseExists) {
await initializeDb();
const profile = await USERBOX.getUserProfile(username).catch(_ => null)
if (!profile) return;
userbox = profile;
console.log(userbox);

allItems = await DATA.allItems('chu3').catch(_ => {
error = t("userbox.error.nodata")
}) as typeof allItems
USERBOX_INSTALLED = databaseExists;
}
})
}
</script>

<main id="user-home" class="content">
Expand Down Expand Up @@ -132,6 +167,18 @@
</nav>
</div>

{#if USERBOX_ACTIVE.value && USERBOX_INSTALLED && game == "chu3"}
<div class="chuni-userbox-container">
<ChuniUserplateComponent chuniCharacter={userbox.characterId} chuniRating={d.user.rating / 100} chuniLevel={userbox.level.toString()}
chuniNameplate={userbox.nameplateId} chuniName={userbox.userName} chuniTrophyName={allItems.trophy[userbox.trophyId].name}></ChuniUserplateComponent>
<div class="chuni-penguin-container">
<ChuniPenguinComponent classPassthrough="chuni-penguin-float" chuniWear={userbox.avatarWear} chuniHead={userbox.avatarHead} chuniBack={userbox.avatarBack}
chuniFront={userbox.avatarFront} chuniFace={userbox.avatarFace} chuniItem={userbox.avatarItem}
chuniSkin={userbox.avatarSkin}></ChuniPenguinComponent>
</div>
</div>
{/if}

<div>
<h2>{titleText} {t('UserHome.Statistics')}</h2>
<div class="scoring-info">
Expand Down Expand Up @@ -576,4 +623,18 @@
&:before
content: "+"
color: vars.$c-good

.chuni-userbox-container
display: flex
align-items: center
justify-content: center

.chuni-penguin-container
height: 256px
aspect-ratio: 1
position: relative

@media (max-width: 1000px)
.chuni-userbox-container
flex-wrap: wrap
</style>