chuni: add userbox sub trophy, fix unlock challenge

This commit is contained in:
2025-08-31 19:49:06 +02:00
parent 3c7ac3ac58
commit 415bbc92b3
6 changed files with 73 additions and 19 deletions

View File

@ -44,7 +44,7 @@ def upgrade():
mysql_charset="utf8mb4",
)
op.create_tablee(
op.create_table(
"chuni_item_unlock_challenge",
sa.Column("id", sa.Integer(), primary_key=True, nullable=False),
sa.Column("version", sa.Integer(), nullable=False),
@ -59,7 +59,7 @@ def upgrade():
sa.Column("conditionType", sa.Integer()),
sa.Column("score", sa.Integer()),
sa.Column("life", sa.Integer()),
sa.Column("clearDate", sa.Integer()),
sa.Column("clearDate", sa.TIMESTAMP(), server_defaul=func.now()),
sa.UniqueConstraint(
"version",
"user",

View File

@ -655,14 +655,18 @@ class ChuniFrontend(FE_Base):
form_data = await request.form()
new_nameplate: str = form_data.get("nameplate")
new_trophy: str = form_data.get("trophy")
new_trophy_sub_1: str = form_data.get("trophySub1")
new_trophy_sub_2: str = form_data.get("trophySub2")
new_character: str = form_data.get("character")
if not new_nameplate or \
not new_trophy or \
not new_trophy_sub_1 or \
not new_trophy_sub_2 or \
not new_character:
return RedirectResponse("/game/chuni/userbox?e=4", 303)
if not await self.data.profile.update_userbox(usr_sesh.user_id, usr_sesh.chunithm_version, new_nameplate, new_trophy, new_character):
if not await self.data.profile.update_userbox(usr_sesh.user_id, usr_sesh.chunithm_version, new_nameplate, new_trophy, new_trophy_sub_1, new_trophy_sub_2, new_character):
return RedirectResponse("/gate/?e=999", 303)
return RedirectResponse("/game/chuni/userbox", 303)

View File

@ -293,7 +293,7 @@ unlock_challenge = Table(
Column("conditionType", Integer),
Column("score", Integer),
Column("life", Integer),
Column("clearDate", TIMESTAMP),
Column("clearDate", TIMESTAMP, server_default=func.now()),
UniqueConstraint(
"version", "user", "unlockChallengeId", name="chuni_item_unlock_challenge_uk"
),

View File

@ -463,12 +463,12 @@ class ChuniProfileData(BaseData):
return False
return True
async def update_userbox(self, user_id: int, version: int, new_nameplate: int, new_trophy: int, new_character: int) -> bool:
async def update_userbox(self, user_id: int, version: int, new_nameplate: int, new_trophy: int, new_trophy_sub_1: int, new_trophy_sub_2: int, new_character: int) -> bool:
sql = profile.update((profile.c.user == user_id) & (profile.c.version == version)).values(
nameplateId=new_nameplate,
trophyId=new_trophy,
trophyIdSub1=new_trophySub1,
trophyIdSub2=new_trophySub2,
trophyIdSub1=new_trophy_sub_1,
trophyIdSub2=new_trophy_sub_2,
charaIllustId=new_character
)
result = await self.execute(sql)

View File

@ -44,7 +44,25 @@
<tr><td>Nameplate:</td><td style="width: 80%;"><div id="name_nameplate"></div></td></tr>
<tr><td>Trophy:</td><td><div id="name_trophy">
<select name="trophy" id="trophy" onchange="changeTrophy()" style="width:100%;">
<select name="trophy" id="trophy" onclick="changeTrophy()" style="width:100%;">
{% for item in trophies.values() %}
<option value="{{ item["id"] }}" class="trophy-rank{{ item["rarity"] }}">{{ item["name"] }}</option>
{% endfor %}
</select>
</div></td></tr>
<tr><td>Trophy Sub 1:</td><td><div id="name_trophy">
<select name="trophy-sub-1" id="trophy-sub-1" onclick="changeTrophySub1()" style="width:100%;">
<option value="-1"></option>
{% for item in trophies.values() %}
<option value="{{ item["id"] }}" class="trophy-rank{{ item["rarity"] }}">{{ item["name"] }}</option>
{% endfor %}
</select>
</div></td></tr>
<tr><td>Trophy Sub 2:</td><td><div id="name_trophy">
<select name="trophy-sub-2" id="trophy-sub-2" onclick="changeTrophySub2()" style="width:100%;">
<option value="-1"></option>
{% for item in trophies.values() %}
<option value="{{ item["id"] }}" class="trophy-rank{{ item["rarity"] }}">{{ item["name"] }}</option>
{% endfor %}
@ -124,7 +142,10 @@ userbox_components = {
};
types = Object.keys(userbox_components);
orig_trophy = curr_trophy = "{{ profile.trophyId }}";
orig_trophy_sub_1 = curr_trophy_sub_1 = "{{ profile.trophyIdSub1 }}";
orig_trophy_sub_2 = curr_trophy_sub_2 = "{{ profile.trophyIdSub2 }}";
curr_trophy_img = "";
curr_trophy_name = "";
function enableButtons(enabled) {
document.getElementById("reset-btn").disabled = !enabled;
@ -169,6 +190,7 @@ function changeTrophy() {
var trophy_element = document.getElementById("trophy");
curr_trophy = trophy_element.value;
curr_trophy_name = trophy_element[trophy_element.selectedIndex].innerText
curr_trophy_img = getRankImage(trophy_element[trophy_element.selectedIndex]);
updatePreview();
if (curr_trophy != orig_trophy) {
@ -176,12 +198,38 @@ function changeTrophy() {
}
}
function changeTrophySub1() {
var trophy_element = document.getElementById("trophy-sub-1");
curr_trophy_sub_1 = trophy_element.value;
curr_trophy_img = getRankImage(trophy_element[trophy_element.selectedIndex]);
curr_trophy_name = trophy_element[trophy_element.selectedIndex].innerText
updatePreview();
if (curr_trophy_sub_1 != orig_trophy_sub_1) {
enableButtons(true);
}
}
function changeTrophySub2() {
var trophy_element = document.getElementById("trophy-sub-2");
curr_trophy_sub_2 = trophy_element.value;
curr_trophy_img = getRankImage(trophy_element[trophy_element.selectedIndex]);
curr_trophy_name = trophy_element[trophy_element.selectedIndex].innerText
updatePreview();
if (curr_trophy_sub_2 != orig_trophy_sub_2) {
enableButtons(true);
}
}
function resetUserbox() {
for (const type of types) {
changeItem(type, userbox_components[type][orig_id], userbox_components[type][orig_name], userbox_components[type][orig_img]);
}
// reset trophy
document.getElementById("trophy").value = orig_trophy;
document.getElementById("trophy-sub-1").value = orig_trophy_sub_1;
document.getElementById("trophy-sub-2").value = orig_trophy_sub_2;
changeTrophy();
// disable the save/reset buttons until something changes
enableButtons(false);
@ -193,12 +241,14 @@ function updatePreview() {
document.getElementById("name_" + type).innerHTML = userbox_components[type][curr_name];
}
document.getElementById("preview_trophy_rank").src = "img/rank/" + curr_trophy_img;
document.getElementById("preview_trophy_name").innerHTML = document.getElementById("trophy")[document.getElementById("trophy").selectedIndex].innerText;
document.getElementById("preview_trophy_name").innerHTML = curr_trophy_name;
}
function saveUserbox() {
$.post("/game/chuni/update.userbox", { nameplate: userbox_components["nameplate"][curr_id],
trophy: curr_trophy,
trophy: curr_trophy,
trophySub1: curr_trophy_sub_1,
trophySub2: curr_trophy_sub_2,
character: userbox_components["character"][curr_id] })
.done(function (data) {
// set the current as the original and disable buttons
@ -207,7 +257,9 @@ function saveUserbox() {
userbox_components[type][orig_name] = userbox_components[type][orig_name];
userbox_components[type][orig_img] = userbox_components[type][curr_img];
}
orig_trophy = curr_trophy
orig_trophy = curr_trophy;
orig_trophy_sub_1 = curr_trophy_sub_1;
orig_trophy_sub_2 = curr_trophy_sub_2;
enableButtons(false);
})
.fail(function () {

View File

@ -29,11 +29,9 @@ class ChuniVerse(ChuniLuminousPlus):
for unlock_challenge in unlock_challenges:
course_ids = [
unlock_challenge["courseId1"],
unlock_challenge["courseId2"],
unlock_challenge["courseId3"],
unlock_challenge["courseId4"],
unlock_challenge["courseId5"],
unlock_challenge[f"courseId{i}"]
for i in range(1, 6)
if unlock_challenge[f"courseId{i}"] is not None
]
start_date = unlock_challenge["startDate"].replace(
@ -60,7 +58,7 @@ class ChuniVerse(ChuniLuminousPlus):
"length": len(game_course_level_list),
"gameCourseLevelList": game_course_level_list,
}
async def handle_get_game_u_c_condition_api_request(self, data: Dict) -> Dict:
unlock_challenges = await self.data.static.get_unlock_challenges(self.version)
game_unlock_challenge_condition_list = []
@ -84,8 +82,8 @@ class ChuniVerse(ChuniLuminousPlus):
unlock_condition = conditions.get(
unlock_challenge_id,
{
"type": MapAreaConditionType.ALWAYS_UNLOCKED.value, # always unlocked
"conditionId": -1,
"type": MapAreaConditionType.TROPHY_OBTAINED.value, # always unlocked
"conditionId": 0,
},
)