feat(city): add plaza exercise system with health tracking

- Adds CityPlazas support class for deterministic public plaza generation with outdoor gym equipment
- Implements exercise and stop-exercise actions with proximity validation to equipment
- Introduces health (0-100) and exercise_count attributes to Character model
- Reduces hospital stay duration from two game days to one game hour
- Adds 3D gym equipment rendering (bench, bars, bike, treadmill) in city viewer
- Includes exercise state machine handling in world ticker with energy drain
- Adds comprehensive PlazaExerciseTest and updates HospitalAdmissionTest
- Provides localized UI strings for health HUD and exercise prompts
This commit is contained in:
2026-10-17 22:10:50 -03:00
parent 79ce2a1825
commit 090b530481
18 changed files with 848 additions and 21 deletions
@@ -9,6 +9,7 @@ use App\Models\Character;
use App\Models\City;
use App\Models\Job;
use App\Models\Store;
use App\Support\CityPlazas;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -128,7 +129,9 @@ class CityViewerController extends Controller
'energy' => (int) $me->energy,
'hunger' => (int) $me->hunger,
'thirst' => (int) $me->thirst,
'health' => (int) $me->health,
'education' => (int) $me->education,
'exercise_count' => (int) $me->exercise_count,
'job_id' => $me->job_id,
'job_title' => $me->job?->title,
'house_id' => $me->house_id,
@@ -137,6 +140,7 @@ class CityViewerController extends Controller
'inventory' => $me->inventory()->get()->mapWithKeys(fn ($i) => [$i->item => (int) $i->qty])->all(),
] : null,
'layout' => $this->cityLayout($city, $stores->all()),
'plazas' => CityPlazas::forCity($city),
'agents' => AiAgent::orderBy('id')->get()->map(fn ($a): array => [
'id' => $a->id,
'name' => $a->name,