From 63bf981e214c7f0f1bccfd823b326612aedc81f0 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Tue, 10 Nov 2026 21:06:27 +0600 Subject: [PATCH] Fixing minor bugs, some renaming --- docs/NPC_BEHAVIOR.md | 85 + resources/config/campaigns.json | 36 +- ...i_exterior.json => battle_zone_korea.json} | 2 +- resources/config/npcs_battle_zone.json | 162 ++ resources/config/start_state.json | 1538 ++++++++-------- resources/config/start_state_battle_zone.json | 1566 +++++++++++------ .../start_state_battle_zone_singleplayer.json | 1566 +++++++++++------ server/tests/LocationGameStateTests.cpp | 53 + src/LocationGameState.cpp | 110 +- src/LocationGameState.h | 4 + src/ScriptEngine.cpp | 2 +- src/game_server/InternalGameServer.h | 2 +- 12 files changed, 3186 insertions(+), 1940 deletions(-) create mode 100644 docs/NPC_BEHAVIOR.md rename resources/config/locations/{battle_zone_uni_exterior.json => battle_zone_korea.json} (94%) diff --git a/docs/NPC_BEHAVIOR.md b/docs/NPC_BEHAVIOR.md new file mode 100644 index 0000000..d57c078 --- /dev/null +++ b/docs/NPC_BEHAVIOR.md @@ -0,0 +1,85 @@ +# Hostile NPC Behavior + +## Authority and update order + +Hostile NPC behavior is simulated by `LocationGameState` and +`CharacterState`. Rendering objects do not select targets and do not change +NPC combat state. + +During each authoritative simulation tick: + +1. The location gathers the enabled players and NPCs visible to the + simulation. +2. Each hostile NPC selects or retains a player target. +3. Every character advances using the same tick-start observations. +4. Movement reservations and attack damage are resolved deterministically. +5. Navigation recovery events are applied by `InternalGameServer`. + +The resulting state and recovery decisions are replicated through the existing +WebSocket lockstep stream. NPC target changes are simulation consequences, not +client commands. + +## Eligible players and nearest selection + +An eligible target must: + +- exist in the campaign player map; +- be enabled; +- have positive health; and +- be within the NPC's `visibleRange` when a new target is selected. + +Distance is measured in the X/Z plane. If two players are equally close, +their stable player IDs are compared lexicographically. This gives every +lockstep replica the same result regardless of hash-map iteration order. + +## Ordinary target locking + +Once a hostile NPC has a valid target, it keeps that target during ordinary +ticks. The target remains locked even if it moves outside `visibleRange`. +The lock ends when the player dies or becomes disabled. + +When a lock ends, the NPC selects the nearest eligible player in range. If no +player qualifies, it clears the attack target, leaves combat state, and +requests a route to its `homePosition`. + +## Movement blockage and target reconsideration + +NPC movement uses a retry schedule after a character blocks its path. The +blocked NPC first stops and waits for its deterministic navigation retry +cooldown. When the retry event emits `forceNavigationReplan`, the authoritative +location state performs a fresh target selection across all eligible players. + +This blocked-replan selection differs from ordinary target locking: + +- the current target is not privileged; +- the nearest eligible player may remain the target; +- a nearer eligible player replaces the current target; +- the route is rebuilt from the NPC's current position toward the selected + player's current position. + +If no eligible player is in range during blocked recovery, the NPC clears its +stale chase target and returns toward its home position instead. The blocker is +still passed to path planning so the immediate replan does not route through +the character that caused the recovery event. + +## Death, disconnect, and attack safety + +Dead or disabled players are excluded from target acquisition. A target that +dies or disconnects is therefore invalidated on the next authoritative +selection pass, and the NPC either switches to another player or returns home. + +Attack impacts are also validated at application time. Damage is ignored if +the recorded target no longer exists, is disabled, or has already reached +zero health. This prevents a queued animation impact from damaging a stale +target. + +## Regression expectations + +The state and pathfinding tests should preserve these guarantees: + +- nearest in-range player selection is deterministic; +- a valid ordinary lock is retained; +- blocked NPC recovery can replace the target and rebuild the chase route; +- no-target blocked recovery clears combat and routes home; +- dead and disabled players cannot be selected or damaged; +- retry cooldowns and blocker identity remain deterministic. diff --git a/resources/config/campaigns.json b/resources/config/campaigns.json index 335b4dd..356f6a8 100644 --- a/resources/config/campaigns.json +++ b/resources/config/campaigns.json @@ -2,7 +2,10 @@ "campaigns": [ { "id": "main", - "title": { "ru": "Основная игра", "en": "Main Game" }, + "title": { + "ru": "Основная игра", + "en": "Main Game" + }, "locations": [ "resources/config/locations/location_dorm.json", "resources/config/locations/uni_exterior.json", @@ -17,12 +20,15 @@ }, { "id": "battle_zone", - "title": { "ru": "Зона боя (одиночная)", "en": "Battle Zone (Single Player)" }, + "title": { + "ru": "Зона боя (одиночная)", + "en": "Battle Zone (Single Player)" + }, "locations": [ - "resources/config/locations/battle_zone_uni_exterior.json" + "resources/config/locations/battle_zone_korea.json" ], - "startLocation": "uni_exterior", - "startMusic": "music/bishkek univer day.ogg", + "startLocation": "park_korea", + "startMusic": "music/bishkek fight calm.ogg", "startState": "resources/config/start_state_battle_zone_singleplayer.json", "quests": "resources/config/quests_battle_zone.json", "tutorial": false, @@ -30,18 +36,26 @@ }, { "id": "battle_zone_multiplayer", - "title": { "ru": "Зона боя (сетевая)", "en": "Battle Zone (Multiplayer)" }, + "title": { + "ru": "Зона боя (сетевая)", + "en": "Battle Zone (Multiplayer)" + }, "locations": [ - "resources/config/locations/battle_zone_uni_exterior.json" + "resources/config/locations/battle_zone_korea.json" ], - "startLocation": "uni_exterior", - "startMusic": "music/bishkek univer day.ogg", + "startLocation": "park_korea", + "startMusic": "music/bishkek fight calm.ogg", "startState": "resources/config/start_state_battle_zone.json", "quests": "resources/config/quests_battle_zone.json", "tutorial": false, - "networkPlayerSlots": ["player", "player2"], + "networkPlayerSlots": [ + "player1", + "player2", + "player3", + "player4" + ], "networkCompatibility": "battle-zone-lockstep-v5", "loadingScreen": "resources/w/ui/screen_loading.json" } ] -} +} \ No newline at end of file diff --git a/resources/config/locations/battle_zone_uni_exterior.json b/resources/config/locations/battle_zone_korea.json similarity index 94% rename from resources/config/locations/battle_zone_uni_exterior.json rename to resources/config/locations/battle_zone_korea.json index 24120cf..ecf2363 100644 --- a/resources/config/locations/battle_zone_uni_exterior.json +++ b/resources/config/locations/battle_zone_korea.json @@ -1,5 +1,5 @@ { - "id": "uni_exterior", + "id": "park_korea", "gameObjects": "resources/w/shelter/game_objects.json", "interactiveObjects": "resources/w/shelter/interactive_objects.json", "npcs": "resources/config/npcs_battle_zone.json", diff --git a/resources/config/npcs_battle_zone.json b/resources/config/npcs_battle_zone.json index 8d065f2..502dc44 100644 --- a/resources/config/npcs_battle_zone.json +++ b/resources/config/npcs_battle_zone.json @@ -161,6 +161,168 @@ "hp": 35, "visibleRange" : 6.5, "canAttack": true + }, + { + "id": "ghost_07x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -5.6, + "positionY": 0.0, + "positionZ": -14.0, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true + }, + { + "id": "ghost_08x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -6.4, + "positionY": 0.0, + "positionZ": -14.0, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true + }, + { + "id": "ghost_09x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -5.6, + "positionY": 0.0, + "positionZ": -14.5, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true + }, + { + "id": "ghost_10x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -6.4, + "positionY": 0.0, + "positionZ": -14.5, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true + }, + { + "id": "ghost_11x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -5.6, + "positionY": 0.0, + "positionZ": -15.0, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true + }, + { + "id": "ghost_12x", + "name": "Тень", + "meshTextures": { + "Shadow_NPC_Rigged": "resources/w/shadow/Shadow_BaseColor.png" + }, + "animationIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationWalkPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionIdlePath": "resources/w/shadow/shadow_idle003.anim", + "animationActionAttackPath": "resources/w/shadow/shadow_attack003.anim", + "animationStandToActionPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToStandPath": "resources/w/shadow/shadow_idle003.anim", + "animationActionToDeathPath": "resources/w/shadow/shadow_die003.anim", + "animationDeathIdlePath": "resources/w/shadow/shadow_dead003.anim", + "positionX": -6.4, + "positionY": 0.0, + "positionZ": -15.0, + "walkSpeed": 1.5, + "rotationSpeed": 8.0, + "modelScale": 1.0, + "modelCorrectionRotX": -90.0, + "modelCorrectionRotY": 180.0, + "modelCorrectionRotZ": 0.0, + "hp": 35, + "visibleRange" : 6.5, + "canAttack": true } ] } diff --git a/resources/config/start_state.json b/resources/config/start_state.json index 7c58899..3c1fa86 100644 --- a/resources/config/start_state.json +++ b/resources/config/start_state.json @@ -1,775 +1,803 @@ { - "campaignId": "main", - "chatHistory": [ - [], - [], - [] - ], - "chatPreviewMsg": [ - "", - "", - "" - ], - "chatUnread": [ - true, - true, - true - ], - "currentLocationId": "", - "globalFloats": { + "localState": { + "locations": { + "location_dorm": { + "cameraAzimuth": -2.3499999046325684, + "cameraInclination": 1.103600025177002 + } + } }, - "globalInts": {}, - "inventory": { - "items": [] - }, - "isDarklands": false, - "isDawn": false, - "isNight": false, - "locations": { - "location_dorm": { - "dialogue": { - "active": true, - "currentNodeId": "line_1", - "dialogueId": "dialog_start001" - }, - "interactiveObjects": { - "Bed001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 + "networkState": { + "campaignId": "main", + "chatHistory": [ + [], + [], + [] + ], + "chatPreviewMsg": [ + "", + "", + "" + ], + "chatUnread": [ + true, + true, + true + ], + "currentLocationId": "", + "globalFloats": {}, + "globalInts": {}, + "inventory": { + "items": [] + }, + "isDarklands": false, + "isDawn": false, + "isNight": false, + "locations": { + "location_dorm": { + "dialogue": { + "active": true, + "currentNodeId": "line_1", + "dialogueId": "dialog_start001" }, - "Boombox001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Bath_-1_-1_1_Leaf_002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -2.825000047683716, - "positionY": 0.9695000052452087, - "positionZ": -14.300000190734863, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Bath_-1_1_1_Leaf_002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 2.825000047683716, - "positionY": 0.9695000052452087, - "positionZ": -14.300000190734863, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_-1_-1_0_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -10.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_-1_-1_1_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -15.699999809265137, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_-1_1_0_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -10.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_-1_1_1_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -15.699999809265137, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_1_-1_0_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 10.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_1_-1_1_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 15.699999809265137, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_1_1_0_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 10.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Room_1_1_1_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 15.699999809265137, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Utility_-1_-1_2_Leaf_001": { - "alpha": 1.0, - "animTask": { - "durationMs": 10.0, - "elapsedMs": 0.0, - "onCompleteName": "", - "startPosX": -1.100000023841858, - "startPosY": 0.9695000052452087, - "startPosZ": -19.950000762939453, - "startRotY": 0.0, - "startScale": 1.0, - "targetPosX": -1.100000023841858, - "targetPosY": 0.9695000052452087, - "targetPosZ": -19.950000762939453, - "targetRotY": -1.5707963705062866, - "targetScale": 1.0, - "type": 1 + "interactiveObjects": { + "Bed001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 }, - "isActive": true, - "isAnimating": true, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Utility_-1_1_2_Leaf_001": { - "alpha": 1.0, - "animTask": { - "durationMs": 10.0, - "elapsedMs": 0.0, - "onCompleteName": "", - "startPosX": 1.100000023841858, - "startPosY": 0.9695000052452087, - "startPosZ": -19.950000762939453, - "startRotY": 0.0, - "startScale": 1.0, - "targetPosX": 1.100000023841858, - "targetPosY": 0.9695000052452087, - "targetPosZ": -19.950000762939453, - "targetRotY": 1.5707963705062866, - "targetScale": 1.0, - "type": 1 + "Boombox001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 }, - "isActive": true, - "isAnimating": true, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": -19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 + "Door_Bath_-1_-1_1_Leaf_002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -2.825000047683716, + "positionY": 0.9695000052452087, + "positionZ": -14.300000190734863, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Bath_-1_1_1_Leaf_002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 2.825000047683716, + "positionY": 0.9695000052452087, + "positionZ": -14.300000190734863, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_-1_-1_0_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -10.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_-1_-1_1_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -15.699999809265137, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_-1_1_0_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -10.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_-1_1_1_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -15.699999809265137, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_1_-1_0_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 10.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_1_-1_1_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 15.699999809265137, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_1_1_0_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 10.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Room_1_1_1_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 15.699999809265137, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Utility_-1_-1_2_Leaf_001": { + "alpha": 1.0, + "animTask": { + "durationMs": 10.0, + "elapsedMs": 0.0, + "onCompleteName": "", + "startPosX": -1.100000023841858, + "startPosY": 0.9695000052452087, + "startPosZ": -19.950000762939453, + "startRotY": 0.0, + "startScale": 1.0, + "targetPosX": -1.100000023841858, + "targetPosY": 0.9695000052452087, + "targetPosZ": -19.950000762939453, + "targetRotY": -1.5707963705062866, + "targetScale": 1.0, + "type": 1 + }, + "isActive": true, + "isAnimating": true, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Utility_-1_1_2_Leaf_001": { + "alpha": 1.0, + "animTask": { + "durationMs": 10.0, + "elapsedMs": 0.0, + "onCompleteName": "", + "startPosX": 1.100000023841858, + "startPosY": 0.9695000052452087, + "startPosZ": -19.950000762939453, + "startRotY": 0.0, + "startScale": 1.0, + "targetPosX": 1.100000023841858, + "targetPosY": 0.9695000052452087, + "targetPosZ": -19.950000762939453, + "targetRotY": 1.5707963705062866, + "targetScale": 1.0, + "type": 1 + }, + "isActive": true, + "isAnimating": true, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": -19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Utility_1_-1_2_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Door_Utility_1_1_2_Leaf_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.100000023841858, + "positionY": 0.9695000052452087, + "positionZ": 19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Dryer001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Dryer002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Freezer001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Journal001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 5.842959880828857, + "positionY": 0.92849200963974, + "positionZ": -12.466099739074707, + "rotationY": 0.0, + "scale": 1.0 + }, + "Music001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 5.1006693840026855, + "positionY": 1.0181854963302612, + "positionZ": -11.958325386047363, + "rotationY": 0.0, + "scale": 1.0 + }, + "Phone001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 6.664400577545166, + "positionY": 0.8999999761581421, + "positionZ": -12.526200294494629, + "rotationY": 0.0, + "scale": 1.0 + }, + "Roof": { + "alpha": 1.0, + "isActive": false, + "isAnimating": false, + "positionX": 0.0, + "positionY": 3.2049999237060547, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_Bath_W_N_2_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 2.8249998092651367, + "positionY": 2.8500001430511475, + "positionZ": -12.850000381469727, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_LivingRoom_W_N_2_001": { + "alpha": 1.0, + "isActive": false, + "isAnimating": false, + "positionX": 4.949999809265137, + "positionY": 2.8500001430511475, + "positionZ": -14.25, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_LivingRoom_W_S_2_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -4.949999809265137, + "positionY": 2.8500001430511475, + "positionZ": -14.25, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_Main_Hall_And_Corridors_002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 2.8500001430511475, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_Others_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 2.8500001430511475, + "positionZ": 4.250000476837158, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_Utility_W_N_3_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 4.949999809265137, + "positionY": 2.8500001430511475, + "positionZ": -19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Room_Cover_Utility_W_S_3_001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -4.949999809265137, + "positionY": 2.8500001430511475, + "positionZ": -19.950000762939453, + "rotationY": 0.0, + "scale": 1.0 + }, + "Shelf001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Shower001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Sink001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Sink002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Sink003": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Sink004": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Sink005": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Stove001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "Toilet001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "WashingMachine001": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "WashingMachine002": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + } }, - "Door_Utility_1_-1_2_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 - }, - "Door_Utility_1_1_2_Leaf_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.100000023841858, - "positionY": 0.9695000052452087, - "positionZ": 19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 - }, - "Dryer001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Dryer002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Freezer001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Journal001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 5.842959880828857, - "positionY": 0.92849200963974, - "positionZ": -12.466099739074707, - "rotationY": 0.0, - "scale": 1.0 - }, - "Music001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 5.1006693840026855, - "positionY": 1.0181854963302612, - "positionZ": -11.958325386047363, - "rotationY": 0.0, - "scale": 1.0 - }, - "Phone001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 6.664400577545166, - "positionY": 0.8999999761581421, - "positionZ": -12.526200294494629, - "rotationY": 0.0, - "scale": 1.0 - }, - "Roof": { - "alpha": 1.0, - "isActive": false, - "isAnimating": false, - "positionX": 0.0, - "positionY": 3.2049999237060547, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_Bath_W_N_2_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 2.8249998092651367, - "positionY": 2.8500001430511475, - "positionZ": -12.850000381469727, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_LivingRoom_W_N_2_001": { - "alpha": 1.0, - "isActive": false, - "isAnimating": false, - "positionX": 4.949999809265137, - "positionY": 2.8500001430511475, - "positionZ": -14.25, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_LivingRoom_W_S_2_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -4.949999809265137, - "positionY": 2.8500001430511475, - "positionZ": -14.25, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_Main_Hall_And_Corridors_002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 2.8500001430511475, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_Others_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 2.8500001430511475, - "positionZ": 4.250000476837158, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_Utility_W_N_3_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 4.949999809265137, - "positionY": 2.8500001430511475, - "positionZ": -19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 - }, - "Room_Cover_Utility_W_S_3_001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -4.949999809265137, - "positionY": 2.8500001430511475, - "positionZ": -19.950000762939453, - "rotationY": 0.0, - "scale": 1.0 - }, - "Shelf001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Shower001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Sink001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Sink002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Sink003": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Sink004": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Sink005": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Stove001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "Toilet001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "WashingMachine001": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "WashingMachine002": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.0, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - } - }, - "npcs": { - "npc_alik": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": false, - "faceTargetId": "", - "facingAngle": 1.5707963705062866, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.334780216217041, - 0.0, - -15.038200378417969 - ], - "hp": 100.0, - "pathWaypoints": [ - [ + "npcs": { + "npc_alik": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 1.5707963705062866, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.334780216217041, + 0.0, + -15.038200378417969 + ], + "hp": 100.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 10, + 4, + 5, + 8, + 11, + 9, + 6, + 3, + 2, + 7 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + [ + -6.296899795532227, + 0.0, + -15.041899681091309 + ] + ], + "position": [ + -6.334780216217041, + 0.0, + -15.038200378417969 + ], + "requestedWalkTarget": [ + -6.334780216217041, + 0.0, + -15.038200378417969 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ -6.296899795532227, 0.0, -15.041899681091309 ] - ], - "position": [ - -6.334780216217041, - 0.0, - -15.038200378417969 - ], - "requestedWalkTarget": [ - -6.334780216217041, - 0.0, - -15.038200378417969 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - -6.296899795532227, - 0.0, - -15.041899681091309 - ] - } - }, - "scriptGlobals": { - "alik_door_opened": false, - "bathroom_door_opened": false, - "journal_picked_up": false, - "phone_picked_up": false, - "player_door_opened": false - }, - "state": { - "activeNavigationIndex": 0, - "cameraAzimuth": -2.3499999046325684, - "cameraInclination": 1.103600025177002, - "targetInteractNpcId": "", - "targetInteractiveObjectId": "", - "targetTeleportZoneId": "", - "taxi": { - "arrivedCallbackCalled": false, - "car": { - "currentWaypoint": 0, - "mode": 1, - "position": [ - -20.850000381469727, - 0.0, - 64.0 - ], - "rotation": 0.0, - "steeringAngle": 0.0, - "velocity": 0.0, - "waypoints": [], - "wheelAngle": 0.0 + } + }, + "scriptGlobals": { + "alik_door_opened": false, + "bathroom_door_opened": false, + "journal_picked_up": false, + "phone_picked_up": false, + "player_door_opened": false + }, + "state": { + "activeNavigationIndex": 0, + "targetInteractNpcId": "", + "targetInteractiveObjectId": "", + "targetTeleportZoneId": "", + "taxi": { + "arrivedCallbackCalled": false, + "car": { + "currentWaypoint": 0, + "mode": 1, + "position": [ + -20.850000381469727, + 0.0, + 64.0 + ], + "rotation": 0.0, + "steeringAngle": 0.0, + "velocity": 0.0, + "waypoints": [], + "wheelAngle": 0.0 + } + } + }, + "teleportZones": { + "tp_dorm_to_2floor": false, + "tp_dorm_to_loc2": false + }, + "triggerZones": { + "ladder_zone001": { + "enabled": true, + "playerInside": false + }, + "pickup_phone_zone001": { + "enabled": true, + "playerInside": false + }, + "taxi_zone001": { + "enabled": true, + "playerInside": false } } - }, - "teleportZones": { - "tp_dorm_to_2floor": false, - "tp_dorm_to_loc2": false - }, - "triggerZones": { - "ladder_zone001": { - "enabled": true, - "playerInside": false - }, - "pickup_phone_zone001": { - "enabled": true, - "playerInside": false - }, - "taxi_zone001": { - "enabled": true, - "playerInside": false - } } - } - }, - "money": 5500, - "playerHp": 200.0, - "playerMaxHp": 200.0, - "players": { - "player": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - 0.0, - 0.0, - 0.0 - ], - "hp": 200.0, - "pathWaypoints": [ - [ + }, + "money": 5500, + "playerMaxHp": 200.0, + "players": { + "player1": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [], + "navigationRetryTicks": 0, + "pathWaypoints": [ + [ + 6.8031005859375, + 0.0, + -14.641900062561035 + ] + ], + "position": [ + 6.7634501457214355, + 0.0, + -14.60219955444336 + ], + "requestedWalkTarget": [ + 6.7634501457214355, + 0.0, + -14.60219955444336 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ 6.8031005859375, 0.0, -14.641900062561035 ] - ], - "position": [ - 6.7634501457214355, - 0.0, - -14.60219955444336 - ], - "requestedWalkTarget": [ - 6.7634501457214355, - 0.0, - -14.60219955444336 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - 6.8031005859375, - 0.0, - -14.641900062561035 - ] - } - }, - "questJournal": { - "quests": [ - { - "activeObjectiveIndex": 0, - "id": "tutorial_take_items", - "objectives": [ - { - "completed": false, - "id": "take_phone", - "visible": true - }, - { - "completed": false, - "id": "take_journal", - "visible": true - } - ], - "status": 1 - }, - { - "activeObjectiveIndex": 0, - "id": "ghost_lore", - "objectives": [ - { - "completed": false, - "id": "ghost_lore_aiperi", - "visible": true - }, - { - "completed": false, - "id": "ghost_lore_alik", - "visible": false - }, - { - "completed": false, - "id": "ghost_lore_teacher", - "visible": true - } - ], - "status": 0 - }, - { - "activeObjectiveIndex": 0, - "id": "ghost_coursework", - "objectives": [ - { - "completed": false, - "id": "ghost_coursework_find", - "visible": true - }, - { - "completed": false, - "id": "ghost_coursework_mark", - "visible": true - } - ], - "status": 0 - }, - { - "activeObjectiveIndex": 0, - "id": "ghost_release", - "objectives": [ - { - "completed": false, - "id": "ghost_release_reportcard", - "visible": true - }, - { - "completed": false, - "id": "ghost_release_mark", - "visible": true - }, - { - "completed": false, - "id": "ghost_release_show", - "visible": true - } - ], - "status": 0 - }, - { - "activeObjectiveIndex": 0, - "id": "study_beginning", - "objectives": [ - { - "completed": false, - "id": "study_beginning_lecture", - "visible": true - }, - { - "completed": false, - "id": "study_beginning_task", - "visible": true - } - ], - "status": 1 - }, - { - "activeObjectiveIndex": 0, - "id": "study_project", - "objectives": [ - { - "completed": false, - "id": "study_project_book", - "visible": true - }, - { - "completed": false, - "id": "study_project_write", - "visible": true - }, - { - "completed": false, - "id": "study_project_give", - "visible": true - } - ], - "status": 0 - }, - { - "activeObjectiveIndex": 0, - "id": "aiperi_knife", - "objectives": [ - { - "completed": false, - "id": "aiperi_knife_keys", - "visible": true - }, - { - "completed": false, - "id": "aiperi_knife_take", - "visible": true - }, - { - "completed": false, - "id": "aiperi_knife_give", - "visible": true - } - ], - "status": 0 } - ] + }, + "questJournal": { + "quests": [ + { + "activeObjectiveIndex": 0, + "id": "tutorial_take_items", + "objectives": [ + { + "completed": false, + "id": "take_phone", + "visible": true + }, + { + "completed": false, + "id": "take_journal", + "visible": true + } + ], + "status": 1 + }, + { + "activeObjectiveIndex": 0, + "id": "ghost_lore", + "objectives": [ + { + "completed": false, + "id": "ghost_lore_aiperi", + "visible": true + }, + { + "completed": false, + "id": "ghost_lore_alik", + "visible": false + }, + { + "completed": false, + "id": "ghost_lore_teacher", + "visible": true + } + ], + "status": 0 + }, + { + "activeObjectiveIndex": 0, + "id": "ghost_coursework", + "objectives": [ + { + "completed": false, + "id": "ghost_coursework_find", + "visible": true + }, + { + "completed": false, + "id": "ghost_coursework_mark", + "visible": true + } + ], + "status": 0 + }, + { + "activeObjectiveIndex": 0, + "id": "ghost_release", + "objectives": [ + { + "completed": false, + "id": "ghost_release_reportcard", + "visible": true + }, + { + "completed": false, + "id": "ghost_release_mark", + "visible": true + }, + { + "completed": false, + "id": "ghost_release_show", + "visible": true + } + ], + "status": 0 + }, + { + "activeObjectiveIndex": 0, + "id": "study_beginning", + "objectives": [ + { + "completed": false, + "id": "study_beginning_lecture", + "visible": true + }, + { + "completed": false, + "id": "study_beginning_task", + "visible": true + } + ], + "status": 1 + }, + { + "activeObjectiveIndex": 0, + "id": "study_project", + "objectives": [ + { + "completed": false, + "id": "study_project_book", + "visible": true + }, + { + "completed": false, + "id": "study_project_write", + "visible": true + }, + { + "completed": false, + "id": "study_project_give", + "visible": true + } + ], + "status": 0 + }, + { + "activeObjectiveIndex": 0, + "id": "aiperi_knife", + "objectives": [ + { + "completed": false, + "id": "aiperi_knife_keys", + "visible": true + }, + { + "completed": false, + "id": "aiperi_knife_take", + "visible": true + }, + { + "completed": false, + "id": "aiperi_knife_give", + "visible": true + } + ], + "status": 0 + } + ] + }, + "savedAt": "2026-11-10 20:38", + "schemaVersion": 5, + "taxiIsCalled": false, + "tutorialJournalScreenOpened": false, + "tutorialNeedOpenTaxiScreen": false, + "tutorialPhoneChatScreenOpened": false, + "tutorialStep": 0, + "tutorialTaxiHintDone": false }, - "savedAt": "2026-10-30 14:48", - "schemaVersion": 1, - "taxiIsCalled": false, - "tutorialJournalScreenOpened": false, - "tutorialNeedOpenTaxiScreen": false, - "tutorialPhoneChatScreenOpened": false, - "tutorialStep": 0, - "tutorialTaxiHintDone": false + "persistenceVersion": 1 } \ No newline at end of file diff --git a/resources/config/start_state_battle_zone.json b/resources/config/start_state_battle_zone.json index 0f4e46a..f8ce63d 100644 --- a/resources/config/start_state_battle_zone.json +++ b/resources/config/start_state_battle_zone.json @@ -1,574 +1,1002 @@ { - "localState": { - "locations": { - "uni_exterior": { - "cameraAzimuth": -2.3499999046325684, - "cameraInclination": 1.103600025177002 - } - } - }, - "networkState": { - "campaignId": "battle_zone", - "chatHistory": [ - [], - [], - [] - ], - "chatPreviewMsg": [ - "", - "", - "" - ], - "chatUnread": [ - true, - true, - true - ], - "currentLocationId": "", - "globalFloats": { - }, - "globalInts": {}, - "inventory": { - "items": [] - }, - "isDarklands": true, - "isDawn": false, - "isNight": true, - "locations": { - "uni_exterior": { - "dialogue": { - "active": false - }, - "interactiveObjects": { - "intBin_Cans": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.6000000238418579, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Plastic": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.399999976158142, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Waste_A": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 2.200000047683716, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Waste_B": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 3.0, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intRoof": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 3.200000047683716, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.00": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.01": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.02": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - } - }, - "npcs": { - "ghost_01x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 2, - 3, - 10, - 5, - 6, - 8, - 7, - 9, - 4, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -12.0 - ] - }, - "ghost_02x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 8, - 11, - 3, - 10, - 2, - 9, - 5, - 4, - 7, - 6 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -12.0 - ] - }, - "ghost_03x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 2, - 4, - 8, - 3, - 6, - 10, - 9, - 7, - 5, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -12.5 - ] - }, - "ghost_04x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 3, - 4, - 7, - 10, - 5, - 11, - 9, - 2, - 8, - 6 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -12.5 - ] - }, - "ghost_05x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 8, - 7, - 2, - 9, - 4, - 10, - 6, - 5, - 3, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -13.0 - ] - }, - "ghost_06x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 7, - 11, - 5, - 4, - 3, - 10, - 9, - 8, - 6, - 2 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -13.0 - ] - } - }, - "scriptGlobals": {}, - "state": { - "activeNavigationIndex": 0, - "targetInteractNpcId": "", - "targetInteractiveObjectId": "", - "targetTeleportZoneId": "", - "taxi": { - "arrivedCallbackCalled": false, - "car": { - "currentWaypoint": 0, - "mode": 1, - "position": [ - -100.0, - -100.0, - -100.0 - ], - "rotation": 0.0, - "steeringAngle": 0.0, - "velocity": 0.0, - "waypoints": [], - "wheelAngle": 0.0 + "localState": { + "locations": { + "park_korea": { + "cameraAzimuth": -2.3499999046325684, + "cameraInclination": 1.103600025177002 } - } + } + }, + "networkState": { + "campaignId": "battle_zone", + "chatHistory": [ + [ + ], + [ + ], + [ + ] + ], + "chatPreviewMsg": [ + "", + "", + "" + ], + "chatUnread": [ + true, + true, + true + ], + "currentLocationId": "", + "globalFloats": { }, - "teleportZones": {}, - "triggerZones": {} - } + "globalInts": { + }, + "inventory": { + "items": [ + ] + }, + "isDarklands": true, + "isDawn": false, + "isNight": true, + "locations": { + "park_korea": { + "dialogue": { + "active": false + }, + "interactiveObjects": { + "intBin_Cans": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.60000002384185791, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Plastic": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.3999999761581421, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Waste_A": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 2.2000000476837158, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Waste_B": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 3.0, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intRoof": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 3.2000000476837158, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.00": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.01": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.02": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + } + }, + "npcs": { + "ghost_01x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 3, + 10, + 5, + 6, + 8, + 7, + 9, + 4, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -12.0 + ] + }, + "ghost_02x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 11, + 3, + 10, + 2, + 9, + 5, + 4, + 7, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -12.0 + ] + }, + "ghost_03x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 4, + 8, + 3, + 6, + 10, + 9, + 7, + 5, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -12.5 + ] + }, + "ghost_04x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 3, + 4, + 7, + 10, + 5, + 11, + 9, + 2, + 8, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ] + }, + "ghost_05x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 7, + 2, + 9, + 4, + 10, + 6, + 5, + 3, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -13.0 + ] + }, + "ghost_06x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 7, + 11, + 5, + 4, + 3, + 10, + 9, + 8, + 6, + 2 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -13.0 + ] + }, + "ghost_07x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 3, + 10, + 5, + 6, + 8, + 7, + 9, + 4, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -14.0 + ] + }, + "ghost_08x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 11, + 3, + 10, + 2, + 9, + 5, + 4, + 7, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -14.0 + ] + }, + "ghost_09x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 4, + 8, + 3, + 6, + 10, + 9, + 7, + 5, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -14.5 + ] + }, + "ghost_10x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -14.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 3, + 4, + 7, + 10, + 5, + 11, + 9, + 2, + 8, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -14.5 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -14.5 + ] + }, + "ghost_11x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 7, + 2, + 9, + 4, + 10, + 6, + 5, + 3, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -15.0 + ] + }, + "ghost_12x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 7, + 11, + 5, + 4, + 3, + 10, + 9, + 8, + 6, + 2 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -15.0 + ] + } + }, + "scriptGlobals": { + }, + "state": { + "activeNavigationIndex": 0, + "targetInteractNpcId": "", + "targetInteractiveObjectId": "", + "targetTeleportZoneId": "", + "taxi": { + "arrivedCallbackCalled": false, + "car": { + "currentWaypoint": 0, + "mode": 1, + "position": [ + -100.0, + -100.0, + -100.0 + ], + "rotation": 0.0, + "steeringAngle": 0.0, + "velocity": 0.0, + "waypoints": [ + ], + "wheelAngle": 0.0 + } + } + }, + "teleportZones": { + }, + "triggerZones": { + } + } + }, + "money": 5500, + "playerHp": 200.0, + "playerMaxHp": 200.0, + "players": { + "player1": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -5.4, + 0.0, + 12.8 + ] + ], + "position": [ + -5.4, + 0.0, + 12.8 + ], + "requestedWalkTarget": [ + -5.4, + 0.0, + 12.8 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -5.4, + 0.0, + 12.8 + ] + }, + "player2": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -6.8, + 0.0, + 13.0 + ] + ], + "position": [ + -6.8, + 0.0, + 13.0 + ], + "requestedWalkTarget": [ + -6.8, + 0.0, + 13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -6.8, + 0.0, + 13.0 + ] + }, + "player3": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -5.4, + 0.0, + 14.8 + ] + ], + "position": [ + -5.4, + 0.0, + 14.8 + ], + "requestedWalkTarget": [ + -5.4, + 0.0, + 14.8 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -5.4, + 0.0, + 14.8 + ] + }, + "player4": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -6.8, + 0.0, + 15.0 + ] + ], + "position": [ + -6.8, + 0.0, + 15.0 + ], + "requestedWalkTarget": [ + -6.8, + 0.0, + 15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -6.8, + 0.0, + 15.0 + ] + } + }, + "questJournal": { + "quests": [ + ] + }, + "savedAt": "2026-11-05 17:43", + "schemaVersion": 5, + "taxiIsCalled": false, + "tutorialJournalScreenOpened": false, + "tutorialNeedOpenTaxiScreen": false, + "tutorialPhoneChatScreenOpened": false, + "tutorialStep": 0, + "tutorialTaxiHintDone": false }, - "money": 5500, - "playerHp": 200.0, - "playerMaxHp": 200.0, - "players": { - "player2": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": false, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - 0.0, - 0.0, - 0.0 - ], - "hp": 200.0, - "pathWaypoints": [[ - -6.4, - 0.0, - 13.0 - ]], - "position": [ - -6.4, - 0.0, - 13.0 - ], - "requestedWalkTarget": [ - -6.4, - 0.0, - 13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - -6.4, - 0.0, - 13.0 - ] - }, - "player": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - 0.0, - 0.0, - 0.0 - ], - "hp": 200.0, - "pathWaypoints": [ - [ - -5.8, - 0.0, - 12.8 - ] - ], - "position": [ - -5.8, - 0.0, - 12.8 - ], - "requestedWalkTarget": [ - -5.8, - 0.0, - 12.8 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - -5.8, - 0.0, - 12.8 - ] - } - }, - "questJournal": { - "quests": [] - }, - "savedAt": "2026-11-05 17:43", - "schemaVersion": 5, - "taxiIsCalled": false, - "tutorialJournalScreenOpened": false, - "tutorialNeedOpenTaxiScreen": false, - "tutorialPhoneChatScreenOpened": false, - "tutorialStep": 0, - "tutorialTaxiHintDone": false - }, - "persistenceVersion": 1 + "persistenceVersion": 1 } \ No newline at end of file diff --git a/resources/config/start_state_battle_zone_singleplayer.json b/resources/config/start_state_battle_zone_singleplayer.json index 5f8abad..f8ce63d 100644 --- a/resources/config/start_state_battle_zone_singleplayer.json +++ b/resources/config/start_state_battle_zone_singleplayer.json @@ -1,574 +1,1002 @@ { - "localState": { - "locations": { - "uni_exterior": { - "cameraAzimuth": -2.3499999046325684, - "cameraInclination": 1.103600025177002 - } - } - }, - "networkState": { - "campaignId": "battle_zone", - "chatHistory": [ - [], - [], - [] - ], - "chatPreviewMsg": [ - "", - "", - "" - ], - "chatUnread": [ - true, - true, - true - ], - "currentLocationId": "", - "globalFloats": { - }, - "globalInts": {}, - "inventory": { - "items": [] - }, - "isDarklands": true, - "isDawn": false, - "isNight": true, - "locations": { - "uni_exterior": { - "dialogue": { - "active": false - }, - "interactiveObjects": { - "intBin_Cans": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.6000000238418579, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Plastic": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.399999976158142, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Waste_A": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 2.200000047683716, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intBin_Waste_B": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 3.0, - "positionY": 0.45736101269721985, - "positionZ": 3.8499999046325684, - "rotationY": 0.0, - "scale": 1.0 - }, - "intRoof": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 3.200000047683716, - "positionZ": 0.0, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.00": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": -1.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.01": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 0.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - }, - "intVending.02": { - "alpha": 1.0, - "isActive": true, - "isAnimating": false, - "positionX": 1.0, - "positionY": 0.9150000214576721, - "positionZ": -3.9000000953674316, - "rotationY": 0.0, - "scale": 1.0 - } - }, - "npcs": { - "ghost_01x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 2, - 3, - 10, - 5, - 6, - 8, - 7, - 9, - 4, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -12.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -12.0 - ] - }, - "ghost_02x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 8, - 11, - 3, - 10, - 2, - 9, - 5, - 4, - 7, - 6 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -12.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -12.0 - ] - }, - "ghost_03x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 2, - 4, - 8, - 3, - 6, - 10, - 9, - 7, - 5, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -12.5 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -12.5 - ] - }, - "ghost_04x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 3, - 4, - 7, - 10, - 5, - 11, - 9, - 2, - 8, - 6 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -12.5 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -12.5 - ] - }, - "ghost_05x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 8, - 7, - 2, - 9, - 4, - 10, - 6, - 5, - 3, - 11 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "requestedWalkTarget": [ - -5.599999904632568, - 0.0, - -13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -5.599999904632568, - 0.0, - -13.0 - ] - }, - "ghost_06x": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "hp": 35.0, - "movedLastTick": false, - "movementBlockedTicks": 0, - "navigationRetryCooldownIndex": 0, - "navigationRetryCooldownTicks": [ - 7, - 11, - 5, - 4, - 3, - 10, - 9, - 8, - 6, - 2 - ], - "navigationRetryTicks": 0, - "pathWaypoints": [], - "position": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "requestedWalkTarget": [ - -6.400000095367432, - 0.0, - -13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.5, - "walkTarget": [ - -6.400000095367432, - 0.0, - -13.0 - ] - } - }, - "scriptGlobals": {}, - "state": { - "activeNavigationIndex": 0, - "targetInteractNpcId": "", - "targetInteractiveObjectId": "", - "targetTeleportZoneId": "", - "taxi": { - "arrivedCallbackCalled": false, - "car": { - "currentWaypoint": 0, - "mode": 1, - "position": [ - -100.0, - -100.0, - -100.0 - ], - "rotation": 0.0, - "steeringAngle": 0.0, - "velocity": 0.0, - "waypoints": [], - "wheelAngle": 0.0 + "localState": { + "locations": { + "park_korea": { + "cameraAzimuth": -2.3499999046325684, + "cameraInclination": 1.103600025177002 } - } + } + }, + "networkState": { + "campaignId": "battle_zone", + "chatHistory": [ + [ + ], + [ + ], + [ + ] + ], + "chatPreviewMsg": [ + "", + "", + "" + ], + "chatUnread": [ + true, + true, + true + ], + "currentLocationId": "", + "globalFloats": { }, - "teleportZones": {}, - "triggerZones": {} - } + "globalInts": { + }, + "inventory": { + "items": [ + ] + }, + "isDarklands": true, + "isDawn": false, + "isNight": true, + "locations": { + "park_korea": { + "dialogue": { + "active": false + }, + "interactiveObjects": { + "intBin_Cans": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.60000002384185791, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Plastic": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.3999999761581421, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Waste_A": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 2.2000000476837158, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intBin_Waste_B": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 3.0, + "positionY": 0.45736101269721985, + "positionZ": 3.8499999046325684, + "rotationY": 0.0, + "scale": 1.0 + }, + "intRoof": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 3.2000000476837158, + "positionZ": 0.0, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.00": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": -1.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.01": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 0.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + }, + "intVending.02": { + "alpha": 1.0, + "isActive": true, + "isAnimating": false, + "positionX": 1.0, + "positionY": 0.91500002145767212, + "positionZ": -3.9000000953674316, + "rotationY": 0.0, + "scale": 1.0 + } + }, + "npcs": { + "ghost_01x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 3, + 10, + 5, + 6, + 8, + 7, + 9, + 4, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -12.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -12.0 + ] + }, + "ghost_02x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 11, + 3, + 10, + 2, + 9, + 5, + 4, + 7, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -12.0 + ] + }, + "ghost_03x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 4, + 8, + 3, + 6, + 10, + 9, + 7, + 5, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -12.5 + ] + }, + "ghost_04x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 3, + 4, + 7, + 10, + 5, + 11, + 9, + 2, + 8, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ] + }, + "ghost_05x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 7, + 2, + 9, + 4, + 10, + 6, + 5, + 3, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -13.0 + ] + }, + "ghost_06x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 7, + 11, + 5, + 4, + 3, + 10, + 9, + 8, + 6, + 2 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -13.0 + ] + }, + "ghost_07x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 3, + 10, + 5, + 6, + 8, + 7, + 9, + 4, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -14.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -14.0 + ] + }, + "ghost_08x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 11, + 3, + 10, + 2, + 9, + 5, + 4, + 7, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -14.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -14.0 + ] + }, + "ghost_09x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 2, + 4, + 8, + 3, + 6, + 10, + 9, + 7, + 5, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -14.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -14.5 + ] + }, + "ghost_10x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -14.5 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 3, + 4, + 7, + 10, + 5, + 11, + 9, + 2, + 8, + 6 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -14.5 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -12.5 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -14.5 + ] + }, + "ghost_11x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 8, + 7, + 2, + 9, + 4, + 10, + 6, + 5, + 3, + 11 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "requestedWalkTarget": [ + -5.5999999046325684, + 0.0, + -15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -5.5999999046325684, + 0.0, + -15.0 + ] + }, + "ghost_12x": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "hp": 35.0, + "movedLastTick": false, + "movementBlockedTicks": 0, + "navigationRetryCooldownIndex": 0, + "navigationRetryCooldownTicks": [ + 7, + 11, + 5, + 4, + 3, + 10, + 9, + 8, + 6, + 2 + ], + "navigationRetryTicks": 0, + "pathWaypoints": [ + ], + "position": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "requestedWalkTarget": [ + -6.4000000953674316, + 0.0, + -15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.5, + "walkTarget": [ + -6.4000000953674316, + 0.0, + -15.0 + ] + } + }, + "scriptGlobals": { + }, + "state": { + "activeNavigationIndex": 0, + "targetInteractNpcId": "", + "targetInteractiveObjectId": "", + "targetTeleportZoneId": "", + "taxi": { + "arrivedCallbackCalled": false, + "car": { + "currentWaypoint": 0, + "mode": 1, + "position": [ + -100.0, + -100.0, + -100.0 + ], + "rotation": 0.0, + "steeringAngle": 0.0, + "velocity": 0.0, + "waypoints": [ + ], + "wheelAngle": 0.0 + } + } + }, + "teleportZones": { + }, + "triggerZones": { + } + } + }, + "money": 5500, + "playerHp": 200.0, + "playerMaxHp": 200.0, + "players": { + "player1": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": true, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -5.4, + 0.0, + 12.8 + ] + ], + "position": [ + -5.4, + 0.0, + 12.8 + ], + "requestedWalkTarget": [ + -5.4, + 0.0, + 12.8 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -5.4, + 0.0, + 12.8 + ] + }, + "player2": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -6.8, + 0.0, + 13.0 + ] + ], + "position": [ + -6.8, + 0.0, + 13.0 + ], + "requestedWalkTarget": [ + -6.8, + 0.0, + 13.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -6.8, + 0.0, + 13.0 + ] + }, + "player3": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -5.4, + 0.0, + 14.8 + ] + ], + "position": [ + -5.4, + 0.0, + 14.8 + ], + "requestedWalkTarget": [ + -5.4, + 0.0, + 14.8 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -5.4, + 0.0, + 14.8 + ] + }, + "player4": { + "animationFrame": 0.0, + "attackTargetId": "", + "attack_cooldown": 0.0, + "battle_state": 0, + "currentState": 0, + "currentWaypointIndex": 0, + "enabled": false, + "faceTargetId": "", + "facingAngle": 0.0, + "homeDriftCheckTimer": 5.0, + "homePosition": [ + 0.0, + 0.0, + 0.0 + ], + "hp": 200.0, + "pathWaypoints": [ + [ + -6.8, + 0.0, + 15.0 + ] + ], + "position": [ + -6.8, + 0.0, + 15.0 + ], + "requestedWalkTarget": [ + -6.8, + 0.0, + 15.0 + ], + "showWeapon": true, + "targetFacingAngle": 0.0, + "visibleRange": 6.0, + "walkTarget": [ + -6.8, + 0.0, + 15.0 + ] + } + }, + "questJournal": { + "quests": [ + ] + }, + "savedAt": "2026-11-05 17:43", + "schemaVersion": 5, + "taxiIsCalled": false, + "tutorialJournalScreenOpened": false, + "tutorialNeedOpenTaxiScreen": false, + "tutorialPhoneChatScreenOpened": false, + "tutorialStep": 0, + "tutorialTaxiHintDone": false }, - "money": 5500, - "playerHp": 200.0, - "playerMaxHp": 200.0, - "players": { - "player2": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": false, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - 0.0, - 0.0, - 0.0 - ], - "hp": 200.0, - "pathWaypoints": [[ - -6.8, - 0.0, - 13.0 - ]], - "position": [ - -6.8, - 0.0, - 13.0 - ], - "requestedWalkTarget": [ - -6.8, - 0.0, - 13.0 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - -6.8, - 0.0, - 13.0 - ] - }, - "player": { - "animationFrame": 0.0, - "attackTargetId": "", - "attack_cooldown": 0.0, - "battle_state": 0, - "currentState": 0, - "currentWaypointIndex": 0, - "enabled": true, - "faceTargetId": "", - "facingAngle": 0.0, - "homeDriftCheckTimer": 5.0, - "homePosition": [ - 0.0, - 0.0, - 0.0 - ], - "hp": 200.0, - "pathWaypoints": [ - [ - -5.4, - 0.0, - 12.8 - ] - ], - "position": [ - -5.4, - 0.0, - 12.8 - ], - "requestedWalkTarget": [ - -5.4, - 0.0, - 12.8 - ], - "showWeapon": true, - "targetFacingAngle": 0.0, - "visibleRange": 6.0, - "walkTarget": [ - -5.4, - 0.0, - 12.8 - ] - } - }, - "questJournal": { - "quests": [] - }, - "savedAt": "2026-11-05 17:43", - "schemaVersion": 5, - "taxiIsCalled": false, - "tutorialJournalScreenOpened": false, - "tutorialNeedOpenTaxiScreen": false, - "tutorialPhoneChatScreenOpened": false, - "tutorialStep": 0, - "tutorialTaxiHintDone": false - }, - "persistenceVersion": 1 + "persistenceVersion": 1 } \ No newline at end of file diff --git a/server/tests/LocationGameStateTests.cpp b/server/tests/LocationGameStateTests.cpp index 4d09e05..58c1260 100644 --- a/server/tests/LocationGameStateTests.cpp +++ b/server/tests/LocationGameStateTests.cpp @@ -194,6 +194,59 @@ int main() return fail("Hostile NPC did not return home after losing its target"); } + auto blocker = std::make_shared(); + blocker->enabled = true; + blocker->hp = 50.f; + blocker->position = {0.8f, 0.f, 0.f}; + state.npcs["blocker"] = blocker; + hostileNpc.position = Eigen::Vector3f::Zero(); + hostileNpc.homePosition = {5.f, 0.f, 0.f}; + hostileNpc.attackTargetId = "player"; + hostileNpc.requestedWalkTarget = playerOne->position; + hostileNpc.walkTarget = playerOne->position; + hostileNpc.pathWaypoints = {playerOne->position}; + hostileNpc.currentWaypointIndex = 0; + hostileNpc.movementBlockedTicks = 0; + playerOne->enabled = true; + playerOne->hp = 75.f; + playerOne->position = {4.f, 0.f, 0.f}; + playerTwo->enabled = true; + playerTwo->hp = 75.f; + playerTwo->position = {2.f, 0.f, 0.f}; + + bool blockedRetryRequested = false; + for (int tick = 0; tick < 10 && !blockedRetryRequested; ++tick) { + const FRG::LocationSimulationEvents events = + state.update(100, combatPlayers, false); + for (const auto& event : events.characters) { + if (event.characterId == "npc" && + event.events.forceNavigationReplan) { + blockedRetryRequested = true; + if (!state.replanCharacter( + "npc", combatPlayers, + event.events.blockingCharacterId)) { + return fail("Blocked NPC replan was rejected"); + } + } + } + } + if (!blockedRetryRequested || + hostileNpc.attackTargetId != "player2" || + (hostileNpc.requestedWalkTarget - playerTwo->position).norm() > + FRG::CharacterState::kWalkThreshold) { + return fail("Blocked NPC did not switch to the nearest player"); + } + + playerOne->enabled = false; + playerTwo->enabled = false; + if (!state.replanCharacter("npc", combatPlayers, "blocker") || + !hostileNpc.attackTargetId.empty() || + hostileNpc.battle_state != 0 || + (hostileNpc.requestedWalkTarget - hostileNpc.homePosition).norm() > + FRG::CharacterState::kWalkThreshold) { + return fail("Blocked NPC did not return home without an eligible target"); + } + FRG::CampaignConfig battleZone; battleZone.id = "battle_zone"; battleZone.questsPath = "resources/config/quests_battle_zone.json"; diff --git a/src/LocationGameState.cpp b/src/LocationGameState.cpp index 2a2d742..f223a7a 100644 --- a/src/LocationGameState.cpp +++ b/src/LocationGameState.cpp @@ -173,11 +173,84 @@ bool LocationGameState::replanCharacter( { CharacterState* character = findCharacter(id, players); if (!character || !location) return false; + if (!forcedObstacleId.empty() && !character->isPlayer && + character->canAttack && character->hp > 0.f) { + const std::string selectedTarget = + selectNpcTarget(*character, players, false); + if (selectedTarget != character->attackTargetId) { + character->stopInPlace(); + character->attackTargetId = selectedTarget; + character->battle_state = 0; + character->attack = 0; + } + + if (!selectedTarget.empty()) { + const CharacterState* target = findCharacter(selectedTarget, players); + if (target) { + character->setTarget( + target->position, {}, *location, id, + collectPathObstacles(id, players, forcedObstacleId)); + return true; + } + } + + character->attackTargetId.clear(); + character->battle_state = 0; + character->attack = 0; + const Eigen::Vector3f homeTarget( + character->homePosition.x(), 0.f, character->homePosition.z()); + if ((homeTarget - character->position).norm() > + CharacterState::kWalkThreshold) { + character->setTarget( + homeTarget, {}, *location, id, + collectPathObstacles(id, players, forcedObstacleId)); + } + return true; + } character->forceReplan( *location, id, collectPathObstacles(id, players, forcedObstacleId)); return true; } +std::string LocationGameState::selectNpcTarget( + const CharacterState& npc, + const PlayerStateMap& players, + bool preserveValidLock) const +{ + if (preserveValidLock) { + const auto locked = players.find(npc.attackTargetId); + if (locked != players.end() && locked->second && + locked->second->enabled && locked->second->hp > 0.f) + return npc.attackTargetId; + } + + std::vector playerIds; + playerIds.reserve(players.size()); + for (const auto& [id, player] : players) + if (player && player->enabled && player->hp > 0.f) + playerIds.push_back(id); + std::sort(playerIds.begin(), playerIds.end()); + + const float visibleRangeSquared = npc.visibleRange * npc.visibleRange; + std::string selectedTarget; + float nearestDistanceSquared = visibleRangeSquared; + for (const std::string& playerId : playerIds) { + const Eigen::Vector3f delta = + players.at(playerId)->position - npc.position; + const float distanceSquared = + delta.x() * delta.x() + delta.z() * delta.z(); + if (distanceSquared <= nearestDistanceSquared && + (selectedTarget.empty() || + distanceSquared < nearestDistanceSquared || + (distanceSquared == nearestDistanceSquared && + playerId < selectedTarget))) { + selectedTarget = playerId; + nearestDistanceSquared = distanceSquared; + } + } + return selectedTarget; +} + void LocationGameState::startTaxi() { location->taxiCar.waypoints = location->taxiCarWaypoints; @@ -321,13 +394,6 @@ LocationSimulationEvents LocationGameState::update( if (player) playerIds.push_back(id); std::sort(playerIds.begin(), playerIds.end()); - std::vector eligiblePlayerIds; - for (const std::string& id : playerIds) { - const auto& player = players.at(id); - if (player->enabled && player->hp > 0.f) - eligiblePlayerIds.push_back(id); - } - std::vector npcIds; npcIds.reserve(npcs.size()); for (const auto& [id, npc] : npcs) @@ -343,30 +409,8 @@ LocationSimulationEvents LocationGameState::update( continue; const std::string previousTarget = npc.attackTargetId; - const auto locked = players.find(previousTarget); - const bool lockValid = - locked != players.end() && locked->second && - locked->second->enabled && locked->second->hp > 0.f; - std::string selectedTarget = lockValid ? previousTarget : std::string(); - - if (!lockValid) { - float nearestDistanceSquared = npc.visibleRange * npc.visibleRange; - for (const std::string& playerId : eligiblePlayerIds) { - const Eigen::Vector3f delta = - players.at(playerId)->position - npc.position; - const float distanceSquared = - delta.x() * delta.x() + delta.z() * delta.z(); - if (distanceSquared <= nearestDistanceSquared) { - if (selectedTarget.empty() || - distanceSquared < nearestDistanceSquared || - (distanceSquared == nearestDistanceSquared && - playerId < selectedTarget)) { - selectedTarget = playerId; - nearestDistanceSquared = distanceSquared; - } - } - } - } + const std::string selectedTarget = + selectNpcTarget(npc, players, true); if (selectedTarget != previousTarget) { npc.stopInPlace(); @@ -474,7 +518,7 @@ LocationSimulationEvents LocationGameState::update( source.events.attackDirection}); } - auto player = players.find("player"); + auto player = players.find("player1"); if (!interactiveObjectsLocked && !location->targetInteractiveObjectId.empty() && player != players.end() && player->second && player->second->enabled) { @@ -502,7 +546,7 @@ LocationSimulationEvents LocationGameState::update( (player->second->position - npc->position).norm(); if (distance <= NPC_TALK_DISTANCE) { player->second->stopInPlace(); - npc->faceTargetId = "player"; + npc->faceTargetId = "player1"; result.npcInteractionId = location->targetInteractNpcId; location->targetInteractNpcId.clear(); } diff --git a/src/LocationGameState.h b/src/LocationGameState.h index bd35235..fde4079 100644 --- a/src/LocationGameState.h +++ b/src/LocationGameState.h @@ -86,6 +86,10 @@ struct LocationGameState { void load(const nlohmann::json& in); private: + std::string selectNpcTarget( + const CharacterState& npc, + const PlayerStateMap& players, + bool preserveValidLock) const; bool updateNpcCar(std::int64_t deltaMs); }; diff --git a/src/ScriptEngine.cpp b/src/ScriptEngine.cpp index 7451bbd..be99d2c 100644 --- a/src/ScriptEngine.cpp +++ b/src/ScriptEngine.cpp @@ -172,7 +172,7 @@ namespace FRG { << npcId << "'\n"; return; } - loc->faceCharacter(*npc, "player"); + loc->faceCharacter(*npc, "player1"); }); api.set_function("player_walk_to", diff --git a/src/game_server/InternalGameServer.h b/src/game_server/InternalGameServer.h index 19ae069..5ab1156 100644 --- a/src/game_server/InternalGameServer.h +++ b/src/game_server/InternalGameServer.h @@ -51,7 +51,7 @@ private: GameSnapshot buildSnapshot() const; GameState state_; - std::string localPlayerId_ = "player"; + std::string localPlayerId_ = "player1"; std::string resourceZipFile_; std::vector networkPlayerSlots_; std::int64_t battleZoneTestBotElapsedMs_ = 0;