fifa17-recon: pack opening (store catalog + buy + award)
Add a first-cut FUT store on top of the persistent profile: - fut_store: PACK_CATALOG (Bronze/Gold/Premium), a curated real-player PACK_POOL, and open_pack() (deduct coins -> generate items -> add to club -> persist). - utas_server routes: GET store/purchasegroup/all (catalog), PUT (v2) store/transaction (buy + open, returns awarded itemData + updated coins), GET purchased (last pack). Matches both /ut/game and /ut/v2/game prefixes. Verified via curl: buy Gold Pack -> 7 real players awarded, coins 15000->10000, club 10->17, persisted. Wire format is a best-guess grounded in the CardsDLL store keys (packId/price/itemData/coins); iterate against the in-game store next. Pool is curated for now -- replace with a full dbdata.dll extract later. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
This commit is contained in:
@@ -155,4 +155,53 @@ class Store:
|
||||
return i
|
||||
|
||||
|
||||
def open_pack(self, price, count, gold=True):
|
||||
"""Deduct `price` coins, generate `count` player items from the pool, add
|
||||
them to the club, return them. Returns None if not enough coins."""
|
||||
import random
|
||||
if not self.spend(price):
|
||||
return None
|
||||
pool = [p for p in PACK_POOL if (p[1] >= 75) == gold] or PACK_POOL
|
||||
picks = [random.choice(pool) for _ in range(count)]
|
||||
items = [_item(self.new_item_id(), a, r, p, n, lg, tm, at)
|
||||
for (a, r, p, n, lg, tm, at) in picks]
|
||||
self.add_items(items)
|
||||
with _LOCK:
|
||||
self.load()["packsOpened"] += 1
|
||||
self._last_pack = items
|
||||
self._save()
|
||||
return items
|
||||
|
||||
def last_pack(self):
|
||||
return getattr(self, "_last_pack", [])
|
||||
|
||||
|
||||
# Card pool for packs. TODO: replace with a full dbdata.dll extract (~18k players);
|
||||
# for now a curated set of real FIFA17 assetIds so packs hand out real cards.
|
||||
PACK_POOL = STARTER_PLAYERS + [
|
||||
(167495, 90, "GK", 27, 19, 22, [86, 88, 52, 88, 22, 88]), # Neuer
|
||||
(192985, 88, "RM", 21, 19, 22, [80, 82, 85, 85, 63, 68]), # De Bruyne
|
||||
(188545, 89, "ST", 37, 16, 240, [77, 88, 75, 82, 42, 82]), # Lewandowski
|
||||
(169193, 87, "CDM",54, 16, 240, [70, 66, 80, 78, 82, 84]), # Alonso(X)
|
||||
(202126, 86, "ST", 18, 13, 5, [79, 84, 74, 82, 45, 79]), # Kane
|
||||
(177003, 88, "CM", 14, 13, 5, [65, 78, 88, 79, 71, 66]), # Modric(X)
|
||||
(190871, 87, "LW", 54, 16, 240, [90, 78, 80, 88, 36, 61]), # Neymar(X)
|
||||
(184941, 85, "CB", 14, 4, 5, [72, 40, 55, 60, 86, 85]), # (X)
|
||||
]
|
||||
|
||||
# 3 store packs (price in coins, card count, gold-only). Ids are stable.
|
||||
PACK_CATALOG = [
|
||||
{"id": 101, "name": "Bronze Pack", "price": 400, "count": 5, "gold": False},
|
||||
{"id": 102, "name": "Gold Pack", "price": 5000, "count": 7, "gold": True},
|
||||
{"id": 103, "name": "Premium Gold", "price": 15000, "count": 11, "gold": True},
|
||||
]
|
||||
|
||||
|
||||
def pack_by_id(pid):
|
||||
for p in PACK_CATALOG:
|
||||
if p["id"] == pid:
|
||||
return p
|
||||
return None
|
||||
|
||||
|
||||
STORE = Store()
|
||||
|
||||
Reference in New Issue
Block a user