feat: Add universal victory celebration modal, chamber item requirements, and fix broom & cauldron displays
This commit is contained in:
+103
-11
@@ -48,6 +48,14 @@ ALL_ITEMS = {
|
||||
"action": "broom_polish",
|
||||
"action_label": "Besen polieren ✨"
|
||||
},
|
||||
"winged_key": {
|
||||
"id": "winged_key",
|
||||
"name": "Geflügelter Schlüssel",
|
||||
"icon": "🗝️",
|
||||
"desc": "Ein alter Silberschlüssel mit zarten Libellenflügeln. Er sperrt die Eichentür zur Duellier-Kammer auf!",
|
||||
"action": "flutter_key",
|
||||
"action_label": "Flügel surren lassen 🪽"
|
||||
},
|
||||
"duel_badge": {
|
||||
"id": "duel_badge",
|
||||
"name": "Duellanten-Abzeichen",
|
||||
@@ -130,6 +138,8 @@ def get_session_state(request: Request) -> dict:
|
||||
state = request.session["escape"]
|
||||
if "inventory" not in state:
|
||||
state["inventory"] = ["wand", "broom", "snape_scroll"]
|
||||
if state.get("broom_solved") and "winged_key" not in state["inventory"]:
|
||||
state["inventory"].append("winged_key")
|
||||
if state.get("duel_solved") and "duel_badge" not in state["inventory"]:
|
||||
state["inventory"].append("duel_badge")
|
||||
if state.get("brew_solved") and "felix_felicis" not in state["inventory"]:
|
||||
@@ -153,17 +163,94 @@ def get_session_state(request: Request) -> dict:
|
||||
request.session["escape"] = state
|
||||
return request.session["escape"]
|
||||
|
||||
def get_template_context(request: Request, state: dict, lang: str) -> dict:
|
||||
CHAMBER_REQUIREMENTS = {
|
||||
"duel": {
|
||||
"item_id": "winged_key",
|
||||
"item_name": "Geflügelter Schlüssel",
|
||||
"item_icon": "🗝️",
|
||||
"from_chamber": "Kammer I: Der Ring-Flug",
|
||||
"from_url": "/broom",
|
||||
"reason": "Die schwere Eichentür zur Duellier-Kammer ist mit einem verzauberten Flügelschloss versiegelt. Fange zuerst den geflügelten Schlüssel im Besenflug!"
|
||||
},
|
||||
"brew": {
|
||||
"item_id": "duel_badge",
|
||||
"item_name": "Duellanten-Abzeichen & Kessel-Rezept",
|
||||
"item_icon": "⚡",
|
||||
"from_chamber": "Kammer II: Das Spruch-Duell",
|
||||
"from_url": "/duel",
|
||||
"reason": "Snapes Kupferkessel bleibt kalt. Du benötigst die geheime Rezeptur aus der bezwungenen Trainingsrüstung des Duellier-Clubs!"
|
||||
},
|
||||
"cryptex": {
|
||||
"item_id": "felix_felicis",
|
||||
"item_name": "Felix Felicis",
|
||||
"item_icon": "🧪",
|
||||
"from_chamber": "Kammer III: Die Brauküche",
|
||||
"from_url": "/brew",
|
||||
"reason": "Ein uralter Verwirrungsbann verschleiert die Runen des Gründerschlosses. Braue 'Felix Felicis', um die Symbole der vier Gründer zu durchschauen!"
|
||||
},
|
||||
"pixies": {
|
||||
"item_id": "cryptex_key",
|
||||
"item_name": "Schlüssel der Gründer",
|
||||
"item_icon": "🗝️",
|
||||
"from_chamber": "Kammer IV: Das Runen-Drehschloss",
|
||||
"from_url": "/cryptex",
|
||||
"reason": "Das Verteidigungs-Klassenzimmer ist mit dem uralten Siegel der vier Gründer verriegelt. Knacke das Drehschloss in Kammer IV!"
|
||||
},
|
||||
"bottles": {
|
||||
"item_id": "cryptex_key",
|
||||
"item_name": "Schlüssel der Gründer",
|
||||
"item_icon": "🗝️",
|
||||
"from_chamber": "Kammer V: Wichtel-Panik",
|
||||
"from_url": "/pixies",
|
||||
"reason": "Tödliche Flammen und schwere Ketten versperren den Eingang. Schließe zuerst die Wichtel-Prüfung ab und banne die Plagegeister!"
|
||||
},
|
||||
"finale": {
|
||||
"item_id": "philosophers_stone",
|
||||
"item_name": "Stein der Weisen",
|
||||
"item_icon": "💎",
|
||||
"from_chamber": "Kammer VI: Snapes Flaschen",
|
||||
"from_url": "/bottles",
|
||||
"reason": "Der Spiegel Nerhegeb offenbart sich nur jenem Zauberer, der Snapes schwarzes Feuer erfolgreich durchquert hat!"
|
||||
}
|
||||
}
|
||||
|
||||
def get_template_context(request: Request, state: dict, lang: str, chamber_name: str = None) -> dict:
|
||||
inv_ids = state.get("inventory", ["wand", "broom", "snape_scroll"])
|
||||
inv_items = [ALL_ITEMS[i] for i in inv_ids if i in ALL_ITEMS]
|
||||
house_info = HOUSES.get(state.get("house", "gryffindor"), HOUSES["gryffindor"])
|
||||
|
||||
is_locked = False
|
||||
lock_info = None
|
||||
has_alohomora = request.query_params.get("alohomora") == "1" or state.get("alohomora_mode")
|
||||
if request.query_params.get("alohomora") == "1":
|
||||
state["alohomora_mode"] = True
|
||||
request.session["escape"] = state
|
||||
|
||||
req = CHAMBER_REQUIREMENTS.get(chamber_name)
|
||||
if req and not has_alohomora:
|
||||
has_item = req["item_id"] in inv_ids
|
||||
solved_bypass = {
|
||||
"duel": state.get("broom_solved"),
|
||||
"brew": state.get("duel_solved"),
|
||||
"cryptex": state.get("brew_solved"),
|
||||
"pixies": state.get("cryptex_solved"),
|
||||
"bottles": state.get("pixies_solved"),
|
||||
"finale": state.get("bottles_solved")
|
||||
}
|
||||
if not has_item and not solved_bypass.get(chamber_name, False):
|
||||
is_locked = True
|
||||
lock_info = req
|
||||
|
||||
return {
|
||||
"state": state,
|
||||
"lang": lang,
|
||||
"inventory_items": inv_items,
|
||||
"all_items": ALL_ITEMS,
|
||||
"house": house_info,
|
||||
"houses": HOUSES
|
||||
"houses": HOUSES,
|
||||
"is_locked": is_locked,
|
||||
"lock_info": lock_info,
|
||||
"chamber_requirements": CHAMBER_REQUIREMENTS
|
||||
}
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
@@ -187,7 +274,7 @@ async def page_broom(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="broom.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="broom")
|
||||
)
|
||||
|
||||
@app.get("/duel", response_class=HTMLResponse)
|
||||
@@ -199,7 +286,7 @@ async def page_duel(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="duel.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="duel")
|
||||
)
|
||||
|
||||
@app.get("/brew", response_class=HTMLResponse)
|
||||
@@ -211,7 +298,7 @@ async def page_brew(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="brew.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="brew")
|
||||
)
|
||||
|
||||
@app.get("/cryptex", response_class=HTMLResponse)
|
||||
@@ -223,7 +310,7 @@ async def page_cryptex(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="cryptex.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="cryptex")
|
||||
)
|
||||
|
||||
@app.get("/pixies", response_class=HTMLResponse)
|
||||
@@ -235,7 +322,7 @@ async def page_pixies(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="pixies.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="pixies")
|
||||
)
|
||||
|
||||
@app.get("/chess")
|
||||
@@ -252,7 +339,7 @@ async def page_bottles(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="bottles.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="bottles")
|
||||
)
|
||||
|
||||
@app.get("/sliding", response_class=HTMLResponse)
|
||||
@@ -264,7 +351,7 @@ async def page_sliding(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="sliding.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="sliding")
|
||||
)
|
||||
|
||||
@app.get("/finale", response_class=HTMLResponse)
|
||||
@@ -276,7 +363,7 @@ async def page_finale(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="finale.html",
|
||||
context=get_template_context(request, state, lang)
|
||||
context=get_template_context(request, state, lang, chamber_name="finale")
|
||||
)
|
||||
|
||||
@app.get("/api/state")
|
||||
@@ -348,10 +435,15 @@ async def api_broom_complete(request: Request):
|
||||
state["broom_solved"] = True
|
||||
state["broom_score"] = int(data.get("score", 100))
|
||||
state["broom_time"] = int(data.get("time_taken", 30))
|
||||
if "inventory" not in state:
|
||||
state["inventory"] = ["wand", "broom", "snape_scroll"]
|
||||
if "winged_key" not in state["inventory"]:
|
||||
state["inventory"].append("winged_key")
|
||||
request.session["escape"] = state
|
||||
return JSONResponse({
|
||||
"success": True,
|
||||
"message": "Parcours gemeistert! Die Tür zum Zauberspruch-Duell steht offen!",
|
||||
"message": "Parcours gemeistert! Der geflügelte Schlüssel öffnet die Tür zum Zauberspruch-Duell!",
|
||||
"new_item": ALL_ITEMS["winged_key"],
|
||||
"state": state
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user