116 lines
5.7 KiB
Go
116 lines
5.7 KiB
Go
package routers
|
||
|
||
import (
|
||
"context"
|
||
"sync"
|
||
)
|
||
|
||
var _ = sync.Mutex{}
|
||
var _ = context.Background
|
||
|
||
//
|
||
// Gang territory enemies at their authored city corners — the enemy counterpart of
|
||
// GameRouter.FunctionalNpc (which does the same follow loop for shop clerks).
|
||
// Where the positions come from is the interesting part, because the enemy tables have none:
|
||
// EnemyCatalog.json is a pure template table. The only authored enemy coordinates in the
|
||
// whole dump live in the faction influence system — FactionInfluenceAreaConfig (24 turfs,
|
||
// each a FactionId plus the point ids it owns) × FactionAreaPointConfig (85 points, 2D).
|
||
// Together they answer "which gang stands on which street corner", which is exactly the "put
|
||
// bodies where they belong" placement. See EnemyTerritorySpotCatalog4229938.
|
||
// What they DO once they exist is not decided here. The spawn goes through
|
||
// GameAdminBridge.SpawnAgentAsync, the same path the admin panel's 生成敌人 button uses:
|
||
// it sets forbidAetherAI = true, so the client's own behaviour tree takes the unit over the
|
||
// moment it appears — idle, then whatever its tree does when the player gets close. That is why
|
||
// they do NOT stroll along the pavement like ambient peds (which the server drives with
|
||
// SyncLogicAgentCommand): this path has no server-side walking at all.
|
||
// Two ways in, one placement helper:
|
||
// • the follow loop (EnsureEnemyTerritory) — walk into a turf and its gang is
|
||
// already standing there;
|
||
// • the panel button (SpawnEnemyTerritoryAsync) — "put the nearby ones down now".
|
||
//
|
||
func GameRouter_EnemyTerritory_EnemyTerritoryStateOf(ctx context.Context, session *GameSession) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_EnemyTerritoryStateOf
|
||
var zero any; return zero
|
||
}
|
||
|
||
// World-ready hook: start the follow loop. Idempotent; no-op when disabled.
|
||
func GameRouter_EnemyTerritory_EnsureEnemyTerritory(ctx context.Context, session *GameSession) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_EnsureEnemyTerritory
|
||
var zero any; return zero
|
||
}
|
||
|
||
// Disconnect / scene switch: stop the loop. The client clears the entities itself.
|
||
func GameRouter_EnemyTerritory_StopEnemyTerritory(ctx context.Context, session *GameSession) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_StopEnemyTerritory
|
||
var zero any; return zero
|
||
}
|
||
|
||
// How many territory enemies the follow loop currently has standing. Panel display only.
|
||
func GameRouter_EnemyTerritory_EnemyTerritoryActiveCount(ctx context.Context, session *GameSession) int32 {
|
||
// Router implementation for GameRouter_EnemyTerritory_EnemyTerritoryActiveCount
|
||
return 0
|
||
}
|
||
|
||
func GameRouter_EnemyTerritory_RunEnemyTerritoryLoopAsync(ctx context.Context, session *GameSession, owner any, token context.Context) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_RunEnemyTerritoryLoopAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_EnemyTerritory_TickEnemyTerritoryAsync(ctx context.Context, session *GameSession, owner any, cfg any) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_TickEnemyTerritoryAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Puts <count> members of one turf on the ground.
|
||
// Where they go comes from EnemyTerritorySpot4229938.Members, and that list is
|
||
// the whole point of the 2026-09-24 rework: the authored turf point is the corner of the
|
||
// influence polygon, i.e. the middle of the intersection (measured: median 12.0 m from the
|
||
// nearest pavement spot). Standing bodies there read as "traffic cone". The generator now
|
||
// moves the whole group onto CivilianDistricts pavement spots near the turf point, preferring
|
||
// the ones with 2-4 neighbours (an alley edge) over 7+ (a plaza/crossroads), and the members
|
||
// face the group centroid so they read as a knot of people rather than a firing line.
|
||
// The old ring-around-the-point placement is kept as a fallback for a JSON without "members"
|
||
// — it is worse, but it is better than standing on the road.
|
||
//
|
||
func GameRouter_EnemyTerritory_PlaceTerritoryGroupAsync(ctx context.Context, session *GameSession, owner any, spot any, count int32, engage bool) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_PlaceTerritoryGroupAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_EnemyTerritory_RemoveTerritoryEnemyAsync(ctx context.Context, session *GameSession, owner any, id uint64) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_RemoveTerritoryEnemyAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Drops a retired unit out of the enemy ledger. SpawnAgentAsync registered it so its hits are
|
||
// settled; leaving the entry behind would keep the attack AI driving a unit that no longer
|
||
// exists, and the death-clear / groggy timers would fire into the void.
|
||
//
|
||
func GameRouter_EnemyTerritory_ForgetTerritoryEnemy(ctx context.Context, session *GameSession, uid uint64) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_ForgetTerritoryEnemy
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Panel button: stock every turf within <radius> of the player (radius <= 0 = a 90 m
|
||
// default), nearest first. Turfs already stocked are skipped.
|
||
//
|
||
func GameRouter_EnemyTerritory_SpawnEnemyTerritoryAsync(ctx context.Context, session *GameSession, radius float32) any {
|
||
// Router implementation for GameRouter_EnemyTerritory_SpawnEnemyTerritoryAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
type EnemyTerritorySessionState struct {
|
||
SyncRoot any `json:"syncRoot"`
|
||
Cts *context.CancelFunc `json:"cts"`
|
||
Loop *any `json:"loop"`
|
||
// entityId -> the spot it was placed for. Doubles as the "already placed" set.
|
||
Active map[uint64]EnemyTerritorySpot4229938 `json:"active"`
|
||
// Point ids already stocked this scene; a change of raid wipes them.
|
||
Stocked []uint32 `json:"stocked"`
|
||
Raid uint32 `json:"raid"`
|
||
}
|
||
|