feat: Add metro transit, gadgets, shop, social apps, and traffic models checkpoint
This commit is contained in:
1 parent
caa42b84ed
commit
74e2963a12
79 files changed
+527962
-496
No files matched your search
@@ -2,6 +2,7 @@ using System.Collections.Concurrent;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Ananta.SDK.Network;
|
||||
using Ananta.Server.ClientData.Client4229938;
|
||||
using Ananta.Server.Protocol.Client4229938;
|
||||
|
||||
namespace Ananta.Server.Gameplay.Crowd;
|
||||
@@ -121,8 +122,43 @@ public sealed class UrbanCrowdEngine
|
||||
40968790, // Kaneko Mei - Pedestrian
|
||||
];
|
||||
|
||||
// Common idle / chatter / phone POI action IDs
|
||||
private static readonly uint[] AmbientPoiActions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
// Contextual ambient POI pools, built from the client's UrbanDiversityPOIActionConfig by
|
||||
// NAME keyword. The old fixed [1..10] roll included 走路 (walk-in-place), 跑步 (run) and
|
||||
// 受惊 (startled) — motion/fear states that looked broken on a standing NPC. 站姿* rows
|
||||
// are the authored standing set (phone, look-around, lean, clap…); shop rows add
|
||||
// browsing/vending actions for interior patrons.
|
||||
private uint[]? _idlePoiPool;
|
||||
private uint[]? _shopPoiPool;
|
||||
|
||||
private uint[] IdlePoiPool()
|
||||
{
|
||||
if (_idlePoiPool is null)
|
||||
{
|
||||
var pool = PoiActionCatalog4229938.All()
|
||||
.Where(p => p.MainActions.Length > 0 && p.Name.StartsWith("站姿", StringComparison.Ordinal))
|
||||
.Select(p => p.Id)
|
||||
.ToList();
|
||||
pool.Insert(0, 2u); // plain idle is always valid
|
||||
_idlePoiPool = pool.ToArray();
|
||||
}
|
||||
return _idlePoiPool;
|
||||
}
|
||||
|
||||
private uint[] ShopPoiPool()
|
||||
{
|
||||
if (_shopPoiPool is null)
|
||||
{
|
||||
var pool = PoiActionCatalog4229938.All()
|
||||
.Where(p => p.MainActions.Length > 0 &&
|
||||
(p.Name.StartsWith("站姿", StringComparison.Ordinal) ||
|
||||
p.Name.Contains("商品") || p.Name.Contains("售货机") || p.Name.Contains("购物")))
|
||||
.Select(p => p.Id)
|
||||
.ToList();
|
||||
pool.Insert(0, 2u);
|
||||
_shopPoiPool = pool.ToArray();
|
||||
}
|
||||
return _shopPoiPool;
|
||||
}
|
||||
|
||||
private readonly Random _rng = new();
|
||||
|
||||
@@ -400,7 +436,8 @@ public sealed class UrbanCrowdEngine
|
||||
|
||||
// Spawn 1 shopkeeper/patron inside
|
||||
var formworkId = CitizenFormworkPool[_rng.Next(CitizenFormworkPool.Length)];
|
||||
var poiAction = AmbientPoiActions[_rng.Next(AmbientPoiActions.Length)];
|
||||
var shopPool = ShopPoiPool();
|
||||
var poiAction = shopPool[_rng.Next(shopPool.Length)];
|
||||
var facing = _rng.Next(0, 360);
|
||||
|
||||
var (ok, ids) = await _driver.SpawnCrowdPedestriansAsync(
|
||||
@@ -475,7 +512,8 @@ public sealed class UrbanCrowdEngine
|
||||
var spawnY = MathF.Abs(pt0[1] - py) > 2.5f ? py : pt0[1];
|
||||
var formworkId = CitizenFormworkPool[_rng.Next(CitizenFormworkPool.Length)];
|
||||
var isWalker = _rng.Next(100) < 60; // 60% walkers, 40% ambient idle/talkers
|
||||
var poiAction = isWalker ? 0u : AmbientPoiActions[_rng.Next(AmbientPoiActions.Length)];
|
||||
var idlePool = IdlePoiPool();
|
||||
var poiAction = isWalker ? 0u : idlePool[_rng.Next(idlePool.Length)];
|
||||
var facing = _rng.Next(0, 360);
|
||||
|
||||
var (ok, ids) = await _driver.SpawnCrowdPedestriansAsync(
|
||||
|
||||
Reference in new issue
Block a user