feat(city): add player marketplace, mission journal, character customization and presence
- Player-to-player marketplace with listings, buying and selling - Mission system with progress tracking and money rewards - Character appearance customization (skin, hair, face, beard, accessory) - Multiplayer presence feed showing nearby citizens in near-real-time - Admin world dashboard with live platform metrics - Bus and train transportation with temporary ride state - Mobile joystick controls and minimap HUD - Education bonus applied to work salary
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Http\Controllers\Web\Admin\AdminWorldController;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Prints a one-shot world metrics report for operators and CI logs.
|
||||
*/
|
||||
class CityReport extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'city:report';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Print world metrics (citizens, economy, market, missions)';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$metrics = app(AdminWorldController::class)->metrics();
|
||||
|
||||
$this->info('City10 world report');
|
||||
$this->line('Users: '.$metrics['users']['total']
|
||||
.' (pending '.$metrics['users']['pending']
|
||||
.', active '.$metrics['users']['active']
|
||||
.', banned '.$metrics['users']['banned'].')');
|
||||
$this->line('Cities: '.$metrics['cities']);
|
||||
$this->line('Characters: '.$metrics['characters']['total']
|
||||
.' (online '.$metrics['characters']['online']
|
||||
.', hospital '.$metrics['characters']['hospitalized']
|
||||
.', avg health '.$metrics['characters']['avg_health']
|
||||
.', money '.$metrics['characters']['total_money'].')');
|
||||
$this->line('World: '.$metrics['world']['stores'].' stores, '
|
||||
.$metrics['world']['houses_complete'].' houses, '
|
||||
.$metrics['world']['jobs'].' jobs, '
|
||||
.$metrics['world']['messages'].' messages, '
|
||||
.$metrics['world']['transaction_volume'].' coins traded');
|
||||
$this->line('Market: '.$metrics['market']['listings'].' active listings');
|
||||
$this->line('Missions: '.$metrics['missions']['active'].' active, '
|
||||
.$metrics['missions']['completed'].' completed');
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Building;
|
||||
use App\Models\Character;
|
||||
use App\Support\MissionTracker;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@@ -102,6 +103,12 @@ class CityTick extends Command
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporary bus/train rides expire after ride_until.
|
||||
if ($character->ride_kind !== null && $character->ride_until !== null
|
||||
&& $character->ride_until->isPast()) {
|
||||
$character->forceFill(['ride_kind' => null, 'ride_until' => null])->save();
|
||||
}
|
||||
|
||||
$elapsedMin = 1.0;
|
||||
if ($character->last_tick_at !== null) {
|
||||
$elapsedMin = max(0.5, $character->last_tick_at->diffInMinutes($now));
|
||||
@@ -124,7 +131,9 @@ class CityTick extends Command
|
||||
case Character::STATE_WORKING:
|
||||
if ($character->job_id !== null) {
|
||||
$salary = (float) ($character->job?->salary ?? 0);
|
||||
$character->money = round((float) $character->money + ($salary / 30) * $elapsedMin, 2);
|
||||
// Education boosts take-home pay up to +50% at 100% education.
|
||||
$bonus = 1 + (min(100, (int) $character->education) / 200);
|
||||
$character->money = round((float) $character->money + ($salary * $bonus / 30) * $elapsedMin, 2);
|
||||
}
|
||||
$character->energy = max(0, (int) $character->energy - (int) round(1.2 * $elapsedMin));
|
||||
break;
|
||||
@@ -132,6 +141,7 @@ class CityTick extends Command
|
||||
case Character::STATE_STUDYING:
|
||||
$character->education = min(100, (int) $character->education + (int) round(0.5 * $elapsedMin));
|
||||
$character->energy = max(0, (int) $character->energy - (int) round(0.8 * $elapsedMin));
|
||||
MissionTracker::sync($character, 'education');
|
||||
break;
|
||||
|
||||
case Character::STATE_EXERCISING:
|
||||
|
||||
Reference in New Issue
Block a user