yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
track_collision_generator.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_DUNGEON_TRACK_COLLISION_GENERATOR_H
2#define YAZE_ZELDA3_DUNGEON_TRACK_COLLISION_GENERATOR_H
3
4#include <cstddef>
5#include <cstdint>
6#include <map>
7#include <span>
8#include <string>
9#include <tuple>
10#include <utility>
11#include <vector>
12
13#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15#include "rom/rom.h"
18#include "zelda3/dungeon/room.h"
19
20namespace yaze {
21namespace zelda3 {
22
23// Collision tile types used by the Oracle of Secrets minecart system.
24// The minecart sprite reads these via Sprite_GetTileAttr and dispatches
25// movement based on tile value.
26enum class TrackTileType : uint8_t {
27 HorizStraight = 0xB0,
28 VertStraight = 0xB1,
29 CornerTL = 0xB2, // top-left corner (exits: right, down)
30 CornerBL = 0xB3, // bottom-left corner (exits: right, up)
31 CornerTR = 0xB4, // top-right corner (exits: left, down)
32 CornerBR = 0xB5, // bottom-right corner (exits: left, up)
33 Intersection = 0xB6,
34 StopNorth = 0xB7, // endpoint: neighbor is south, cart departs south
35 StopSouth = 0xB8, // endpoint: neighbor is north, cart departs north
36 StopWest = 0xB9, // endpoint: neighbor is east, cart departs east
37 StopEast = 0xBA, // endpoint: neighbor is west, cart departs west
38 TJuncNorth = 0xBB, // closed north; exits south, east, west
39 TJuncSouth = 0xBC, // closed south; exits north, east, west
40 TJuncEast = 0xBD, // closed east; exits north, south, west
41 TJuncWest = 0xBE, // closed west; exits north, south, east
42 SwitchTL = 0xD0,
43 SwitchBL = 0xD1,
44 SwitchTR = 0xD2,
45 SwitchBR = 0xD3,
46};
47
57
59 // Track rail object ID to scan for (default: 0x31)
60 int track_object_id = 0x31;
61
62 // Positions to promote from regular corners to switch corners.
63 // Each pair is (tile_x, tile_y) in the 64x64 collision grid.
64 std::vector<std::pair<int, int>> switch_promotions;
65
66 // Manual stop direction overrides: (tile_x, tile_y, tile_type).
67 // Useful when the auto-detected direction isn't what you want.
68 std::vector<std::tuple<int, int, TrackTileType>> stop_overrides;
69};
70
71// Session-only ownership: keep the exact cell displaced by an automatic rail
72// stamp. An authored cell already matching the desired rail is never adopted.
74 bool baseline_override = false;
75 uint8_t baseline_value = 0;
76 uint8_t generated_value = 0;
77
78 bool operator==(const MinecartTrackCollisionCellOwner&) const = default;
79};
80
82 std::map<size_t, MinecartTrackCollisionCellOwner>;
83
88
89// Synchronize changed Oracle object 0x31 straight rails with their verified 2x2
90// behavior: subtypes 0/7 are horizontal, 1/6 vertical. Changed corner/crossing
91// pieces require explicit behavior editing until their stencils are verified.
92// Only primary-list rails are supported. Unchanged geometry, authored
93// stops/switches, and unowned departing cells are preserved. Owned departing
94// cells restore their baseline only while their generated value still matches.
95// Conflicting shapes, changed lower-layer/out-of-room rails, and new non-rail
96// collision conflicts fail atomically. No Room, ROM, or source file is mutated.
97// The editor must capture collision AND ownership in its object Undo action;
98// ownership is discarded on room/session reload, never inferred from ROM data.
99absl::StatusOr<MinecartTrackCollisionEdit> SynchronizeMinecartTrackCollision(
100 std::span<const RoomObject> before_objects,
101 std::span<const RoomObject> after_objects,
102 const CustomCollisionMap& before_collision,
103 const MinecartTrackCollisionOwnership& before_ownership = {});
104
105// Build a collision map from rail objects in a room.
106// Reads Object 0x31 (rail) positions, builds an occupancy grid,
107// then classifies each tile by its neighbor connectivity.
108absl::StatusOr<TrackCollisionResult> GenerateTrackCollision(
109 Room* room, const GeneratorOptions& options = {});
110
111// Write a generated collision map into the ROM. Reuses a room's uniquely owned
112// blob when the replacement fits; otherwise appends encoded single-tile data
113// and updates the pointer table at kCustomCollisionRoomPointers.
114absl::Status WriteTrackCollision(Rom* rom, int room_id,
115 const CustomCollisionMap& map);
116
117// Generate an ASCII visualization of a collision map for debug/review.
118std::string VisualizeCollisionMap(const CustomCollisionMap& map);
119
120} // namespace zelda3
121} // namespace yaze
122
123#endif // YAZE_ZELDA3_DUNGEON_TRACK_COLLISION_GENERATOR_H
absl::Status WriteTrackCollision(Rom *rom, int room_id, const CustomCollisionMap &map)
std::map< size_t, MinecartTrackCollisionCellOwner > MinecartTrackCollisionOwnership
std::string VisualizeCollisionMap(const CustomCollisionMap &map)
absl::StatusOr< MinecartTrackCollisionEdit > SynchronizeMinecartTrackCollision(std::span< const RoomObject > before_objects, std::span< const RoomObject > after_objects, const CustomCollisionMap &before_collision, const MinecartTrackCollisionOwnership &before_ownership)
absl::StatusOr< TrackCollisionResult > GenerateTrackCollision(Room *room, const GeneratorOptions &options)
std::vector< std::pair< int, int > > switch_promotions
std::vector< std::tuple< int, int, TrackTileType > > stop_overrides
bool operator==(const MinecartTrackCollisionCellOwner &) const =default