diff --git a/.gitignore b/.gitignore index 2e0a22a..306c7e2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ instance/ .DS_Store grepo.db data/ +3rdparty/ \ No newline at end of file diff --git a/bot_modules/02_state.js b/bot_modules/02_state.js index b71745a..5a5fa5d 100644 --- a/bot_modules/02_state.js +++ b/bot_modules/02_state.js @@ -17,6 +17,22 @@ function gatherState() { const total_points = uw.Game?.player_points ?? 0; const world = uw.Game?.world_id || ''; + let battle_points = { att: 0, def: 0, available: 0, used: 0 }; + try { + const pk = uw.MM?.getModels?.()?.PlayerKillpoints; + if (pk) { + const m = pk[player_id] || Object.values(pk)[0]; + if (m && m.attributes) { + battle_points = { + att: m.attributes.att || 0, + def: m.attributes.def || 0, + available: m.attributes.available || 0, + used: m.attributes.used || 0 + }; + } + } + } catch (e) { log(`Failed to extract battle_points: ${e}`); } + const townList = Object.values(towns).map(town => { const res = town.resources(); const buildings = town.buildings()?.attributes ?? {}; @@ -211,7 +227,7 @@ function gatherState() { } } catch (e) { log(`unit speed gather failed: ${e}`); } - return { player, player_id, alliance_id, total_points, world_id: world, + return { player, player_id, alliance_id, total_points, battle_points, world_id: world, world_speed, unit_speeds, towns: townList }; } diff --git a/future_ideas.md b/future_ideas.md index 25d5737..86ba640 100644 --- a/future_ideas.md +++ b/future_ideas.md @@ -109,3 +109,33 @@ window.addEventListener('beforeunload', () => { # Make sure the generator yields spaces/heartbeats actively so the OS # throws an IOError/GeneratorExit the moment the client drops. ``` + +## 4. Auto-Culture / Auto-Celebrations +**Inspired by:** `3rdparty/AutoFarm - AutoUpgrade villages lvl 6 - AutoCelebrations-NoOrpheus.user.js` + +**Current State:** +Players manually check their towns for sufficient resources (Wood, Stone, Silver), Gold, or Battle Points, and manually trigger City Festivals, Olympic Games, Victory Processions, or Theater Plays. + +**Proposed Implementation:** +- Add a new bot module (e.g., `Auto-Culture`) containing a background loop that periodically checks the resource counts, gold, and battle points for each active town. +- When conditions are met (e.g., 15000 Wood, 18000 Stone, 15000 Silver for a City Festival, or 300 Battle Points for a Victory Procession), send the appropriate API request (action: `start_celebration` or `start_all_celebrations`) to queue the celebration. +- Provide dashboard controls so users can selectively enable or disable specific celebration types (keeping Olympic Games off by default to avoid accidental gold spending). + +**Benefits:** +- Automates the generation of Culture Points across all towns without user intervention. +- Ensures resources aren't maxed out and wasted while the player is away. + +## 5. Auto-WW Donator / Resource Balancer +**Inspired by:** `3rdparty/WW Trade Helper.user.js` + +**Current State:** +Players manually open the World Wonder window and use UI helpers to calculate how much Wood, Stone, and Silver they can send based on their town's trade capacity and available resources. They then manually click the "Send Resources" button. + +**Proposed Implementation:** +- Integrate the calculation logic from `WW Trade Helper` which effectively balances resource distribution (e.g., Even distribution, No Wood, No Stone, No Silver). +- Create a bot module that periodically checks cities for excess resources and available trade capacity. +- Automatically construct and send the `ajaxPost` payload to the World Wonder endpoint (`model_url: 'WorldWonder'`, `action_name: 'sendResources'`, etc.) without requiring the World Wonder window to be open or requiring manual button clicks. + +**Benefits:** +- Maximizes alliance contributions to World Wonders around the clock. +- Perfectly balances resources sent so the player doesn't accidentally empty their town of a critical resource. diff --git a/routes/api.py b/routes/api.py index f248ce6..f6a829f 100644 --- a/routes/api.py +++ b/routes/api.py @@ -60,6 +60,7 @@ def receive_state(): player_id = data.get('player_id', '') alliance_id = str(data.get('alliance_id', '') or '') world_id = data.get('world_id', '') + battle_points = data.get('battle_points', {}) # Auto-register this player to the clan that matches the key (if any) clan = _get_clan_from_request() @@ -72,6 +73,7 @@ def receive_state(): x = town.get('x') y = town.get('y') sea = town.get('sea') + town['battle_points'] = battle_points c.execute(''' INSERT INTO town_state (town_id, town_name, player, player_id, alliance_id, world_id, x, y, sea, data, updated_at) diff --git a/routes/dashboard.py b/routes/dashboard.py index d736315..0b20c67 100644 --- a/routes/dashboard.py +++ b/routes/dashboard.py @@ -268,7 +268,8 @@ def get_towns(): 'total_points': d.get('total_points', 0), 'alliance_name': d.get('alliance_name', None), 'blueprint_name': row['blueprint_name'], - 'blueprint_active': bool(row['blueprint_active']) + 'blueprint_active': bool(row['blueprint_active']), + 'battle_points': d.get('battle_points', {'att': 0, 'def': 0, 'available': 0, 'used': 0}) }) return jsonify(towns) diff --git a/static/js/components/townViewer.js b/static/js/components/townViewer.js index 217f996..5e2d6db 100644 --- a/static/js/components/townViewer.js +++ b/static/js/components/townViewer.js @@ -178,12 +178,16 @@ window.renderTownDetails = function() { allianceHtml = `
Συμμαχία: ID ${t.alliance_id}
`; } + let bp = t.battle_points || { available: 0, used: 0 }; + let bpHtml = `
Πόντοι Μάχης: ${bp.available} / ${bp.available + bp.used}
`; + document.getElementById('td-general').innerHTML = `
Πόντοι: ${t.points}${t.wonder_points ? ` / Θαύμα: ${t.wonder_points}` : ''}
Θεός: ${godName}
Θάλασσα: ${seaStr}${coordStr}
Παίκτης: ${t.player}${t.has_premium ? ' ' : ''}
${allianceHtml} + ${bpHtml} `; // ---- Researches ----