Improved pathfinding logic
This commit is contained in:
parent
2659951d8e
commit
3a73f3fbde
260
PATHFINDING.md
Normal file
260
PATHFINDING.md
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
# Pathfinding System
|
||||||
|
|
||||||
|
This document describes the grid-based pathfinding used for the player and all NPCs, including the collision avoidance and movement quality improvements.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. [Grid Representation](#1-grid-representation)
|
||||||
|
2. [Building the Walkable Grid](#2-building-the-walkable-grid)
|
||||||
|
3. [A\* Path Search](#3-a-path-search)
|
||||||
|
4. [Path Smoothing](#4-path-smoothing)
|
||||||
|
5. [Approaching Unreachable Destinations](#5-approaching-unreachable-destinations)
|
||||||
|
6. [Dynamic Obstacles](#6-dynamic-obstacles)
|
||||||
|
7. [Path Following](#7-path-following)
|
||||||
|
8. [Character Collision Resolution](#8-character-collision-resolution)
|
||||||
|
9. [Dynamic Replanning](#9-dynamic-replanning)
|
||||||
|
10. [Key Constants Reference](#10-key-constants-reference)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Grid Representation
|
||||||
|
|
||||||
|
The world is divided into a uniform 2D grid in the XZ plane (Y is ignored during pathfinding; all characters walk on a flat floor at `floorY`).
|
||||||
|
|
||||||
|
Each cell is either **walkable** (`1`) or **blocked** (`0`). The grid is stored as a flat `std::vector<unsigned char>` indexed by `z * gridWidth + x`.
|
||||||
|
|
||||||
|
**Parameters** (all configurable in the JSON config file):
|
||||||
|
|
||||||
|
| Parameter | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `cellSize` | 0.4 m | Width and depth of one cell |
|
||||||
|
| `agentRadius` | 0.45 m | Half-width of a character — used to erode free space |
|
||||||
|
| `objectPadding` | 0.25 m | Extra clearance added around obstacle polygons |
|
||||||
|
| `boundaryPadding` | 0.0 m | Inward erosion from the edges of navigation areas |
|
||||||
|
| `floorY` | 0.0 | Y coordinate placed on every path waypoint |
|
||||||
|
|
||||||
|
**Grid bounds** are computed from the union of all navigation area polygons plus a padding margin of `cellSize * 2 + agentRadius + objectPadding` on every side.
|
||||||
|
|
||||||
|
**Cell coordinate conversion:**
|
||||||
|
|
||||||
|
```
|
||||||
|
cell.x = floor((worldX - minX) / cellSize)
|
||||||
|
cell.z = floor((worldZ - minZ) / cellSize)
|
||||||
|
|
||||||
|
cellCenter.x = minX + (cell.x + 0.5) * cellSize
|
||||||
|
cellCenter.z = minZ + (cell.z + 0.5) * cellSize
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Building the Walkable Grid
|
||||||
|
|
||||||
|
The grid can be loaded in two ways.
|
||||||
|
|
||||||
|
### 2a. Pre-computed grid (`.txt` file)
|
||||||
|
|
||||||
|
A plain-text file with a small header followed by rows of `1`/`0` characters:
|
||||||
|
|
||||||
|
```
|
||||||
|
cellSize 0.4
|
||||||
|
agentRadius 0.45
|
||||||
|
floorY 0.0
|
||||||
|
...
|
||||||
|
minX -5.0
|
||||||
|
minZ -5.0
|
||||||
|
gridWidth 50
|
||||||
|
gridDepth 50
|
||||||
|
11111111...
|
||||||
|
10000001...
|
||||||
|
```
|
||||||
|
|
||||||
|
This format is generated by `PathFinder::saveGrid()` after building from polygons and can be loaded much faster than recomputing from geometry.
|
||||||
|
|
||||||
|
### 2b. Polygon-based config (`.json` file)
|
||||||
|
|
||||||
|
The JSON file lists **navigation areas** (convex or concave walkable regions) and **obstacle polygons** (impassable zones within those regions):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cellSize": 0.4,
|
||||||
|
"areas": [
|
||||||
|
{ "name": "main_room", "available": true, "polygon": [[x,z], ...] }
|
||||||
|
],
|
||||||
|
"obstacles": [
|
||||||
|
{ "name": "table", "polygon": [[x,z], ...] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build steps:**
|
||||||
|
|
||||||
|
1. **Mark available areas walkable** — every cell whose center lies inside any `available` navigation area polygon gets `walkable = 1`. If `boundaryPadding > 0`, cells too close to the outer edge of the area are left blocked.
|
||||||
|
2. **Mark obstacle polygons blocked** — cells whose center lies inside an obstacle polygon, or within `agentRadius + objectPadding` of its edges, are set to `0`.
|
||||||
|
|
||||||
|
Navigation areas can be toggled at runtime via `PathFinder::setAreaAvailable()`, which rebuilds the entire grid. This is used to open or close doors, gated areas, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. A\* Path Search
|
||||||
|
|
||||||
|
`PathFinder::findPath(start, end)` runs a standard A\* on the walkable grid.
|
||||||
|
|
||||||
|
**Neighbor connectivity:** 8-directional (cardinal + diagonal). Diagonal moves are blocked if either of the two adjacent cardinal cells is unwalkable (no corner-cutting).
|
||||||
|
|
||||||
|
**Step costs:** `1.0` for cardinal, `√2 ≈ 1.414` for diagonal.
|
||||||
|
|
||||||
|
**Heuristic:** Euclidean distance in cell units to the end cell.
|
||||||
|
|
||||||
|
**Start/end snapping:** If the exact cell for `start` or `end` is not walkable, `findNearestWalkableCell` expands a square ring outward (up to radius 8 m) to find the nearest walkable cell. This makes clicking slightly outside the nav mesh still produce a valid path.
|
||||||
|
|
||||||
|
**Path reconstruction:** After A\* completes, the cell chain is walked via `cameFrom[]` from `end` back to `start`, reversed, then smoothed (see §4).
|
||||||
|
|
||||||
|
**First-waypoint trimming:** If the first waypoint is within `cellSize × 0.75` of `start`, it is dropped (the character is already close enough).
|
||||||
|
|
||||||
|
**Last-waypoint precision:** If the requested `end` maps to the same cell as the snapped end cell, the last waypoint is replaced with the exact `end` world position rather than the cell centre.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Path Smoothing
|
||||||
|
|
||||||
|
Raw A\* paths follow the grid diagonals and produce staircase-shaped routes. A **string-pulling** (line-of-sight) pass compresses them:
|
||||||
|
|
||||||
|
```
|
||||||
|
anchor = path[0]
|
||||||
|
result = [anchor]
|
||||||
|
while anchor is not the last cell:
|
||||||
|
find the furthest cell 'next' from anchor with unobstructed line of sight
|
||||||
|
result.append(next)
|
||||||
|
anchor = next
|
||||||
|
```
|
||||||
|
|
||||||
|
Line-of-sight is checked by stepping along the segment in increments of `cellSize / 2` and verifying that each sampled cell is walkable. The result is a minimal set of waypoints connected by straight, obstacle-free segments.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Approaching Unreachable Destinations
|
||||||
|
|
||||||
|
When a player clicks on a point in a disconnected region (e.g., across a thin wall), the original `findPath` returns an empty path and the character does not move. This is surprising — a click on a solid wall sensibly moves the character to the nearest reachable point, but a click into an inaccessible room does nothing.
|
||||||
|
|
||||||
|
**`findPathToNearest`** fixes this with a three-step cascade:
|
||||||
|
|
||||||
|
1. Try `findPath` with dynamic obstacles (stationary characters are avoided).
|
||||||
|
2. If empty, retry `findPath` without dynamic obstacles (an NPC blocking a doorway is ignored).
|
||||||
|
3. If still empty (destination genuinely unreachable), run **nearest-reachable A\***.
|
||||||
|
|
||||||
|
**Nearest-reachable A\***, implemented in `findNearestReachableImpl`:
|
||||||
|
|
||||||
|
- Runs the identical A\* loop against the static walkable grid.
|
||||||
|
- While processing cells, tracks `bestIndex` — the already-visited cell with the smallest Euclidean distance (in cell units) to the end cell.
|
||||||
|
- If A\* exhausts all reachable space without finding `end`, it reconstructs and returns a path to `bestIndex`.
|
||||||
|
- If `bestIndex` is still the start cell (character is completely isolated), an empty path is returned and the character stays put.
|
||||||
|
|
||||||
|
The net effect: clicking anywhere in the world always moves the character as close as possible to the target, matching the behaviour of clicking on a solid wall.
|
||||||
|
|
||||||
|
`findPathToNearest` replaces the direct `findPath` call in `Location::setupNavigation`'s path planner lambda, so it applies equally to the player and all NPCs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Dynamic Obstacles
|
||||||
|
|
||||||
|
When a path is planned, other characters can temporarily mark cells as blocked to make the character walk around them rather than through them.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
|
||||||
|
In `Location::setupNavigation`, every character is given a `PathPlanner` closure. Before calling `findPath`, the closure builds a list of `PathFinder::DynamicObstacle` entries (position + radius) representing nearby characters. `findPath` copies the static walkable grid, stamps zeros in circles around each obstacle, then runs A\* on the modified copy. The static grid is never mutated.
|
||||||
|
|
||||||
|
**Which characters become obstacles:**
|
||||||
|
|
||||||
|
A character is added as a dynamic obstacle only when **all** of these are true:
|
||||||
|
|
||||||
|
- It is not the character currently planning the path (`self`).
|
||||||
|
- It is alive and enabled.
|
||||||
|
- **It is not moving** — a moving character is transparent to pathfinding, so it does not block narrow corridors that it is actively passing through.
|
||||||
|
- Its position lies within `kDynamicObstacleInfluenceDist = 6 m` of the direct line segment from `start` to `end` (distant characters do not affect the search).
|
||||||
|
|
||||||
|
**Obstacle radius:** `character.collisionRadius × 0.6`. Using 60 % of the physical collision radius makes path planning less conservative; physical separation at full radius is still enforced by collision resolution (§8).
|
||||||
|
|
||||||
|
**Fallback when dynamic obstacles block the only path:**
|
||||||
|
|
||||||
|
If step 1 of `findPathToNearest` (with dynamic obstacles) returns empty, step 2 retries without any dynamic obstacles. This handles the common case of an NPC standing in a doorway: the player paths through the NPC's position, and the nudge logic (§8) pushes the NPC aside as the player passes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Path Following
|
||||||
|
|
||||||
|
`Character::setTarget(destination, onArrived)` sets a new walk target. It calls the path planner to generate a waypoint list. The result is stored in `pathWaypoints`; the final destination is also stored in `walkTarget` and `requestedWalkTarget`.
|
||||||
|
|
||||||
|
Each frame in `Character::update`:
|
||||||
|
|
||||||
|
1. **Active target** — if `pathWaypoints` is non-empty, the character moves toward `pathWaypoints[currentWaypointIndex]`; otherwise it moves toward `walkTarget`.
|
||||||
|
2. **Movement** — the character advances along the XZ direction at `walkSpeed` m/s and rotates smoothly toward the movement direction at `rotationSpeed` rad/s.
|
||||||
|
3. **Waypoint advance** — when the character is within `WALK_THRESHOLD = 0.05 m` of the current waypoint, it advances to the next one. When the last waypoint is reached, `pathWaypoints` is cleared and the optional `onArrived` callback is fired.
|
||||||
|
4. **State machine** — the animation state switches between `STAND` and `WALK` based on whether the character is moving.
|
||||||
|
|
||||||
|
`Character::isMoving()` returns `true` if `pathWaypoints` is non-empty or the distance to `walkTarget` exceeds `WALK_THRESHOLD`. This is used by dynamic obstacle filtering and collision nudging.
|
||||||
|
|
||||||
|
**Stopping in place:** `Character::stopInPlace()` sets `walkTarget` and `requestedWalkTarget` to the current position and clears `pathWaypoints`. It is called when an external force (collision resolution) displaces a stationary player so that the player does not walk back to their previous target position.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Character Collision Resolution
|
||||||
|
|
||||||
|
Pathfinding alone does not prevent two characters from occupying the same space — it only steers paths around stationary characters. Physical separation is handled separately each frame by `Location::resolveCharacterCollisions`.
|
||||||
|
|
||||||
|
**Algorithm** (3 iterations per frame):
|
||||||
|
|
||||||
|
For every pair `(A, B)` of living, enabled characters:
|
||||||
|
|
||||||
|
1. Compute the overlap: `penetration = (collisionRadius_A + collisionRadius_B) - distance(A, B)`.
|
||||||
|
2. If `penetration > 0`, compute a push direction (A-to-B normal) and a push magnitude of `penetration / 2` per character.
|
||||||
|
3. Compute candidate new positions `newA` and `newB`.
|
||||||
|
4. Validate against the navigation grid (`PathFinder::isWalkable`). If a pushed position is unwalkable, only the other character is moved.
|
||||||
|
5. **Player stays put:** if the player was not moving (`!isMoving()`) before the push, `stopInPlace()` is called after the push so the player does not walk back to the old target.
|
||||||
|
6. **NPC yielding:** if one character was moving and the other was standing, `nudgeCharacterAside` is called on the standing character.
|
||||||
|
|
||||||
|
**`nudgeCharacterAside(standing, awayFrom)`:**
|
||||||
|
|
||||||
|
Gives the standing NPC a short walk target so it steps out of the way:
|
||||||
|
|
||||||
|
1. Compute the direction from `awayFrom` to the NPC's current position.
|
||||||
|
2. Try four candidate targets at distance `1.2 m` in directions: straight away, +90°, −90°, 180°.
|
||||||
|
3. Use the first candidate that is walkable (per `PathFinder::isWalkable`).
|
||||||
|
4. Call `standing->setTarget(candidate)` — the NPC takes a small step aside, then stands at the new spot.
|
||||||
|
5. The player is never nudged; combat NPCs can be nudged, but their attack AI immediately overrides the yield target on the next tick.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Dynamic Replanning
|
||||||
|
|
||||||
|
When characters move they can displace each other or enter each other's planned paths. `Location::updateDynamicReplans` handles this:
|
||||||
|
|
||||||
|
**Every frame:**
|
||||||
|
|
||||||
|
1. Measure how much each character moved since the last frame. Characters that moved more than `kMovedEps = 0.05 m` are collected as **movers**.
|
||||||
|
2. For each mover, find other characters that are currently walking. If the mover's position is within `kReplanTriggerDist = 1.8 m` of the segment `[walker.position → walker.nextWaypoint]`, trigger a replan for the walker via `forceReplan()`.
|
||||||
|
3. A per-character cooldown of `kReplanCooldownMs = 500 ms` prevents the same character from replanning more often than twice per second.
|
||||||
|
|
||||||
|
**`Character::forceReplan()`** re-runs the path planner from the character's current position to its stored `requestedWalkTarget`, updating `pathWaypoints` in place. If the replanned path is empty, the character stops at its current position.
|
||||||
|
|
||||||
|
The relatively generous trigger distance (1.8 m vs the old 1.1 m) and cooldown (500 ms vs 300 ms) prevent micro-jitter: small position corrections from collision resolution no longer spam replanning events.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Key Constants Reference
|
||||||
|
|
||||||
|
| Constant | Location | Value | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `cellSize` | `PathFinder` config | 0.4 m | Grid cell size |
|
||||||
|
| `agentRadius` | `PathFinder` config | 0.45 m | Character half-width for grid erosion |
|
||||||
|
| `objectPadding` | `PathFinder` config | 0.25 m | Extra clearance around obstacles |
|
||||||
|
| `WALK_THRESHOLD` | `Character.h` | 0.05 m | Distance below which a waypoint is considered reached |
|
||||||
|
| `TARGET_REPLAN_THRESHOLD` | `Character.h` | 0.25 m | Deduplication threshold in `setTarget` |
|
||||||
|
| `kDynamicObstacleInfluenceDist` | `Location.cpp` | 6.0 m | Max distance from path for a character to become an obstacle |
|
||||||
|
| `kDynamicObstacleRadiusFraction` | `Location.cpp` | 0.6× | Fraction of collision radius used for dynamic obstacle footprint |
|
||||||
|
| `kNudgeDist` | `Location.cpp` | 1.2 m | Distance an NPC steps aside when yielding |
|
||||||
|
| `kReplanTriggerDist` | `Location.cpp` | 1.8 m | Mover must be this close to a walker's path to trigger replan |
|
||||||
|
| `kReplanCooldownMs` | `Location.cpp` | 500 ms | Minimum interval between replans for any one character |
|
||||||
|
| `NPC_TALK_DISTANCE` | `Location.cpp` | 1.35 m | Distance at which walking-to-NPC interaction fires |
|
||||||
|
| `kIterations` (collision) | `Location.cpp` | 3 | Push-apart iterations per frame |
|
||||||
@ -1,186 +0,0 @@
|
|||||||
{
|
|
||||||
"objects": [
|
|
||||||
{
|
|
||||||
"name": "Plane",
|
|
||||||
"texturePath": "resources/w/exterior/Segmented_Plane002.png",
|
|
||||||
"meshPath": "resources/w/exterior/Segmented_Plane002.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "door",
|
|
||||||
"texturePath": "resources/w/exterior/door002.png",
|
|
||||||
"meshPath": "resources/w/exterior/ext_door001.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "inai",
|
|
||||||
"texturePath": "resources/w/exterior/Building_work014.png",
|
|
||||||
"meshPath": "resources/w/exterior/int_building002.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "stairs",
|
|
||||||
"texturePath": "resources/w/exterior/Staircase001.png",
|
|
||||||
"meshPath": "resources/w/exterior/int_stairs001.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree001",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 10.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 12.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree002",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 19.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree003",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 8.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree004",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree005",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": -8.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree006",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 8.49915,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": -2.59884,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree007",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 14.5936,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 5.3401,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree008",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 23.9295,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 9.00583,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree009",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 29.8128,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": -1.45278,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree010",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 33.1771,
|
|
||||||
"positionY": -5.0,
|
|
||||||
"positionZ": 14.609,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
{
|
|
||||||
"objects": [
|
|
||||||
{
|
|
||||||
"name": "Plane",
|
|
||||||
"texturePath": "resources/w/exterior/Segmented_Plane002.png",
|
|
||||||
"textureDarkandsPath": "resources/w/exterior/darklands_Segmented_Plane002.png",
|
|
||||||
"meshPath": "resources/w/exterior/Segmented_Plane002.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "door",
|
|
||||||
"texturePath": "resources/w/exterior/door002.png",
|
|
||||||
"textureDarkandsPath": "resources/w/exterior/darklands_door002.png",
|
|
||||||
"meshPath": "resources/w/exterior/ext_door001.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "inai",
|
|
||||||
"texturePath": "resources/w/exterior/Ext_Building004.png",
|
|
||||||
"textureDarkandsPath": "resources/w/exterior/darklands_Ext_Building004.png",
|
|
||||||
"meshPath": "resources/w/exterior/ext_building001.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 0.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree001",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 10.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 12.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree002",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 19.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree003",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 8.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree004",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 0.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree005",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": -12.0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -8.0,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree006",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 8.49915,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -2.59884,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree007",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 14.5936,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 5.3401,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree008",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 23.9295,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 9.00583,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree009",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": 0.0,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 29.8128,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -1.45278,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tree010",
|
|
||||||
"texturePath": "resources/w/exterior/tree001.png",
|
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
|
||||||
"rotationX": 0.0,
|
|
||||||
"rotationY": -1.5707963267948966,
|
|
||||||
"rotationZ": 0.0,
|
|
||||||
"positionX": 33.1771,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 14.609,
|
|
||||||
"scale": 1.0,
|
|
||||||
"interactive": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -47,7 +47,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 10.0,
|
"positionX": 10.0,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12,
|
"positionX": -12,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -86,7 +86,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12.0,
|
"positionX": -12.0,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12.0,
|
"positionX": -12.0,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -125,7 +125,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 14.5936,
|
"positionX": 14.5936,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -138,7 +138,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 23.9295,
|
"positionX": 23.9295,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
@ -164,7 +164,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 33.1771,
|
"positionX": 33.1771,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
|
|||||||
@ -105,7 +105,7 @@
|
|||||||
"texturePath": "resources/w/interior/doors_tex001.png",
|
"texturePath": "resources/w/interior/doors_tex001.png",
|
||||||
"meshPath": "resources/w/interior/outputRoom_N_0_Leaf001.txt",
|
"meshPath": "resources/w/interior/outputRoom_N_0_Leaf001.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5708,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 1.5,
|
"positionX": 1.5,
|
||||||
"positionY": 0.975,
|
"positionY": 0.975,
|
||||||
@ -117,7 +117,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 10.0,
|
"positionX": 10.0,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -129,7 +129,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12,
|
"positionX": -12,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -153,7 +153,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12.0,
|
"positionX": -12.0,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -165,7 +165,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": -12.0,
|
"positionX": -12.0,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -189,7 +189,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 14.5936,
|
"positionX": 14.5936,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -201,7 +201,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 1.5707963267948966,
|
"rotationY": 90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 23.9295,
|
"positionX": 23.9295,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
@ -225,7 +225,7 @@
|
|||||||
"texturePath": "resources/w/exterior/tree001.png",
|
"texturePath": "resources/w/exterior/tree001.png",
|
||||||
"meshPath": "resources/w/exterior/tree003.txt",
|
"meshPath": "resources/w/exterior/tree003.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": -1.5707963267948966,
|
"rotationY": -90,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
"positionX": 33.1771,
|
"positionX": 33.1771,
|
||||||
"positionY": -5.0,
|
"positionY": -5.0,
|
||||||
|
|||||||
@ -30,8 +30,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Computer001",
|
"name": "Computer001",
|
||||||
"texturePath": "resources/w/interior/computer_texture001.png",
|
"texturePath": "resources/w/interior/computer_texture002.png",
|
||||||
"meshPath": "resources/w/interior/computer001_003.txt",
|
"meshPath": "resources/w/interior/computer001_004.txt",
|
||||||
"rotationX": 0.0,
|
"rotationX": 0.0,
|
||||||
"rotationY": 0.0,
|
"rotationY": 0.0,
|
||||||
"rotationZ": 0.0,
|
"rotationZ": 0.0,
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
{
|
|
||||||
"npcs": [
|
|
||||||
{
|
|
||||||
"id": "npc_04_ghost",
|
|
||||||
"name": "Беспокойный Призрак",
|
|
||||||
"texturePath": "resources/w/ghost_skin001.png",
|
|
||||||
"animationIdlePath": "resources/w/default_float001.anim",
|
|
||||||
"animationWalkPath": "resources/w/default_float001.anim",
|
|
||||||
"positionX": -0.28594,
|
|
||||||
"positionY": 0,
|
|
||||||
"positionZ": 13.9641,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.01,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 1.0,
|
|
||||||
"gift": {
|
|
||||||
"id": "ghost_essence",
|
|
||||||
"name": "Ghost's Essence",
|
|
||||||
"description": "A mysterious essence from the Ghost realm",
|
|
||||||
"icon": "resources/w/red.png"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ghost_01x",
|
|
||||||
"name": "Опасный Призрак",
|
|
||||||
"texturePath": "resources/w/ghost_skin002.png",
|
|
||||||
"animationIdlePath": "resources/w/default_float001.anim",
|
|
||||||
"animationWalkPath": "resources/w/default_float001.anim",
|
|
||||||
"animationActionIdlePath": "resources/w/float_attack003_cut.anim",
|
|
||||||
"animationActionAttackPath": "resources/w/float_attack003.anim",
|
|
||||||
"animationStandToActionPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToStandPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToDeathPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationDeathIdlePath": "resources/w/default_float001_cut.anim",
|
|
||||||
"positionX": 4.09561,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 6.28458,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.01,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"hp": 35,
|
|
||||||
"canAttack": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ghost_02x",
|
|
||||||
"name": "Злой призрак",
|
|
||||||
"texturePath": "resources/w/ghost_skin002.png",
|
|
||||||
"animationIdlePath": "resources/w/default_float001.anim",
|
|
||||||
"animationWalkPath": "resources/w/default_float001.anim",
|
|
||||||
"animationActionIdlePath": "resources/w/float_attack003_cut.anim",
|
|
||||||
"animationActionAttackPath": "resources/w/float_attack003.anim",
|
|
||||||
"animationStandToActionPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToStandPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToDeathPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationDeathIdlePath": "resources/w/default_float001_cut.anim",
|
|
||||||
"positionX": -4.95651,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 5.81422,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.01,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"hp": 25,
|
|
||||||
"canAttack": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ghost_02x",
|
|
||||||
"name": "Злой дух",
|
|
||||||
"texturePath": "resources/w/ghost_skin002.png",
|
|
||||||
"animationIdlePath": "resources/w/default_float001.anim",
|
|
||||||
"animationWalkPath": "resources/w/default_float001.anim",
|
|
||||||
"animationActionIdlePath": "resources/w/float_attack003_cut.anim",
|
|
||||||
"animationActionAttackPath": "resources/w/float_attack003.anim",
|
|
||||||
"animationStandToActionPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToStandPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationActionToDeathPath": "resources/w/default_float001_cut.anim",
|
|
||||||
"animationDeathIdlePath": "resources/w/default_float001_cut.anim",
|
|
||||||
"positionX": 0,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 10,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.01,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"hp": 15,
|
|
||||||
"canAttack": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,125 +0,0 @@
|
|||||||
{
|
|
||||||
"npcs": [
|
|
||||||
{
|
|
||||||
"id": "npc_01_default",
|
|
||||||
"name": "Студент",
|
|
||||||
"animationIdlePath": "resources/w/jam/man_stand_idle002.anim",
|
|
||||||
"animationWalkPath": "resources/w/jam/man_walk002.anim",
|
|
||||||
"meshTextures": {
|
|
||||||
"Body": "resources/w/jam/male_packed0_diffuse.png",
|
|
||||||
"Bottoms": "resources/w/jam/male_packed1_diffuse.png",
|
|
||||||
"Eyelashes": "resources/w/jam/male_packed0_diffuse.png",
|
|
||||||
"Eyes": "resources/w/jam/male_packed0_diffuse.png",
|
|
||||||
"Eyewear": "resources/w/jam/male_packed0_diffuse.png",
|
|
||||||
"Gloves": "resources/w/jam/male_packed1_diffuse.png",
|
|
||||||
"Hair": "resources/w/jam/male_packed0_diffuse.png",
|
|
||||||
"Shoes": "resources/w/jam/male_packed1_diffuse.png",
|
|
||||||
"Tops": "resources/w/jam/male_packed2_diffuse.png"
|
|
||||||
},
|
|
||||||
"positionX": 2.95,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 16.65,
|
|
||||||
"facingAngle" : 3.141592,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.0001,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 2.0,
|
|
||||||
"gift": {
|
|
||||||
"id": "guard_token",
|
|
||||||
"name": "Guard's Token",
|
|
||||||
"description": "A token from the Guard - sign of respect",
|
|
||||||
"icon": "resources/w/red.png"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "npc_02_woman",
|
|
||||||
"name": "Студентка",
|
|
||||||
"animationIdlePath": "resources/w/girl/girl_walk001.txt",
|
|
||||||
"animationWalkPath": "resources/w/girl/girl_walk001.txt",
|
|
||||||
"meshTextures": {
|
|
||||||
"polySurface1": "resources/w/girl/Chat_02_diff_1.png"
|
|
||||||
},
|
|
||||||
"positionX": 19.5,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 32.0,
|
|
||||||
"facingAngle" : 3.141592,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.01,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 2.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "npc_03_salesman",
|
|
||||||
"name": "Мухтар Байке",
|
|
||||||
"animationIdlePath": "resources/w/jam/salesperson_stand_idle003.anim",
|
|
||||||
"animationWalkPath": "resources/w/jam/salesperson_walk001.anim",
|
|
||||||
"meshTextures": {
|
|
||||||
"Body": "resources/w/jam/Salesperson_packed0_diffuse.png",
|
|
||||||
"Bottoms": "resources/w/jam/Salesperson_packed2_diffuse.png",
|
|
||||||
"Eyelashes": "resources/w/jam/Salesperson_packed0_diffuse.png",
|
|
||||||
"Eyes": "resources/w/jam/Salesperson_packed0_diffuse.png",
|
|
||||||
"Hats": "resources/w/jam/Salesperson_packed1_diffuse.png",
|
|
||||||
"Mustashes": "resources/w/jam/Salesperson_packed1_diffuse.png",
|
|
||||||
"Shoes": "resources/w/jam/Salesperson_packed1_diffuse.png",
|
|
||||||
"Tops": "resources/w/jam/Salesperson_packed1_diffuse.png"
|
|
||||||
},
|
|
||||||
"positionX": -1.94774,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": 16.2712,
|
|
||||||
"facingAngle" : 3.141592,
|
|
||||||
"walkSpeed": 1.5,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 0.001,
|
|
||||||
"modelCorrectionRotX": 0.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 2.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "npc_teacher",
|
|
||||||
"name": "Аида Токтоналы",
|
|
||||||
"animationIdlePath": "resources/w/new_anims/teacher_stand_idle001.txt",
|
|
||||||
"animationWalkPath": "resources/w/new_anims/woman_walk4_001.txt",
|
|
||||||
"meshTextures": {
|
|
||||||
"Teacher_lowpoly": "resources/w/new_anims/UniV_Grid_2K.001_Base_color.png"
|
|
||||||
},
|
|
||||||
"positionX": -3.76765,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -21.8495,
|
|
||||||
"facingAngle" : 0,
|
|
||||||
"walkSpeed": 1.3,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 1.0,
|
|
||||||
"modelCorrectionRotX": -90.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 2.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "npc_teacher02",
|
|
||||||
"name": "Асель Дженибековна",
|
|
||||||
"animationIdlePath": "resources/w/new_anims/teacher_stand_idle001.txt",
|
|
||||||
"animationWalkPath": "resources/w/new_anims/woman_walk4_001.txt",
|
|
||||||
"meshTextures": {
|
|
||||||
"Teacher_lowpoly": "resources/w/new_anims/UniV_Grid_2K.001_Base_color.png"
|
|
||||||
},
|
|
||||||
"positionX": 12.7499,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -20.8708,
|
|
||||||
"facingAngle" : 0,
|
|
||||||
"walkSpeed": 1.3,
|
|
||||||
"rotationSpeed": 8.0,
|
|
||||||
"modelScale": 1.0,
|
|
||||||
"modelCorrectionRotX": -90.0,
|
|
||||||
"modelCorrectionRotY": 180.0,
|
|
||||||
"modelCorrectionRotZ": 0.0,
|
|
||||||
"interactionRadius": 2.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -3,19 +3,19 @@
|
|||||||
{
|
{
|
||||||
"id": "npc_01_woman",
|
"id": "npc_01_woman",
|
||||||
"name": "Бермет",
|
"name": "Бермет",
|
||||||
"animationIdlePath": "resources/w/girl/girl_idle001.txt",
|
"animationIdlePath": "resources/w/girlfriend/girlfriend_idle003.txt",
|
||||||
"animationWalkPath": "resources/w/girl/girl_walk010.txt",
|
"animationWalkPath": "resources/w/girlfriend/girlfriend_walk003.txt",
|
||||||
"meshTextures": {
|
"meshTextures": {
|
||||||
"polySurface1": "resources/w/girl/Chat_02_diff_1r006.png"
|
"Girl_Low": "resources/w/girlfriend/Girl_Base_color.png"
|
||||||
},
|
},
|
||||||
"positionX": 1.03298,
|
"positionX": 1.03298,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
"positionZ": -4.61801,
|
"positionZ": -4.61801,
|
||||||
"facingAngle" : 3.141592,
|
"facingAngle" : 180,
|
||||||
"walkSpeed": 1.8,
|
"walkSpeed": 1.8,
|
||||||
"rotationSpeed": 8.0,
|
"rotationSpeed": 8.0,
|
||||||
"modelScale": 0.016,
|
"modelScale": 1.0,
|
||||||
"modelCorrectionRotX": 0.0,
|
"modelCorrectionRotX": -90.0,
|
||||||
"modelCorrectionRotY": 180.0,
|
"modelCorrectionRotY": 180.0,
|
||||||
"modelCorrectionRotZ": 0.0,
|
"modelCorrectionRotZ": 0.0,
|
||||||
"interactionRadius": 2.0
|
"interactionRadius": 2.0
|
||||||
@ -59,7 +59,7 @@
|
|||||||
"positionX": -6.33478,
|
"positionX": -6.33478,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
"positionZ": -15.0382,
|
"positionZ": -15.0382,
|
||||||
"facingAngle" : 3.141592,
|
"facingAngle" : 180,
|
||||||
"walkSpeed": 1.5,
|
"walkSpeed": 1.5,
|
||||||
"rotationSpeed": 8.0,
|
"rotationSpeed": 8.0,
|
||||||
"modelScale": 0.0001,
|
"modelScale": 0.0001,
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
"walkSpeed": 1.3,
|
"walkSpeed": 1.3,
|
||||||
"rotationSpeed": 8.0,
|
"rotationSpeed": 8.0,
|
||||||
"modelScale": 1.0,
|
"modelScale": 1.0,
|
||||||
"facingAngle" : 3.141592,
|
"facingAngle" : 180,
|
||||||
"modelCorrectionRotX": -90.0,
|
"modelCorrectionRotX": -90.0,
|
||||||
"modelCorrectionRotY": 180.0,
|
"modelCorrectionRotY": 180.0,
|
||||||
"modelCorrectionRotZ": 0.0,
|
"modelCorrectionRotZ": 0.0,
|
||||||
@ -23,19 +23,19 @@
|
|||||||
{
|
{
|
||||||
"id": "npc_02_woman",
|
"id": "npc_02_woman",
|
||||||
"name": "Айпери",
|
"name": "Айпери",
|
||||||
"animationIdlePath": "resources/w/girl/girl_idle001.txt",
|
"animationIdlePath": "resources/w/girlfriend/girlfriend_idle003.txt",
|
||||||
"animationWalkPath": "resources/w/girl/girl_walk002.txt",
|
"animationWalkPath": "resources/w/girlfriend/girlfriend_walk003.txt",
|
||||||
"meshTextures": {
|
"meshTextures": {
|
||||||
"polySurface1": "resources/w/girl/Chat_02_diff_1r006.png"
|
"Girl_Low": "resources/w/girlfriend/Girl_Base_color.png"
|
||||||
},
|
},
|
||||||
"positionX": 0.764049,
|
"positionX": 0.764049,
|
||||||
"positionY": 0.0,
|
"positionY": 0.0,
|
||||||
"positionZ": -8.53475,
|
"positionZ": -8.53475,
|
||||||
"facingAngle" : 3.141592,
|
"facingAngle" : 180,
|
||||||
"walkSpeed": 1.66,
|
"walkSpeed": 1.66,
|
||||||
"rotationSpeed": 8.0,
|
"rotationSpeed": 8.0,
|
||||||
"modelScale": 0.016,
|
"modelScale": 1.0,
|
||||||
"modelCorrectionRotX": 0.0,
|
"modelCorrectionRotX": -90.0,
|
||||||
"modelCorrectionRotY": 180.0,
|
"modelCorrectionRotY": 180.0,
|
||||||
"modelCorrectionRotZ": 0.0,
|
"modelCorrectionRotZ": 0.0,
|
||||||
"interactionRadius": 2.0,
|
"interactionRadius": 2.0,
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"teleports": [
|
|
||||||
{
|
|
||||||
"id": "tp_loc2_to_loc1",
|
|
||||||
"positionX": 8.2,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -9.9,
|
|
||||||
"radius": 1.5,
|
|
||||||
"active": true,
|
|
||||||
"destinationLocation": "uni_interior",
|
|
||||||
"destinationPositionX": 2.64621,
|
|
||||||
"destinationPositionY": 0.0,
|
|
||||||
"destinationPositionZ": -9.37259,
|
|
||||||
"destinationRotationY": -1.5708
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "tp_loc2_to_dorm",
|
|
||||||
"positionX": -21.7327,
|
|
||||||
"positionY": 0.0,
|
|
||||||
"positionZ": -34.1036,
|
|
||||||
"radius": 2.5,
|
|
||||||
"active": true,
|
|
||||||
"destinationLocation": "location_dorm",
|
|
||||||
"destinationPositionX": -8.32343,
|
|
||||||
"destinationPositionY": 0.0,
|
|
||||||
"destinationPositionZ": -0.152264,
|
|
||||||
"destinationRotationY": 1.5708
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"trigger_zones": [
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"positionZ": 6.17516,
|
"positionZ": 6.17516,
|
||||||
"radius": 2.0,
|
"radius": 2.0,
|
||||||
"hysteresis": 0.1,
|
"hysteresis": 0.1,
|
||||||
"enabled": false
|
"enabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -833,6 +833,132 @@
|
|||||||
"type": "End"
|
"type": "End"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "book_dialog003",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "Да, вот эта книга! Я возьму ее.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "book_dialog004",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "Я вернул книгу на место.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "book_dialog005",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "На этой полке лежат самые скучные книги в этом кабинете.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "book_dialog006",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "Я надеюсь, мне эта книга больше не пригодится.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "computer_dialog001",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "Это старый библиотечный компьютер, он даже не подключен к интернету.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "computer_dialog002",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "От этого компьютера сейчас не будет никакого толку.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "computer_dialog003",
|
||||||
|
"start": "line_1",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "line_1",
|
||||||
|
"type": "Line",
|
||||||
|
"speaker": "Бекзат",
|
||||||
|
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||||
|
"text": "Надеюсь мне больше не придется притрагиваться к этому компьютеру.",
|
||||||
|
"next": "end_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "end_1",
|
||||||
|
"type": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dialog_report_card001",
|
"id": "dialog_report_card001",
|
||||||
@ -936,7 +1062,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "test_cutscene_02",
|
"id": "test_cutscene_02",
|
||||||
"background": "resources/test_cutscene001.png",
|
"background": "resources/black.png",
|
||||||
|
"backgroundWidth" : 1280,
|
||||||
|
"backgroundHeight" : 720,
|
||||||
"durationMs": 5000,
|
"durationMs": 5000,
|
||||||
"fadeOutMs": 500,
|
"fadeOutMs": 500,
|
||||||
"fadeInMs": 500,
|
"fadeInMs": 500,
|
||||||
@ -980,7 +1108,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "darklands_exit001",
|
"id": "darklands_exit001",
|
||||||
"background": "resources/test_cutscene001.png",
|
"background": "resources/black.png",
|
||||||
|
"backgroundWidth" : 1280,
|
||||||
|
"backgroundHeight" : 720,
|
||||||
"durationMs": 5000,
|
"durationMs": 5000,
|
||||||
"fadeOutMs": 500,
|
"fadeOutMs": 500,
|
||||||
"fadeInMs": 500,
|
"fadeInMs": 500,
|
||||||
@ -1002,21 +1132,23 @@
|
|||||||
],
|
],
|
||||||
"lines": [
|
"lines": [
|
||||||
{
|
{
|
||||||
"speaker": "Бекзат",
|
|
||||||
"portrait": "resources/hero.png",
|
"portrait": "resources/hero.png",
|
||||||
"text": "Кажется, после того как я умер, я очнулся.",
|
"text": "Мгновенно как я упал без сил, что-то сверкнуло.",
|
||||||
"durationMs": 3000
|
"durationMs": 3000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"speaker": "Бекзат",
|
|
||||||
"portrait": "resources/hero.png",
|
"portrait": "resources/hero.png",
|
||||||
"text": "Жесть вообще, хочу спать.",
|
"text": "Я открыл глаза и понял, что я по-прежнему в универе.",
|
||||||
"durationMs": 3000
|
"durationMs": 3000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"speaker": "Бекзат",
|
|
||||||
"portrait": "resources/hero.png",
|
"portrait": "resources/hero.png",
|
||||||
"text": "Который час?",
|
"text": "Все тело болело, как будто я всю ночь таскал мешки с цементом.",
|
||||||
|
"durationMs": 3000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"portrait": "resources/hero.png",
|
||||||
|
"text": "А еще мне сильно хотелось спать...",
|
||||||
"durationMs": 2000,
|
"durationMs": 2000,
|
||||||
"background": "resources/test_cutscene001.png"
|
"background": "resources/test_cutscene001.png"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
resources/first_cutscene.png
(Stored with Git LFS)
BIN
resources/first_cutscene.png
(Stored with Git LFS)
Binary file not shown.
BIN
resources/portraits/elder_bor_neutral.png
(Stored with Git LFS)
BIN
resources/portraits/elder_bor_neutral.png
(Stored with Git LFS)
Binary file not shown.
BIN
resources/second_cutscene.png
(Stored with Git LFS)
BIN
resources/second_cutscene.png
(Stored with Git LFS)
Binary file not shown.
@ -84,21 +84,35 @@ game_api.npc_walk_to(0, -4.57412, 0, 6.78495, on_teacher_arrived2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function on_book_pickup()
|
function on_book_pickup()
|
||||||
|
print("on_book_pickup")
|
||||||
|
local day = game_api.getIntValue("day")
|
||||||
if (teacher_told_about_book) then
|
if (teacher_told_about_book) then
|
||||||
|
print("on_book_pickup step1")
|
||||||
if not player_hold_book then
|
if not player_hold_book then
|
||||||
|
if (night_time) or (day >=1) then
|
||||||
|
game_api.start_dialogue("book_dialog006")
|
||||||
|
else
|
||||||
game_api.pickup_item("book")
|
game_api.pickup_item("book")
|
||||||
game_api.deactivate_interactive_object("Book001")
|
game_api.deactivate_interactive_object("Book001")
|
||||||
player_hold_book = true
|
player_hold_book = true
|
||||||
|
game_api.start_dialogue("book_dialog003")
|
||||||
|
--game_api.set_trigger_zone_enabled(3, true)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
game_api.remove_item("book")
|
game_api.remove_item("book")
|
||||||
game_api.activate_interactive_object("Book001")
|
game_api.activate_interactive_object("Book001")
|
||||||
player_hold_book = false
|
player_hold_book = false
|
||||||
|
game_api.start_dialogue("book_dialog004")
|
||||||
|
--game_api.set_trigger_zone_enabled(3, false)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
print("on_book_pickup step2")
|
||||||
|
game_api.start_dialogue("book_dialog005")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function on_bookshelf_clicked()
|
function on_bookshelf_clicked()
|
||||||
if not player_hold_book then
|
--[[if not player_hold_book then
|
||||||
game_api.pickup_item("book")
|
game_api.pickup_item("book")
|
||||||
game_api.deactivate_interactive_object("Book001")
|
game_api.deactivate_interactive_object("Book001")
|
||||||
player_hold_book = true
|
player_hold_book = true
|
||||||
@ -108,7 +122,8 @@ function on_bookshelf_clicked()
|
|||||||
game_api.activate_interactive_object("Book001")
|
game_api.activate_interactive_object("Book001")
|
||||||
player_hold_book = false
|
player_hold_book = false
|
||||||
game_api.set_trigger_zone_enabled(3, false)
|
game_api.set_trigger_zone_enabled(3, false)
|
||||||
end
|
end]]
|
||||||
|
on_book_pickup()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -353,11 +368,16 @@ print("Teacher arrived2")
|
|||||||
end
|
end
|
||||||
|
|
||||||
function book_dialog_zone001_enter_callback()
|
function book_dialog_zone001_enter_callback()
|
||||||
|
print("book_dialog_zone001_enter_callback step 1")
|
||||||
if (game_api.is_darklands()) then
|
if (game_api.is_darklands()) then
|
||||||
|
print("book_dialog_zone001_enter_callback step 2")
|
||||||
game_api.start_dialogue("ghost_dialog002")
|
game_api.start_dialogue("ghost_dialog002")
|
||||||
game_api.set_trigger_zone_enabled(3, false)
|
game_api.set_trigger_zone_enabled(3, false)
|
||||||
else
|
else
|
||||||
if (night_time == false) then
|
|
||||||
|
print("book_dialog_zone001_enter_callback step 3")
|
||||||
|
if (player_hold_book) and (night_time == false) then
|
||||||
|
print("book_dialog_zone001_enter_callback step 4")
|
||||||
game_api.start_dialogue("book_dialog001")
|
game_api.start_dialogue("book_dialog001")
|
||||||
game_api.switch_navigation(5)
|
game_api.switch_navigation(5)
|
||||||
end
|
end
|
||||||
@ -365,7 +385,8 @@ function book_dialog_zone001_enter_callback()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function book_dialog_zone001_exit_callback()
|
function book_dialog_zone001_exit_callback()
|
||||||
if (night_time == false) then
|
print("book_dialog_zone001_exit_callback step 1")
|
||||||
|
if (player_hold_book) and (night_time == false) then
|
||||||
game_api.switch_navigation(3)
|
game_api.switch_navigation(3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -376,14 +397,27 @@ print("on_computer_clicked--")
|
|||||||
|
|
||||||
if (day == 1) then
|
if (day == 1) then
|
||||||
-- TODO: some dialog like I don't need it
|
-- TODO: some dialog like I don't need it
|
||||||
|
print("on_computer_clicked--1")
|
||||||
|
game_api.start_dialogue("computer_dialog003")
|
||||||
else
|
else
|
||||||
|
if teacher_told_about_book then
|
||||||
|
print("on_computer_clicked--2")
|
||||||
if (night_time == false) then
|
if (night_time == false) then
|
||||||
|
print("on_computer_clicked--3")
|
||||||
if (player_hold_book) then
|
if (player_hold_book) then
|
||||||
|
print("on_computer_clicked--4")
|
||||||
game_api.start_cutscene("test_cutscene_02")
|
game_api.start_cutscene("test_cutscene_02")
|
||||||
else
|
else
|
||||||
|
print("on_computer_clicked--5")
|
||||||
game_api.start_dialogue("book_dialog002")
|
game_api.start_dialogue("book_dialog002")
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
print("on_computer_clicked--6")
|
||||||
|
game_api.start_dialogue("computer_dialog002")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("on_computer_clicked--7")
|
||||||
|
game_api.start_dialogue("computer_dialog001")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -469,6 +503,8 @@ game_api.set_darklands_callbacks(
|
|||||||
first_time_darklands = false
|
first_time_darklands = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
game_api.set_trigger_zone_enabled(1, false)
|
||||||
|
|
||||||
game_api.set_npc_enabled(0, false)
|
game_api.set_npc_enabled(0, false)
|
||||||
game_api.set_npc_enabled(1, false)
|
game_api.set_npc_enabled(1, false)
|
||||||
|
|
||||||
|
|||||||
BIN
resources/w/girlfriend/Girl_Base_color.png
(Stored with Git LFS)
Normal file
BIN
resources/w/girlfriend/Girl_Base_color.png
(Stored with Git LFS)
Normal file
Binary file not shown.
122367
resources/w/girlfriend/girlfriend_idle002.txt
Normal file
122367
resources/w/girlfriend/girlfriend_idle002.txt
Normal file
File diff suppressed because it is too large
Load Diff
116120
resources/w/girlfriend/girlfriend_idle003.txt
Normal file
116120
resources/w/girlfriend/girlfriend_idle003.txt
Normal file
File diff suppressed because it is too large
Load Diff
114287
resources/w/girlfriend/girlfriend_walk001.txt
Normal file
114287
resources/w/girlfriend/girlfriend_walk001.txt
Normal file
File diff suppressed because it is too large
Load Diff
104689
resources/w/girlfriend/girlfriend_walk003.txt
Normal file
104689
resources/w/girlfriend/girlfriend_walk003.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,182 +0,0 @@
|
|||||||
===Vertices (Split by UV/Normal): 119
|
|
||||||
V 0: Pos(-0.321174, -0.380694, 0.03328) Norm(-0.577341, -0.577355, 0.577355) UV(0.622728, 0.985786)
|
|
||||||
V 1: Pos(-0.321174, -0.080976, -0.12644) Norm(-0.577341, 0.577355, -0.577355) UV(0.701365, 0.838077)
|
|
||||||
V 2: Pos(-0.321174, -0.380694, -0.12644) Norm(-0.57735, -0.577325, -0.577377) UV(0.701365, 0.985786)
|
|
||||||
V 3: Pos(-0.321174, -0.080976, 0.03328) Norm(-0.57735, 0.577325, 0.577377) UV(0.84347, 0.785241)
|
|
||||||
V 4: Pos(0.038545, -0.080976, -0.12644) Norm(0.57735, 0.577325, -0.577377) UV(0.764763, 0.962461)
|
|
||||||
V 5: Pos(-0.321174, -0.080976, -0.12644) Norm(-0.577341, 0.577355, -0.577355) UV(0.764763, 0.785276)
|
|
||||||
V 6: Pos(0.038545, -0.080976, 0.03328) Norm(0.577341, 0.577355, 0.577355) UV(-0.0, 0.985999)
|
|
||||||
V 7: Pos(0.038545, -0.380694, -0.12644) Norm(0.577341, -0.577355, -0.577355) UV(0.078326, 0.83829)
|
|
||||||
V 8: Pos(0.038545, -0.080976, -0.12644) Norm(0.57735, 0.577325, -0.577377) UV(0.078326, 0.985999)
|
|
||||||
V 9: Pos(0.038545, -0.380694, 0.03328) Norm(0.57735, -0.577325, 0.577377) UV(0.843469, 0.962426)
|
|
||||||
V 10: Pos(-0.321174, -0.380694, -0.12644) Norm(-0.57735, -0.577325, -0.577377) UV(0.922175, 0.785276)
|
|
||||||
V 11: Pos(0.038545, -0.380694, -0.12644) Norm(0.577341, -0.577355, -0.577355) UV(0.922175, 0.962461)
|
|
||||||
V 12: Pos(0.038545, -0.080976, -0.12644) Norm(0.57735, 0.577325, -0.577377) UV(0.717688, 0.0)
|
|
||||||
V 13: Pos(-0.321174, -0.380694, -0.12644) Norm(-0.57735, -0.577325, -0.577377) UV(0.865397, 0.17727)
|
|
||||||
V 14: Pos(-0.321174, -0.080976, -0.12644) Norm(-0.577341, 0.577355, -0.577355) UV(0.717688, 0.17727)
|
|
||||||
V 15: Pos(-0.321174, -0.080976, 0.03328) Norm(-0.57735, 0.577325, 0.577377) UV(0.764763, 0.60813)
|
|
||||||
V 16: Pos(0.038545, -0.380694, 0.03328) Norm(0.57735, -0.577325, 0.577377) UV(0.912472, 0.785241)
|
|
||||||
V 17: Pos(0.038545, -0.080976, 0.03328) Norm(0.577341, 0.577355, 0.577355) UV(0.764763, 0.785241)
|
|
||||||
V 18: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.865397, 0.0)
|
|
||||||
V 19: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.973174, 0.206141)
|
|
||||||
V 20: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.865397, 0.206141)
|
|
||||||
V 21: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.206323, 0.553153)
|
|
||||||
V 22: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.0, 0.83829)
|
|
||||||
V 23: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.0, 0.553246)
|
|
||||||
V 24: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.867943, 0.277359)
|
|
||||||
V 25: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.97572, 0.482684)
|
|
||||||
V 26: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.867943, 0.482684)
|
|
||||||
V 27: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.206322, 0.838197)
|
|
||||||
V 28: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.412645, 0.553246)
|
|
||||||
V 29: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.412645, 0.83829)
|
|
||||||
V 30: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.514952, 0.553153)
|
|
||||||
V 31: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.622728, 0.838334)
|
|
||||||
V 32: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.514952, 0.838334)
|
|
||||||
V 33: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.622728, 0.553153)
|
|
||||||
V 34: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.730505, 0.838077)
|
|
||||||
V 35: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.622728, 0.838077)
|
|
||||||
V 36: Pos(-0.04492, -0.422368, 0.425114) Norm(-0.964019, -0.126929, -0.233572) UV(0.551589, 0.17729)
|
|
||||||
V 37: Pos(0.154366, -0.062626, -0.106573) Norm(0.092451, 0.354611, -0.930432) UV(0.717688, 0.0)
|
|
||||||
V 38: Pos(0.154366, -0.422368, -0.106573) Norm(0.09503, -0.342725, -0.934617) UV(0.717688, 0.17729)
|
|
||||||
V 39: Pos(-0.04492, -0.062626, 0.425114) Norm(-0.95805, 0.148128, -0.245352) UV(0.049252, 0.277359)
|
|
||||||
V 40: Pos(0.16953, 0.037313, 0.020093) Norm(0.364582, 0.91558, -0.169683) UV(0.275794, -0.0)
|
|
||||||
V 41: Pos(0.154366, -0.062626, -0.106573) Norm(0.092451, 0.354611, -0.930432) UV(0.226542, 0.277359)
|
|
||||||
V 42: Pos(-0.049131, 0.037313, 0.535225) Norm(-0.186957, 0.70094, 0.68828) UV(0.27372, 0.553153)
|
|
||||||
V 43: Pos(0.16953, -0.522306, 0.020093) Norm(0.391468, -0.900748, -0.188163) UV(0.537026, 0.277359)
|
|
||||||
V 44: Pos(0.16953, 0.037313, 0.020093) Norm(0.364582, 0.91558, -0.169683) UV(0.537026, 0.553153)
|
|
||||||
V 45: Pos(-0.049131, -0.522306, 0.535225) Norm(-0.192057, -0.680692, 0.706946) UV(0.551589, -0.0)
|
|
||||||
V 46: Pos(0.154366, -0.422368, -0.106573) Norm(0.09503, -0.342725, -0.934617) UV(0.325047, 0.277359)
|
|
||||||
V 47: Pos(0.16953, -0.522306, 0.020093) Norm(0.391468, -0.900748, -0.188163) UV(0.275794, -0.0)
|
|
||||||
V 48: Pos(0.16953, 0.037313, 0.020093) Norm(0.364582, 0.91558, -0.169683) UV(-0.0, 0.553153)
|
|
||||||
V 49: Pos(0.154366, -0.422368, -0.106573) Norm(0.09503, -0.342725, -0.934617) UV(0.27372, 0.326611)
|
|
||||||
V 50: Pos(0.154366, -0.062626, -0.106573) Norm(0.092451, 0.354611, -0.930432) UV(0.27372, 0.503901)
|
|
||||||
V 51: Pos(-0.04492, -0.062626, 0.425114) Norm(-0.95805, 0.148128, -0.245352) UV(0.537025, 0.503901)
|
|
||||||
V 52: Pos(-0.049131, -0.522306, 0.535225) Norm(-0.192057, -0.680692, 0.706946) UV(0.764763, 0.277359)
|
|
||||||
V 53: Pos(-0.049131, 0.037313, 0.535225) Norm(-0.186957, 0.70094, 0.68828) UV(0.764763, 0.553154)
|
|
||||||
V 54: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.730505, 0.883925)
|
|
||||||
V 55: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.755124, 0.553154)
|
|
||||||
V 56: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.755124, 0.883925)
|
|
||||||
V 57: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.893159, 0.482684)
|
|
||||||
V 58: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(0.867943, 0.586724)
|
|
||||||
V 59: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.867943, 0.482698)
|
|
||||||
V 60: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.97572, 0.60813)
|
|
||||||
V 61: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(1.0, 0.277359)
|
|
||||||
V 62: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(1.0, 0.60813)
|
|
||||||
V 63: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(0.918374, 0.586724)
|
|
||||||
V 64: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.893159, 0.482684)
|
|
||||||
V 65: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.918374, 0.482698)
|
|
||||||
V 66: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(0.412645, 0.883924)
|
|
||||||
V 67: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.514952, 0.553153)
|
|
||||||
V 68: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.514952, 0.883924)
|
|
||||||
V 69: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.764763, 0.60813)
|
|
||||||
V 70: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.867943, 0.277359)
|
|
||||||
V 71: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.867943, 0.60813)
|
|
||||||
V 72: Pos(0.243142, 0.221328, -0.083115) Norm(-0.577358, -0.577347, 0.577347) UV(0.551589, 0.260175)
|
|
||||||
V 73: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.573298, 0.228587)
|
|
||||||
V 74: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.573298, 0.260175)
|
|
||||||
V 75: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.658221, 0.17729)
|
|
||||||
V 76: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.636492, 0.228573)
|
|
||||||
V 77: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.636492, 0.177299)
|
|
||||||
V 78: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.573298, 0.260175)
|
|
||||||
V 79: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.594921, 0.228588)
|
|
||||||
V 80: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.594921, 0.260175)
|
|
||||||
V 81: Pos(0.347237, 0.221328, -0.083115) Norm(0.577359, -0.577332, 0.577359) UV(0.614763, 0.228563)
|
|
||||||
V 82: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.636492, 0.177299)
|
|
||||||
V 83: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.636492, 0.228573)
|
|
||||||
V 84: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.551589, 0.17729)
|
|
||||||
V 85: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.583176, 0.228588)
|
|
||||||
V 86: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.551589, 0.228588)
|
|
||||||
V 87: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.583176, 0.17729)
|
|
||||||
V 88: Pos(0.347237, 0.221328, -0.083115) Norm(0.577359, -0.577332, 0.577359) UV(0.614763, 0.228541)
|
|
||||||
V 89: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.583176, 0.228541)
|
|
||||||
V 90: Pos(-0.321174, -0.080976, 0.03328) Norm(-0.57735, 0.577325, 0.577377) UV(0.622728, 0.838077)
|
|
||||||
V 91: Pos(0.038545, -0.080976, 0.03328) Norm(0.577341, 0.577355, 0.577355) UV(0.84347, 0.962426)
|
|
||||||
V 92: Pos(0.038545, -0.380694, 0.03328) Norm(0.57735, -0.577325, 0.577377) UV(-0.0, 0.83829)
|
|
||||||
V 93: Pos(-0.321174, -0.380694, 0.03328) Norm(-0.577341, -0.577355, 0.577355) UV(0.843469, 0.785241)
|
|
||||||
V 94: Pos(0.038545, -0.380694, -0.12644) Norm(0.577341, -0.577355, -0.577355) UV(0.865397, 0.0)
|
|
||||||
V 95: Pos(-0.321174, -0.380694, 0.03328) Norm(-0.577341, -0.577355, 0.577355) UV(0.912472, 0.60813)
|
|
||||||
V 96: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.973174, 0.0)
|
|
||||||
V 97: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.206323, 0.838198)
|
|
||||||
V 98: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.97572, 0.277359)
|
|
||||||
V 99: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.206322, 0.553153)
|
|
||||||
V 100: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.622728, 0.553153)
|
|
||||||
V 101: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.730505, 0.553153)
|
|
||||||
V 102: Pos(-0.04492, -0.062626, 0.425114) Norm(-0.95805, 0.148128, -0.245352) UV(0.551589, 0.0)
|
|
||||||
V 103: Pos(-0.049131, 0.037313, 0.535225) Norm(-0.186957, 0.70094, 0.68828) UV(-0.0, -0.0)
|
|
||||||
V 104: Pos(-0.049131, -0.522306, 0.535225) Norm(-0.192057, -0.680692, 0.706946) UV(0.27372, 0.277359)
|
|
||||||
V 105: Pos(-0.04492, -0.422368, 0.425114) Norm(-0.964019, -0.126929, -0.233572) UV(0.502336, 0.277359)
|
|
||||||
V 106: Pos(0.16953, -0.522306, 0.020093) Norm(0.391468, -0.900748, -0.188163) UV(-0.0, 0.277359)
|
|
||||||
V 107: Pos(-0.04492, -0.422368, 0.425114) Norm(-0.964019, -0.126929, -0.233572) UV(0.537025, 0.326611)
|
|
||||||
V 108: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.730505, 0.553154)
|
|
||||||
V 109: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.893159, 0.58671)
|
|
||||||
V 110: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.97572, 0.277359)
|
|
||||||
V 111: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.893159, 0.58671)
|
|
||||||
V 112: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(0.412645, 0.553153)
|
|
||||||
V 113: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.764763, 0.277359)
|
|
||||||
V 114: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.551589, 0.228587)
|
|
||||||
V 115: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.658221, 0.228563)
|
|
||||||
V 116: Pos(0.347237, 0.221328, -0.083115) Norm(0.577359, -0.577332, 0.577359) UV(0.573298, 0.228588)
|
|
||||||
V 117: Pos(0.243142, 0.221328, -0.083115) Norm(-0.577358, -0.577347, 0.577347) UV(0.614763, 0.17729)
|
|
||||||
V 118: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.583176, 0.17729)
|
|
||||||
|
|
||||||
===Triangles (Indices): 60
|
|
||||||
Tri: 0 1 2
|
|
||||||
Tri: 3 4 5
|
|
||||||
Tri: 6 7 8
|
|
||||||
Tri: 9 10 11
|
|
||||||
Tri: 12 13 14
|
|
||||||
Tri: 15 16 17
|
|
||||||
Tri: 18 19 20
|
|
||||||
Tri: 21 22 23
|
|
||||||
Tri: 24 25 26
|
|
||||||
Tri: 27 28 29
|
|
||||||
Tri: 30 31 32
|
|
||||||
Tri: 33 34 35
|
|
||||||
Tri: 36 37 38
|
|
||||||
Tri: 39 40 41
|
|
||||||
Tri: 42 43 44
|
|
||||||
Tri: 45 46 47
|
|
||||||
Tri: 48 49 50
|
|
||||||
Tri: 51 52 53
|
|
||||||
Tri: 54 55 56
|
|
||||||
Tri: 57 58 59
|
|
||||||
Tri: 60 61 62
|
|
||||||
Tri: 63 64 65
|
|
||||||
Tri: 66 67 68
|
|
||||||
Tri: 69 70 71
|
|
||||||
Tri: 72 73 74
|
|
||||||
Tri: 75 76 77
|
|
||||||
Tri: 78 79 80
|
|
||||||
Tri: 81 82 83
|
|
||||||
Tri: 84 85 86
|
|
||||||
Tri: 87 88 89
|
|
||||||
Tri: 0 90 1
|
|
||||||
Tri: 3 91 4
|
|
||||||
Tri: 6 92 7
|
|
||||||
Tri: 9 93 10
|
|
||||||
Tri: 12 94 13
|
|
||||||
Tri: 15 95 16
|
|
||||||
Tri: 18 96 19
|
|
||||||
Tri: 21 97 22
|
|
||||||
Tri: 24 98 25
|
|
||||||
Tri: 27 99 28
|
|
||||||
Tri: 30 100 31
|
|
||||||
Tri: 33 101 34
|
|
||||||
Tri: 36 102 37
|
|
||||||
Tri: 39 103 40
|
|
||||||
Tri: 42 104 43
|
|
||||||
Tri: 45 105 46
|
|
||||||
Tri: 48 106 49
|
|
||||||
Tri: 51 107 52
|
|
||||||
Tri: 54 108 55
|
|
||||||
Tri: 57 109 58
|
|
||||||
Tri: 60 110 61
|
|
||||||
Tri: 63 111 64
|
|
||||||
Tri: 66 112 67
|
|
||||||
Tri: 69 113 70
|
|
||||||
Tri: 72 114 73
|
|
||||||
Tri: 75 115 76
|
|
||||||
Tri: 78 116 79
|
|
||||||
Tri: 81 117 82
|
|
||||||
Tri: 84 118 85
|
|
||||||
Tri: 87 117 88
|
|
||||||
172
resources/w/interior/computer001_004.txt
Normal file
172
resources/w/interior/computer001_004.txt
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
===Vertices (Split by UV/Normal): 109
|
||||||
|
V 0: Pos(0.02036, -0.316218, 0.03328) Norm(-0.577372, -0.57734, 0.57734) UV(0.582523, 0.71522)
|
||||||
|
V 1: Pos(0.02036, -0.14665, -0.12644) Norm(-0.577372, 0.57734, -0.57734) UV(0.672618, 0.618748)
|
||||||
|
V 2: Pos(0.02036, -0.316218, -0.12644) Norm(-0.577341, -0.577361, -0.577348) UV(0.672618, 0.715234)
|
||||||
|
V 3: Pos(0.02036, -0.14665, 0.03328) Norm(-0.577341, 0.577354, 0.577356) UV(0.0, 0.850964)
|
||||||
|
V 4: Pos(0.132668, -0.14665, -0.12644) Norm(0.543117, 0.593412, -0.594042) UV(0.063904, 0.941846)
|
||||||
|
V 5: Pos(0.02036, -0.14665, -0.12644) Norm(-0.577372, 0.57734, -0.57734) UV(0.0, 0.941846)
|
||||||
|
V 6: Pos(0.14154, -0.14665, 0.03328) Norm(0.584307, 0.579838, 0.567779) UV(0.672958, 0.522251)
|
||||||
|
V 7: Pos(0.14154, -0.316218, -0.12644) Norm(0.583322, -0.568894, -0.579737) UV(0.582523, 0.618734)
|
||||||
|
V 8: Pos(0.132668, -0.14665, -0.12644) Norm(0.543117, 0.593412, -0.594042) UV(0.582929, 0.522217)
|
||||||
|
V 9: Pos(0.14154, -0.316218, 0.03328) Norm(0.577339, -0.577359, 0.577353) UV(0.068952, 0.850964)
|
||||||
|
V 10: Pos(0.02036, -0.316218, -0.12644) Norm(-0.577341, -0.577361, -0.577348) UV(0.137905, 0.941846)
|
||||||
|
V 11: Pos(0.14154, -0.316218, -0.12644) Norm(0.583322, -0.568894, -0.579737) UV(0.068952, 0.941846)
|
||||||
|
V 12: Pos(0.132668, -0.14665, -0.12644) Norm(0.543117, 0.593412, -0.594042) UV(0.646367, 0.811719)
|
||||||
|
V 13: Pos(0.02036, -0.316218, -0.12644) Norm(-0.577341, -0.577361, -0.577348) UV(0.582523, 0.908205)
|
||||||
|
V 14: Pos(0.02036, -0.14665, -0.12644) Norm(-0.577372, 0.57734, -0.57734) UV(0.582523, 0.811719)
|
||||||
|
V 15: Pos(0.02036, -0.14665, 0.03328) Norm(-0.577341, 0.577354, 0.577356) UV(0.582523, 0.811719)
|
||||||
|
V 16: Pos(0.14154, -0.316218, 0.03328) Norm(0.577339, -0.577359, 0.577353) UV(0.65141, 0.715234)
|
||||||
|
V 17: Pos(0.14154, -0.14665, 0.03328) Norm(0.584307, 0.579838, 0.567779) UV(0.65141, 0.811719)
|
||||||
|
V 18: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.680198, 0.763823)
|
||||||
|
V 19: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.804635, 0.999981)
|
||||||
|
V 20: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.680198, 1.0)
|
||||||
|
V 21: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.0, 0.850964)
|
||||||
|
V 22: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.238239, 0.521684)
|
||||||
|
V 23: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.238239, 0.850964)
|
||||||
|
V 24: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.804635, 0.658012)
|
||||||
|
V 25: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.929069, 0.895159)
|
||||||
|
V 26: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.804635, 0.895235)
|
||||||
|
V 27: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.344284, 0.851497)
|
||||||
|
V 28: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.582523, 0.522217)
|
||||||
|
V 29: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.582523, 0.851497)
|
||||||
|
V 30: Pos(-0.0362, 0.561483, -0.134268) Norm(0.577355, 0.577371, -0.577325) UV(0.929072, 0.657935)
|
||||||
|
V 31: Pos(-0.614892, 0.342792, -0.134268) Norm(-0.577355, -0.577371, -0.577325) UV(0.804635, 0.328968)
|
||||||
|
V 32: Pos(-0.614892, 0.561483, -0.134268) Norm(-0.57734, 0.577355, -0.577355) UV(0.929072, 0.328968)
|
||||||
|
V 33: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.804635, 0.0)
|
||||||
|
V 34: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.929072, 0.328968)
|
||||||
|
V 35: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.804635, 0.328968)
|
||||||
|
V 36: Pos(-0.04492, -0.422368, 0.425114) Norm(-0.970839, -0.041701, -0.236076) UV(0.062426, 0.358244)
|
||||||
|
V 37: Pos(0.154366, -0.062626, -0.04817) Norm(0.071923, 0.11404, -0.990869) UV(0.344284, 0.15346)
|
||||||
|
V 38: Pos(0.154366, -0.422368, -0.04817) Norm(0.073067, -0.106497, -0.991625) UV(0.344284, 0.358155)
|
||||||
|
V 39: Pos(-0.04492, -0.062626, 0.425114) Norm(-0.970251, 0.045613, -0.237765) UV(0.062426, 0.153549)
|
||||||
|
V 40: Pos(0.16953, 0.207044, 0.020093) Norm(0.24987, 0.873883, -0.417005) UV(0.306911, -0.0)
|
||||||
|
V 41: Pos(-0.049131, 0.207044, 0.535225) Norm(-0.195195, 0.782445, 0.591336) UV(0.344284, 0.522217)
|
||||||
|
V 42: Pos(0.16953, -0.709618, 0.020093) Norm(0.2492, -0.870253, -0.424923) UV(0.647624, 0.0)
|
||||||
|
V 43: Pos(0.16953, 0.207044, 0.020093) Norm(0.24987, 0.873883, -0.417005) UV(0.647624, 0.521575)
|
||||||
|
V 44: Pos(-0.049131, -0.709618, 0.535225) Norm(-0.196826, -0.783515, 0.589376) UV(0.0, 0.521684)
|
||||||
|
V 45: Pos(0.16953, -0.709618, 0.020093) Norm(0.2492, -0.870253, -0.424923) UV(0.306911, 0.521586)
|
||||||
|
V 46: Pos(0.154366, -0.422368, -0.04817) Norm(0.073067, -0.106497, -0.991625) UV(0.685505, 0.163524)
|
||||||
|
V 47: Pos(0.154366, -0.062626, -0.04817) Norm(0.071923, 0.11404, -0.990869) UV(0.685505, 0.368215)
|
||||||
|
V 48: Pos(-0.049131, 0.207044, 0.535225) Norm(-0.195195, 0.782445, 0.591336) UV(0.0, 9.8e-05)
|
||||||
|
V 49: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.266327, 0.903586)
|
||||||
|
V 50: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.294091, 0.521694)
|
||||||
|
V 51: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.294091, 0.903596)
|
||||||
|
V 52: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.323209, 0.521684)
|
||||||
|
V 53: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(0.294091, 0.641843)
|
||||||
|
V 54: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.294091, 0.521684)
|
||||||
|
V 55: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.238239, 0.903578)
|
||||||
|
V 56: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(0.266327, 0.521735)
|
||||||
|
V 57: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(0.266327, 0.903629)
|
||||||
|
V 58: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(0.323209, 0.762002)
|
||||||
|
V 59: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.294091, 0.641843)
|
||||||
|
V 60: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.323209, 0.641843)
|
||||||
|
V 61: Pos(0.468575, 0.103404, -0.135202) Norm(0.468342, 0.577346, -0.668826) UV(0.804635, 0.381902)
|
||||||
|
V 62: Pos(0.26061, -0.567769, -0.098532) Norm(-0.668841, -0.57736, -0.468302) UV(0.685505, 0.763804)
|
||||||
|
V 63: Pos(0.26061, 0.103404, -0.098532) Norm(-0.66884, 0.577347, -0.468319) UV(0.685505, 0.381902)
|
||||||
|
V 64: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.685505, 0.381902)
|
||||||
|
V 65: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.804635, 0.0)
|
||||||
|
V 66: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.804635, 0.381902)
|
||||||
|
V 67: Pos(0.243142, 0.221328, -0.083115) Norm(-0.577358, -0.577347, 0.577347) UV(0.137905, 0.887434)
|
||||||
|
V 68: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.162777, 0.850968)
|
||||||
|
V 69: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.162777, 0.887438)
|
||||||
|
V 70: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.65141, 0.774464)
|
||||||
|
V 71: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.6765, 0.715234)
|
||||||
|
V 72: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.6765, 0.774464)
|
||||||
|
V 73: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.65141, 0.870164)
|
||||||
|
V 74: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.676393, 0.83371)
|
||||||
|
V 75: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.676393, 0.870179)
|
||||||
|
V 76: Pos(0.347237, 0.221328, -0.083115) Norm(0.577359, -0.577332, 0.577359) UV(0.65141, 0.833694)
|
||||||
|
V 77: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.6765, 0.774464)
|
||||||
|
V 78: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.6765, 0.833694)
|
||||||
|
V 79: Pos(0.347237, 0.285422, -0.127209) Norm(0.577359, 0.577332, -0.577359) UV(0.330561, 0.821176)
|
||||||
|
V 80: Pos(0.243142, 0.221328, -0.127209) Norm(-0.577359, -0.577332, -0.577359) UV(0.294091, 0.762002)
|
||||||
|
V 81: Pos(0.243142, 0.285422, -0.127209) Norm(-0.577358, 0.577347, -0.577347) UV(0.330561, 0.762002)
|
||||||
|
V 82: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.294091, 0.821176)
|
||||||
|
V 83: Pos(0.347237, 0.221328, -0.083115) Norm(0.577359, -0.577332, 0.577359) UV(0.330561, 0.880351)
|
||||||
|
V 84: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.294091, 0.880351)
|
||||||
|
V 85: Pos(0.02036, -0.14665, 0.03328) Norm(-0.577341, 0.577354, 0.577356) UV(0.582523, 0.618734)
|
||||||
|
V 86: Pos(0.14154, -0.14665, 0.03328) Norm(0.584307, 0.579838, 0.567779) UV(0.068952, 0.850964)
|
||||||
|
V 87: Pos(0.14154, -0.316218, 0.03328) Norm(0.577339, -0.577359, 0.577353) UV(0.673017, 0.618734)
|
||||||
|
V 88: Pos(0.02036, -0.316218, 0.03328) Norm(-0.577372, -0.57734, 0.57734) UV(0.137905, 0.850964)
|
||||||
|
V 89: Pos(0.14154, -0.316218, -0.12644) Norm(0.583322, -0.568894, -0.579737) UV(0.65141, 0.908205)
|
||||||
|
V 90: Pos(0.02036, -0.316218, 0.03328) Norm(-0.577372, -0.57734, 0.57734) UV(0.582523, 0.715234)
|
||||||
|
V 91: Pos(-0.614892, 0.561483, 0.284424) Norm(-0.577355, 0.577371, 0.577325) UV(0.804635, 0.763804)
|
||||||
|
V 92: Pos(-0.0362, 0.561483, 0.284424) Norm(0.57734, 0.577355, 0.577355) UV(0.0, 0.521684)
|
||||||
|
V 93: Pos(-0.0362, 0.342792, 0.284424) Norm(0.577355, -0.577371, 0.577325) UV(0.929069, 0.657935)
|
||||||
|
V 94: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.344284, 0.522217)
|
||||||
|
V 95: Pos(-0.0362, 0.342792, -0.134268) Norm(0.57734, -0.577355, -0.577355) UV(0.804635, 0.657935)
|
||||||
|
V 96: Pos(-0.614892, 0.342792, 0.284424) Norm(-0.57734, -0.577355, 0.577355) UV(0.929072, 0.0)
|
||||||
|
V 97: Pos(-0.049131, -0.709618, 0.535225) Norm(-0.196826, -0.783515, 0.589376) UV(0.344284, 0.000642)
|
||||||
|
V 98: Pos(0.269496, 0.103404, -0.048135) Norm(-0.468342, 0.577346, 0.668826) UV(0.266327, 0.521684)
|
||||||
|
V 99: Pos(0.477461, 0.103404, -0.084805) Norm(0.66884, 0.577347, 0.468319) UV(0.323209, 0.641843)
|
||||||
|
V 100: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.238239, 0.521684)
|
||||||
|
V 101: Pos(0.477461, -0.567769, -0.084805) Norm(0.668841, -0.57736, 0.468302) UV(0.294091, 0.762002)
|
||||||
|
V 102: Pos(0.468575, -0.567769, -0.135202) Norm(0.468336, -0.577333, -0.668841) UV(0.804635, 0.763804)
|
||||||
|
V 103: Pos(0.269496, -0.567769, -0.048135) Norm(-0.468336, -0.577333, 0.668841) UV(0.685505, 0.0)
|
||||||
|
V 104: Pos(0.243142, 0.285422, -0.083115) Norm(-0.577359, 0.577332, 0.577359) UV(0.137905, 0.850964)
|
||||||
|
V 105: Pos(0.347237, 0.285422, -0.083115) Norm(0.577358, 0.577347, 0.577347) UV(0.65141, 0.715234)
|
||||||
|
V 106: Pos(0.243142, 0.221328, -0.083115) Norm(-0.577358, -0.577347, 0.577347) UV(0.65141, 0.774464)
|
||||||
|
V 107: Pos(0.347237, 0.221328, -0.127209) Norm(0.577358, -0.577347, -0.577347) UV(0.294091, 0.821176)
|
||||||
|
V 108: Pos(0.243142, 0.221328, -0.083115) Norm(-0.577358, -0.577347, 0.577347) UV(0.330561, 0.821176)
|
||||||
|
|
||||||
|
===Triangles (Indices): 60
|
||||||
|
Tri: 0 1 2
|
||||||
|
Tri: 3 4 5
|
||||||
|
Tri: 6 7 8
|
||||||
|
Tri: 9 10 11
|
||||||
|
Tri: 12 13 14
|
||||||
|
Tri: 15 16 17
|
||||||
|
Tri: 18 19 20
|
||||||
|
Tri: 21 22 23
|
||||||
|
Tri: 24 25 26
|
||||||
|
Tri: 27 28 29
|
||||||
|
Tri: 30 31 32
|
||||||
|
Tri: 33 34 35
|
||||||
|
Tri: 36 37 38
|
||||||
|
Tri: 39 40 37
|
||||||
|
Tri: 41 42 43
|
||||||
|
Tri: 44 38 45
|
||||||
|
Tri: 43 46 47
|
||||||
|
Tri: 39 44 48
|
||||||
|
Tri: 49 50 51
|
||||||
|
Tri: 52 53 54
|
||||||
|
Tri: 55 56 57
|
||||||
|
Tri: 58 59 60
|
||||||
|
Tri: 61 62 63
|
||||||
|
Tri: 64 65 66
|
||||||
|
Tri: 67 68 69
|
||||||
|
Tri: 70 71 72
|
||||||
|
Tri: 73 74 75
|
||||||
|
Tri: 76 77 78
|
||||||
|
Tri: 79 80 81
|
||||||
|
Tri: 82 83 84
|
||||||
|
Tri: 0 85 1
|
||||||
|
Tri: 3 86 4
|
||||||
|
Tri: 6 87 7
|
||||||
|
Tri: 9 88 10
|
||||||
|
Tri: 12 89 13
|
||||||
|
Tri: 15 90 16
|
||||||
|
Tri: 18 91 19
|
||||||
|
Tri: 21 92 22
|
||||||
|
Tri: 24 93 25
|
||||||
|
Tri: 27 94 28
|
||||||
|
Tri: 30 95 31
|
||||||
|
Tri: 33 96 34
|
||||||
|
Tri: 36 39 37
|
||||||
|
Tri: 39 48 40
|
||||||
|
Tri: 41 97 42
|
||||||
|
Tri: 44 36 38
|
||||||
|
Tri: 43 42 46
|
||||||
|
Tri: 39 36 44
|
||||||
|
Tri: 49 98 50
|
||||||
|
Tri: 52 99 53
|
||||||
|
Tri: 55 100 56
|
||||||
|
Tri: 58 101 59
|
||||||
|
Tri: 61 102 62
|
||||||
|
Tri: 64 103 65
|
||||||
|
Tri: 67 104 68
|
||||||
|
Tri: 70 105 71
|
||||||
|
Tri: 73 76 74
|
||||||
|
Tri: 76 106 77
|
||||||
|
Tri: 79 107 80
|
||||||
|
Tri: 82 108 83
|
||||||
BIN
resources/w/interior/computer_texture002.png
(Stored with Git LFS)
Normal file
BIN
resources/w/interior/computer_texture002.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -7,6 +7,7 @@
|
|||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
|
|
||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
const float ATTACK_COOLDOWN_TIME = 1.6f;
|
const float ATTACK_COOLDOWN_TIME = 1.6f;
|
||||||
@ -94,6 +95,15 @@ Eigen::Vector3f Character::getCurrentNavigationTarget() const
|
|||||||
return walkTarget;
|
return walkTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Character::stopInPlace()
|
||||||
|
{
|
||||||
|
walkTarget = Eigen::Vector3f(position.x(), 0.f, position.z());
|
||||||
|
requestedWalkTarget = walkTarget;
|
||||||
|
pathWaypoints.clear();
|
||||||
|
currentWaypointIndex = 0;
|
||||||
|
onArrivedCallback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Character::forceReplan()
|
void Character::forceReplan()
|
||||||
{
|
{
|
||||||
if (!pathPlanner) {
|
if (!pathPlanner) {
|
||||||
@ -343,6 +353,18 @@ void Character::update(int64_t deltaMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!isPlayer && hp > 0.f && battle_state == 0 && maxHomeDrift > 0.f) {
|
||||||
|
homeDriftCheckTimer -= static_cast<float>(deltaMs) / 1000.f;
|
||||||
|
if (homeDriftCheckTimer <= 0.f) {
|
||||||
|
homeDriftCheckTimer = HOME_DRIFT_CHECK_INTERVAL;
|
||||||
|
Eigen::Vector3f toHome = homePosition - position;
|
||||||
|
toHome.y() = 0.f;
|
||||||
|
if (!isMoving() && toHome.norm() > maxHomeDrift) {
|
||||||
|
setTarget(homePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hitSparkEmitter.isConfigured()) {
|
if (hitSparkEmitter.isConfigured()) {
|
||||||
hitSparkEmitter.update(static_cast<float>(deltaMs));
|
hitSparkEmitter.update(static_cast<float>(deltaMs));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,10 @@ public:
|
|||||||
const Eigen::Vector3f& getRequestedWalkTarget() const { return requestedWalkTarget; }
|
const Eigen::Vector3f& getRequestedWalkTarget() const { return requestedWalkTarget; }
|
||||||
Eigen::Vector3f getCurrentNavigationTarget() const;
|
Eigen::Vector3f getCurrentNavigationTarget() const;
|
||||||
void forceReplan();
|
void forceReplan();
|
||||||
|
// Cancels any active walk target and clears waypoints so the character
|
||||||
|
// stays at its current position. Used when an external push moves the
|
||||||
|
// character and we don't want it to walk back to where it was.
|
||||||
|
void stopInPlace();
|
||||||
|
|
||||||
|
|
||||||
// attackDirection is a world-space horizontal vector pointing from the
|
// attackDirection is a world-space horizontal vector pointing from the
|
||||||
@ -110,6 +114,13 @@ public:
|
|||||||
float hp = 200.f;
|
float hp = 200.f;
|
||||||
float initialHp = 200.f;
|
float initialHp = 200.f;
|
||||||
|
|
||||||
|
// The position the NPC should return to if pushed too far away.
|
||||||
|
// Initialised to the spawn position; updated whenever a script walk command is issued.
|
||||||
|
Eigen::Vector3f homePosition = Eigen::Vector3f::Zero();
|
||||||
|
// Maximum allowed drift from homePosition before a return walk is triggered (metres).
|
||||||
|
// Set to 0 to disable drift recovery for this character.
|
||||||
|
float maxHomeDrift = 3.0f;
|
||||||
|
|
||||||
|
|
||||||
int battle_state = 0;
|
int battle_state = 0;
|
||||||
bool resetAnim = false;
|
bool resetAnim = false;
|
||||||
@ -163,6 +174,9 @@ private:
|
|||||||
|
|
||||||
static constexpr float WALK_THRESHOLD = 0.05f;
|
static constexpr float WALK_THRESHOLD = 0.05f;
|
||||||
static constexpr float TARGET_REPLAN_THRESHOLD = 0.25f;
|
static constexpr float TARGET_REPLAN_THRESHOLD = 0.25f;
|
||||||
|
static constexpr float HOME_DRIFT_CHECK_INTERVAL = 5.0f;
|
||||||
|
|
||||||
|
float homeDriftCheckTimer = HOME_DRIFT_CHECK_INTERVAL;
|
||||||
|
|
||||||
// Returns the animation state to actually play/draw, falling back to IDLE
|
// Returns the animation state to actually play/draw, falling back to IDLE
|
||||||
// if the requested state has no loaded animation.
|
// if the requested state has no loaded animation.
|
||||||
|
|||||||
@ -233,9 +233,7 @@ namespace ZL
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
uniInteriorParams.teleportsJsonPath = "resources/config2/teleports_uni_interior.json";
|
||||||
|
|
||||||
uniInteriorParams.teleportsJsonPath = "resources/config2/teleports.json";
|
|
||||||
uniInteriorParams.triggerZonesJsonPath = "resources/config2/trigger_zones_uni_interior.json";
|
uniInteriorParams.triggerZonesJsonPath = "resources/config2/trigger_zones_uni_interior.json";
|
||||||
uniInteriorParams.scriptPath = "resources/start_uni_interior.lua";
|
uniInteriorParams.scriptPath = "resources/start_uni_interior.lua";
|
||||||
uniInteriorParams.interactiveObjectsJsonPath = "resources/config2/interactive_objects_uni_interior.json";
|
uniInteriorParams.interactiveObjectsJsonPath = "resources/config2/interactive_objects_uni_interior.json";
|
||||||
|
|||||||
@ -111,6 +111,7 @@ namespace ZL
|
|||||||
npcs = GameObjectLoader::loadAndCreate_Npcs(params.npcsJsonPath, CONST_ZIP_FILE);
|
npcs = GameObjectLoader::loadAndCreate_Npcs(params.npcsJsonPath, CONST_ZIP_FILE);
|
||||||
for (auto& npc : npcs) {
|
for (auto& npc : npcs) {
|
||||||
if (!npc) continue;
|
if (!npc) continue;
|
||||||
|
npc->homePosition = Eigen::Vector3f(npc->position.x(), 0.f, npc->position.z());
|
||||||
if (npc->canAttack) {
|
if (npc->canAttack) {
|
||||||
npc->setupHitSparks(sparkTexture);
|
npc->setupHitSparks(sparkTexture);
|
||||||
npc->attackTarget = player.get();
|
npc->attackTarget = player.get();
|
||||||
@ -297,6 +298,7 @@ namespace ZL
|
|||||||
const auto addCharacter = [&](const Character* other) {
|
const auto addCharacter = [&](const Character* other) {
|
||||||
if (!other || other == self) return;
|
if (!other || other == self) return;
|
||||||
if (other->hp <= 0.f || !other->enabled) return;
|
if (other->hp <= 0.f || !other->enabled) return;
|
||||||
|
if (other->isMoving()) return;
|
||||||
|
|
||||||
if (distancePointToSegmentXZ(other->position, start, end) > kDynamicObstacleInfluenceDist) {
|
if (distancePointToSegmentXZ(other->position, start, end) > kDynamicObstacleInfluenceDist) {
|
||||||
return;
|
return;
|
||||||
@ -304,7 +306,7 @@ namespace ZL
|
|||||||
|
|
||||||
PathFinder::DynamicObstacle obs;
|
PathFinder::DynamicObstacle obs;
|
||||||
obs.position = Eigen::Vector3f(other->position.x(), navigation->getFloorY(), other->position.z());
|
obs.position = Eigen::Vector3f(other->position.x(), navigation->getFloorY(), other->position.z());
|
||||||
obs.radius = (std::max)(0.0f, other->collisionRadius);
|
obs.radius = (std::max)(0.0f, other->collisionRadius * 0.6f);
|
||||||
dynamicObstacles.push_back(obs);
|
dynamicObstacles.push_back(obs);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -313,7 +315,7 @@ namespace ZL
|
|||||||
addCharacter(npc.get());
|
addCharacter(npc.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return navigation->findPath(start, end, dynamicObstacles);
|
return navigation->findPathToNearest(start, end, dynamicObstacles);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -981,6 +983,30 @@ namespace ZL
|
|||||||
return navigation->setAreaAvailable(areaName, available);
|
return navigation->setAreaAvailable(areaName, available);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Location::nudgeCharacterAside(Character* standing, const Eigen::Vector3f& awayFrom)
|
||||||
|
{
|
||||||
|
if (!standing || standing->isPlayer) return;
|
||||||
|
if (!navigation || !navigation->isReady()) return;
|
||||||
|
|
||||||
|
static constexpr float kNudgeDist = 1.2f;
|
||||||
|
|
||||||
|
Eigen::Vector3f dir = standing->position - awayFrom;
|
||||||
|
dir.y() = 0.f;
|
||||||
|
if (dir.norm() < 1e-3f) dir = Eigen::Vector3f(1.f, 0.f, 0.f);
|
||||||
|
else dir.normalize();
|
||||||
|
|
||||||
|
const float angles[] = { 0.f, static_cast<float>(M_PI * 0.5), static_cast<float>(-M_PI * 0.5), static_cast<float>(M_PI) };
|
||||||
|
for (float angle : angles) {
|
||||||
|
Eigen::Vector3f rotated = Eigen::AngleAxisf(angle, Eigen::Vector3f::UnitY()) * dir;
|
||||||
|
Eigen::Vector3f candidate = standing->position + rotated * kNudgeDist;
|
||||||
|
candidate.y() = 0.f;
|
||||||
|
if (navigation->isWalkable(candidate)) {
|
||||||
|
standing->setTarget(candidate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Location::resolveCharacterCollisions()
|
void Location::resolveCharacterCollisions()
|
||||||
{
|
{
|
||||||
std::vector<Character*> characters;
|
std::vector<Character*> characters;
|
||||||
@ -1039,6 +1065,9 @@ namespace ZL
|
|||||||
newB.z() += normal.y() * push;
|
newB.z() += normal.y() * push;
|
||||||
newB.y() = 0.f;
|
newB.y() = 0.f;
|
||||||
|
|
||||||
|
const bool aWasMoving = a->isMoving();
|
||||||
|
const bool bWasMoving = b->isMoving();
|
||||||
|
|
||||||
if (navigation && navigation->isReady()) {
|
if (navigation && navigation->isReady()) {
|
||||||
const bool aOk = navigation->isWalkable(newA);
|
const bool aOk = navigation->isWalkable(newA);
|
||||||
const bool bOk = navigation->isWalkable(newB);
|
const bool bOk = navigation->isWalkable(newB);
|
||||||
@ -1058,6 +1087,15 @@ namespace ZL
|
|||||||
a->position = newA;
|
a->position = newA;
|
||||||
b->position = newB;
|
b->position = newB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a->isPlayer && !aWasMoving) a->stopInPlace();
|
||||||
|
if (b->isPlayer && !bWasMoving) b->stopInPlace();
|
||||||
|
|
||||||
|
if (aWasMoving && !bWasMoving) {
|
||||||
|
nudgeCharacterAside(b, a->position);
|
||||||
|
} else if (bWasMoving && !aWasMoving) {
|
||||||
|
nudgeCharacterAside(a, b->position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1066,8 +1104,8 @@ namespace ZL
|
|||||||
void Location::updateDynamicReplans(int64_t deltaMs)
|
void Location::updateDynamicReplans(int64_t deltaMs)
|
||||||
{
|
{
|
||||||
static constexpr float kMovedEps = 0.05f;
|
static constexpr float kMovedEps = 0.05f;
|
||||||
static constexpr float kReplanTriggerDist = 1.1f;
|
static constexpr float kReplanTriggerDist = 1.8f;
|
||||||
static constexpr int64_t kReplanCooldownMs = 300;
|
static constexpr int64_t kReplanCooldownMs = 500;
|
||||||
|
|
||||||
for (auto it = replanCooldownRemainingMs.begin(); it != replanCooldownRemainingMs.end();) {
|
for (auto it = replanCooldownRemainingMs.begin(); it != replanCooldownRemainingMs.end();) {
|
||||||
it->second -= deltaMs;
|
it->second -= deltaMs;
|
||||||
|
|||||||
@ -151,6 +151,7 @@ namespace ZL
|
|||||||
void loadTeleportZones(const std::string& jsonPath, const char* zipFile);
|
void loadTeleportZones(const std::string& jsonPath, const char* zipFile);
|
||||||
void loadTriggerZones(const std::string& jsonPath, const char* zipFile);
|
void loadTriggerZones(const std::string& jsonPath, const char* zipFile);
|
||||||
void updateTriggerZones(const Eigen::Vector3f& playerPos);
|
void updateTriggerZones(const Eigen::Vector3f& playerPos);
|
||||||
|
void nudgeCharacterAside(Character* standing, const Eigen::Vector3f& awayFrom);
|
||||||
|
|
||||||
std::unordered_map<Character*, Eigen::Vector3f> lastCharacterPositions;
|
std::unordered_map<Character*, Eigen::Vector3f> lastCharacterPositions;
|
||||||
std::unordered_map<Character*, int64_t> replanCooldownRemainingMs;
|
std::unordered_map<Character*, int64_t> replanCooldownRemainingMs;
|
||||||
|
|||||||
@ -57,6 +57,7 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
npcs[index]->homePosition = Eigen::Vector3f(x, 0.f, z);
|
||||||
npcs[index]->setTarget(Eigen::Vector3f(x, y, z), std::move(cb));
|
npcs[index]->setTarget(Eigen::Vector3f(x, y, z), std::move(cb));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ namespace ZL {
|
|||||||
api.set_function("set_object_rotation", [game](const std::string& objectName, float value) {
|
api.set_function("set_object_rotation", [game](const std::string& objectName, float value) {
|
||||||
for (auto& intObj : game->interactiveObjects) {
|
for (auto& intObj : game->interactiveObjects) {
|
||||||
if (intObj.loadedObject.name == objectName) {
|
if (intObj.loadedObject.name == objectName) {
|
||||||
intObj.rotationY = value;
|
intObj.rotationY = value * static_cast<float>(M_PI) / 180.f;
|
||||||
std::cout << "[script] set_object_rotation: " << objectName << " " << value << std::endl;
|
std::cout << "[script] set_object_rotation: " << objectName << " " << value << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -316,7 +317,7 @@ namespace ZL {
|
|||||||
npcs[index]->setTarget(pos);
|
npcs[index]->setTarget(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
// npc_set_rotation(index, angle) — sets NPC facing angle around Y axis (radians).
|
// npc_set_rotation(index, angle) — sets NPC facing angle around Y axis (degrees).
|
||||||
api.set_function("npc_set_rotation",
|
api.set_function("npc_set_rotation",
|
||||||
[game](int index, float angle) {
|
[game](int index, float angle) {
|
||||||
auto& npcs = game->npcs;
|
auto& npcs = game->npcs;
|
||||||
@ -324,8 +325,9 @@ namespace ZL {
|
|||||||
std::cerr << "[script] npc_set_rotation: index " << index << " out of range\n";
|
std::cerr << "[script] npc_set_rotation: index " << index << " out of range\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
npcs[index]->facingAngle = angle;
|
const float rad = angle * static_cast<float>(M_PI) / 180.f;
|
||||||
npcs[index]->targetFacingAngle = angle;
|
npcs[index]->facingAngle = rad;
|
||||||
|
npcs[index]->targetFacingAngle = rad;
|
||||||
});
|
});
|
||||||
|
|
||||||
// set_npc_enabled(index, enabled)
|
// set_npc_enabled(index, enabled)
|
||||||
|
|||||||
@ -119,13 +119,14 @@ namespace ZL {
|
|||||||
else
|
else
|
||||||
obj.mesh.data = LoadFromTextFile02(data.meshPath, zipPath);
|
obj.mesh.data = LoadFromTextFile02(data.meshPath, zipPath);
|
||||||
|
|
||||||
|
constexpr float kDeg2Rad = static_cast<float>(M_PI) / 180.0f;
|
||||||
Eigen::Quaternionf rot = Eigen::Quaternionf::Identity();
|
Eigen::Quaternionf rot = Eigen::Quaternionf::Identity();
|
||||||
if (data.rotationX != 0.0f)
|
if (data.rotationX != 0.0f)
|
||||||
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationX, Eigen::Vector3f::UnitX())) * rot;
|
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationX * kDeg2Rad, Eigen::Vector3f::UnitX())) * rot;
|
||||||
if (data.rotationY != 0.0f)
|
if (data.rotationY != 0.0f)
|
||||||
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationY, Eigen::Vector3f::UnitY())) * rot;
|
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationY * kDeg2Rad, Eigen::Vector3f::UnitY())) * rot;
|
||||||
if (data.rotationZ != 0.0f)
|
if (data.rotationZ != 0.0f)
|
||||||
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationZ, Eigen::Vector3f::UnitZ())) * rot;
|
rot = Eigen::Quaternionf(Eigen::AngleAxisf(data.rotationZ * kDeg2Rad, Eigen::Vector3f::UnitZ())) * rot;
|
||||||
obj.mesh.data.RotateByMatrix(rot.toRotationMatrix());
|
obj.mesh.data.RotateByMatrix(rot.toRotationMatrix());
|
||||||
|
|
||||||
if (data.scale != 1.0f)
|
if (data.scale != 1.0f)
|
||||||
@ -262,7 +263,7 @@ namespace ZL {
|
|||||||
data.modelCorrectionRotX = item.value("modelCorrectionRotX", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
data.modelCorrectionRotX = item.value("modelCorrectionRotX", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
data.modelCorrectionRotY = item.value("modelCorrectionRotY", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
data.modelCorrectionRotY = item.value("modelCorrectionRotY", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
data.modelCorrectionRotZ = item.value("modelCorrectionRotZ", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
data.modelCorrectionRotZ = item.value("modelCorrectionRotZ", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
data.facingAngle = item.value("facingAngle", 0.0f);
|
data.facingAngle = item.value("facingAngle", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
data.hp = item.value("hp", 100.0f);
|
data.hp = item.value("hp", 100.0f);
|
||||||
data.canAttack = item.value("canAttack", false);
|
data.canAttack = item.value("canAttack", false);
|
||||||
data.enabled = item.value("enabled", true);
|
data.enabled = item.value("enabled", true);
|
||||||
|
|||||||
@ -397,6 +397,124 @@ std::vector<Eigen::Vector3f> PathFinder::findPath(const Eigen::Vector3f& start,
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Eigen::Vector3f> PathFinder::findNearestReachableImpl(
|
||||||
|
const Eigen::Vector3f& start,
|
||||||
|
const Eigen::Vector3f& end,
|
||||||
|
const std::vector<unsigned char>& walkableGrid) const
|
||||||
|
{
|
||||||
|
if (!ready || walkableGrid.empty()) return {};
|
||||||
|
|
||||||
|
Cell startCell;
|
||||||
|
Cell endCell;
|
||||||
|
if (!findNearestWalkableCell(start, startCell, walkableGrid)) return {};
|
||||||
|
if (!findNearestWalkableCell(end, endCell, walkableGrid)) return {};
|
||||||
|
|
||||||
|
struct QueueNode {
|
||||||
|
int index = 0;
|
||||||
|
float priority = 0.0f;
|
||||||
|
bool operator<(const QueueNode& other) const { return priority > other.priority; }
|
||||||
|
};
|
||||||
|
|
||||||
|
const int cellCount = gridWidth * gridDepth;
|
||||||
|
std::vector<float> cost(static_cast<size_t>(cellCount), INF_COST);
|
||||||
|
std::vector<int> cameFrom(static_cast<size_t>(cellCount), -1);
|
||||||
|
std::priority_queue<QueueNode> open;
|
||||||
|
|
||||||
|
const int startIndex = indexOf(startCell);
|
||||||
|
const int endIndex = indexOf(endCell);
|
||||||
|
|
||||||
|
cost[static_cast<size_t>(startIndex)] = 0.f;
|
||||||
|
open.push({ startIndex, 0.f });
|
||||||
|
|
||||||
|
int bestIndex = startIndex;
|
||||||
|
float bestDist = distanceCells(startCell, endCell);
|
||||||
|
|
||||||
|
static const int offsets[8][2] = {
|
||||||
|
{ 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 },
|
||||||
|
{ 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
while (!open.empty()) {
|
||||||
|
const QueueNode current = open.top();
|
||||||
|
open.pop();
|
||||||
|
|
||||||
|
if (current.index == endIndex) {
|
||||||
|
bestIndex = endIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost[static_cast<size_t>(current.index)] < current.priority - distanceCells({ current.index % gridWidth, current.index / gridWidth }, endCell)) {
|
||||||
|
continue; // stale entry
|
||||||
|
}
|
||||||
|
|
||||||
|
const Cell currentCell{ current.index % gridWidth, current.index / gridWidth };
|
||||||
|
const float d = distanceCells(currentCell, endCell);
|
||||||
|
if (d < bestDist) {
|
||||||
|
bestDist = d;
|
||||||
|
bestIndex = current.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& offset : offsets) {
|
||||||
|
Cell next{ currentCell.x + offset[0], currentCell.z + offset[1] };
|
||||||
|
if (!isCellWalkable(next, walkableGrid)) continue;
|
||||||
|
|
||||||
|
const bool diagonal = offset[0] != 0 && offset[1] != 0;
|
||||||
|
if (diagonal) {
|
||||||
|
Cell h{ currentCell.x + offset[0], currentCell.z };
|
||||||
|
Cell v{ currentCell.x, currentCell.z + offset[1] };
|
||||||
|
if (!isCellWalkable(h, walkableGrid) || !isCellWalkable(v, walkableGrid)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int nextIndex = indexOf(next);
|
||||||
|
const float stepCost = diagonal ? 1.41421356f : 1.0f;
|
||||||
|
const float newCost = cost[static_cast<size_t>(current.index)] + stepCost;
|
||||||
|
if (newCost >= cost[static_cast<size_t>(nextIndex)]) continue;
|
||||||
|
|
||||||
|
cost[static_cast<size_t>(nextIndex)] = newCost;
|
||||||
|
cameFrom[static_cast<size_t>(nextIndex)] = current.index;
|
||||||
|
open.push({ nextIndex, newCost + distanceCells(next, endCell) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestIndex == startIndex) return {};
|
||||||
|
|
||||||
|
std::vector<Cell> cells;
|
||||||
|
for (int cur = bestIndex; cur != -1; cur = cameFrom[static_cast<size_t>(cur)]) {
|
||||||
|
cells.push_back({ cur % gridWidth, cur / gridWidth });
|
||||||
|
if (cur == startIndex) break;
|
||||||
|
}
|
||||||
|
std::reverse(cells.begin(), cells.end());
|
||||||
|
cells = smoothCells(cells, walkableGrid);
|
||||||
|
|
||||||
|
std::vector<Eigen::Vector3f> path;
|
||||||
|
path.reserve(cells.size());
|
||||||
|
for (const Cell& cell : cells) path.push_back(cellCenter(cell));
|
||||||
|
|
||||||
|
if (!path.empty() && (path.front() - Eigen::Vector3f(start.x(), floorY, start.z())).norm() < cellSize * 0.75f)
|
||||||
|
path.erase(path.begin());
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Eigen::Vector3f> PathFinder::findPathToNearest(
|
||||||
|
const Eigen::Vector3f& start, const Eigen::Vector3f& end) const
|
||||||
|
{
|
||||||
|
auto path = findPath(start, end);
|
||||||
|
if (!path.empty()) return path;
|
||||||
|
return findNearestReachableImpl(start, end, walkable);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Eigen::Vector3f> PathFinder::findPathToNearest(
|
||||||
|
const Eigen::Vector3f& start, const Eigen::Vector3f& end,
|
||||||
|
const std::vector<DynamicObstacle>& dynamicObstacles) const
|
||||||
|
{
|
||||||
|
auto path = findPath(start, end, dynamicObstacles);
|
||||||
|
if (!path.empty()) return path;
|
||||||
|
path = findPath(start, end);
|
||||||
|
if (!path.empty()) return path;
|
||||||
|
return findNearestReachableImpl(start, end, walkable);
|
||||||
|
}
|
||||||
|
|
||||||
bool PathFinder::setAreaAvailable(const std::string& areaName, bool available)
|
bool PathFinder::setAreaAvailable(const std::string& areaName, bool available)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|||||||
@ -41,6 +41,14 @@ public:
|
|||||||
const Eigen::Vector3f& end,
|
const Eigen::Vector3f& end,
|
||||||
const std::vector<DynamicObstacle>& dynamicObstacles) const;
|
const std::vector<DynamicObstacle>& dynamicObstacles) const;
|
||||||
|
|
||||||
|
// Like findPath, but when the destination is unreachable the character
|
||||||
|
// walks as close as possible instead of not moving at all.
|
||||||
|
std::vector<Eigen::Vector3f> findPathToNearest(const Eigen::Vector3f& start,
|
||||||
|
const Eigen::Vector3f& end) const;
|
||||||
|
std::vector<Eigen::Vector3f> findPathToNearest(const Eigen::Vector3f& start,
|
||||||
|
const Eigen::Vector3f& end,
|
||||||
|
const std::vector<DynamicObstacle>& dynamicObstacles) const;
|
||||||
|
|
||||||
bool setAreaAvailable(const std::string& areaName, bool available);
|
bool setAreaAvailable(const std::string& areaName, bool available);
|
||||||
bool isReady() const { return ready; }
|
bool isReady() const { return ready; }
|
||||||
bool isWalkable(const Eigen::Vector3f& point) const;
|
bool isWalkable(const Eigen::Vector3f& point) const;
|
||||||
@ -95,6 +103,12 @@ private:
|
|||||||
bool findNearestWalkableCell(const Eigen::Vector3f& point, Cell& out, const std::vector<unsigned char>& walkableGrid) const;
|
bool findNearestWalkableCell(const Eigen::Vector3f& point, Cell& out, const std::vector<unsigned char>& walkableGrid) const;
|
||||||
bool hasLineOfSight(const Cell& from, const Cell& to, const std::vector<unsigned char>& walkableGrid) const;
|
bool hasLineOfSight(const Cell& from, const Cell& to, const std::vector<unsigned char>& walkableGrid) const;
|
||||||
std::vector<Cell> smoothCells(const std::vector<Cell>& cells, const std::vector<unsigned char>& walkableGrid) const;
|
std::vector<Cell> smoothCells(const std::vector<Cell>& cells, const std::vector<unsigned char>& walkableGrid) const;
|
||||||
|
|
||||||
|
// A* that runs to exhaustion and returns a path to the reachable cell
|
||||||
|
// geometrically closest to end when end itself is unreachable.
|
||||||
|
std::vector<Eigen::Vector3f> findNearestReachableImpl(const Eigen::Vector3f& start,
|
||||||
|
const Eigen::Vector3f& end,
|
||||||
|
const std::vector<unsigned char>& walkableGrid) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user