Skip to content

Commit

Permalink
Partially implement Maniacs RewriteMap (without autotile fixup)
Browse files Browse the repository at this point in the history
  • Loading branch information
Primekick committed Nov 26, 2024
1 parent a3be5ea commit ad2557a
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 30 deletions.
44 changes: 42 additions & 2 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4547,12 +4547,52 @@ bool Game_Interpreter::CommandManiacKeyInputProcEx(lcf::rpg::EventCommand const&
return true;
}

bool Game_Interpreter::CommandManiacRewriteMap(lcf::rpg::EventCommand const&) {
bool Game_Interpreter::CommandManiacRewriteMap(lcf::rpg::EventCommand const& com) {
if (!Player::IsPatchManiac()) {
return true;
}

Output::Warning("Maniac Patch: Command RewriteMap not supported");
int mode = com.parameters[0];
bool is_replace_range = com.parameters[1] != 0;
bool is_upper_layer = com.parameters[2] != 0;

int tile_index = ValueOrVariableBitfield(mode, 0, com.parameters[3]);
int x_start = ValueOrVariableBitfield(mode, 1, com.parameters[4]);
int y_start = ValueOrVariableBitfield(mode, 2, com.parameters[5]);
int width = ValueOrVariableBitfield(mode, 3, com.parameters[6]);
int height = ValueOrVariableBitfield(mode, 4, com.parameters[7]);

bool disable_autotile = com.parameters[8] != 0;

Output::Debug("RewriteMap | Mode: {}, SingleRange: {}, Layer: {}, IdOrArrayStart: {}, LeftEnd: {}, TopValue: {}, Width: {}, Height: {}, Autotile: {}",
mode,
is_replace_range,
is_upper_layer,
tile_index,
x_start,
y_start,
width,
height,
disable_autotile);

Scene_Map* scene = (Scene_Map*)Scene::Find(Scene::Map).get();
if (!scene)
return true;

if (is_upper_layer) {
for (auto y = y_start; y < y_start + height; ++y) {
for (auto x = x_start; x < x_start + width; ++x) {
scene->spriteset->ReplaceUpAt(x, y, tile_index);
}
}
} else {
for (auto y = y_start; y < y_start + height; ++y) {
for (auto x = x_start; x < x_start + width; ++x) {
scene->spriteset->ReplaceDownAt(x, y, tile_index, disable_autotile);
}
}
}

return true;
}

Expand Down
13 changes: 13 additions & 0 deletions src/spriteset_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "bitmap.h"
#include "player.h"
#include "drawable_list.h"
#include "map_data.h"

Spriteset_Map::Spriteset_Map() {
panorama = std::make_unique<Plane>();
Expand Down Expand Up @@ -173,6 +174,18 @@ void Spriteset_Map::SubstituteUp(int old_id, int new_id) {
}
}

void Spriteset_Map::ReplaceDownAt(int x, int y, int tile_index, bool disable_autotile) {
auto tile_id = IndexToChipId(tile_index);
Game_Map::ReplaceDownAt(x, y, tile_id);
tilemap->SetMapTileDataDownAt(x, y, tile_id, disable_autotile);
}

void Spriteset_Map::ReplaceUpAt(int x, int y, int tile_index) {
auto tile_id = IndexToChipId(tile_index);
Game_Map::ReplaceUpAt(x, y, tile_id);
tilemap->SetMapTileDataUpAt(x, y, tile_id);
}

bool Spriteset_Map::RequireClear(DrawableList& drawable_list) {
if (drawable_list.empty()) {
return true;
Expand Down
10 changes: 10 additions & 0 deletions src/spriteset_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ class Spriteset_Map {
*/
void SubstituteUp(int old_id, int new_id);

/**
* Replaces a single tile in lower layer at the given coordinates.
*/
void ReplaceDownAt(int x, int y, int tile_index, bool disable_autotile);

/**
* Replaces a single tile in upper layer at the given coordinates.
*/
void ReplaceUpAt(int x, int y, int tile_index);

/**
* @return true if we should clear the screen before drawing the map
*/
Expand Down
10 changes: 10 additions & 0 deletions src/tilemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ class Tilemap {

const std::vector<short>& GetMapDataDown() const;
void SetMapDataDown(std::vector<short> down);
void SetMapTileDataDownAt(int x, int y, int tile_id, bool disable_autotile);

const std::vector<short>& GetMapDataUp() const;
void SetMapDataUp(std::vector<short> up);
void SetMapTileDataUpAt(int x, int y, int tile_id);

const std::vector<unsigned char>& GetPassableUp() const;
void SetPassableUp(std::vector<unsigned char> up);
Expand Down Expand Up @@ -81,6 +83,10 @@ inline void Tilemap::SetMapDataDown(std::vector<short> down) {
layer_down.SetMapData(std::move(down));
}

inline void Tilemap::SetMapTileDataDownAt(int x, int y, int tile_id, bool disable_autotile) {
layer_down.SetMapTileDataAt(x, y, tile_id, disable_autotile);
}

inline const std::vector<short>& Tilemap::GetMapDataUp() const {
return layer_up.GetMapData();
}
Expand All @@ -89,6 +95,10 @@ inline void Tilemap::SetMapDataUp(std::vector<short> up) {
layer_up.SetMapData(std::move(up));
}

inline void Tilemap::SetMapTileDataUpAt(int x, int y, int tile_id) {
layer_down.SetMapTileDataAt(x, y, tile_id, true);
}

inline const std::vector<unsigned char>& Tilemap::GetPassableDown() const {
return layer_down.GetPassable();
}
Expand Down
69 changes: 41 additions & 28 deletions src/tilemap_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,37 +376,39 @@ void TilemapLayer::CreateTileCache(const std::vector<short>& nmap_data) {
data_cache_vec.resize(width * height);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
TileData tile;

// Get the tile ID
tile.ID = nmap_data[x + y * width];

tile.z = TileBelow;

// Calculate the tile Z
if (!passable.empty()) {
if (tile.ID >= BLOCK_F) { // Upper layer
if ((passable[substitutions[tile.ID - BLOCK_F]] & Passable::Above) != 0)
tile.z = TileAbove + 1; // Upper sublayer
else
tile.z = TileBelow + 1; // Lower sublayer

} else { // Lower layer
int chip_index =
tile.ID >= BLOCK_E ? substitutions[tile.ID - BLOCK_E] + 18 :
tile.ID >= BLOCK_D ? (tile.ID - BLOCK_D) / 50 + 6 :
tile.ID >= BLOCK_C ? (tile.ID - BLOCK_C) / 50 + 3 :
tile.ID / 1000;
if ((passable[chip_index] & (Passable::Wall | Passable::Above)) != 0)
tile.z = TileAbove; // Upper sublayer
else
tile.z = TileBelow; // Lower sublayer
auto tile_id = nmap_data[x + y * width];
CreateTileCacheAt(x, y, tile_id);
}
}
}

void TilemapLayer::CreateTileCacheAt(int x, int y, int tile_id) {
TileData tile;
tile.ID = static_cast<short>(tile_id);
tile.z = TileBelow;

// Calculate the tile Z
if (!passable.empty()) {
if (tile.ID >= BLOCK_F) { // Upper layer
if ((passable[substitutions[tile.ID - BLOCK_F]] & Passable::Above) != 0)
tile.z = TileAbove + 1; // Upper sublayer
else
tile.z = TileBelow + 1; // Lower sublayer

} else { // Lower layer
int chip_index =
tile.ID >= BLOCK_E ? substitutions[tile.ID - BLOCK_E] + 18 :
tile.ID >= BLOCK_D ? (tile.ID - BLOCK_D) / 50 + 6 :
tile.ID >= BLOCK_C ? (tile.ID - BLOCK_C) / 50 + 3 :
tile.ID / 1000;
if ((passable[chip_index] & (Passable::Wall | Passable::Above)) != 0)
tile.z = TileAbove; // Upper sublayer
else
tile.z = TileBelow; // Lower sublayer

}
}
GetDataCache(x, y) = tile;
}
}
GetDataCache(x, y) = tile;
}

void TilemapLayer::GenerateAutotileAB(short ID, short animID) {
Expand Down Expand Up @@ -661,6 +663,17 @@ void TilemapLayer::SetMapData(std::vector<short> nmap_data) {
map_data = std::move(nmap_data);
}

void TilemapLayer::SetMapTileDataAt(int x, int y, int tile_id, bool disable_autotile) {
substitutions = Game_Map::GetTilesLayer(layer);

if (disable_autotile) {
CreateTileCacheAt(x, y, tile_id);
} else {
// TODO: handle autotiles
}
}


void TilemapLayer::SetPassable(std::vector<unsigned char> npassable) {
passable = std::move(npassable);

Expand Down
2 changes: 2 additions & 0 deletions src/tilemap_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class TilemapLayer {
void SetChipset(BitmapRef const& nchipset);
const std::vector<short>& GetMapData() const;
void SetMapData(std::vector<short> nmap_data);
void SetMapTileDataAt(int x, int y, int tile_id, bool disable_autotile);
const std::vector<unsigned char>& GetPassable() const;
void SetPassable(std::vector<unsigned char> npassable);
bool IsVisible() const;
Expand Down Expand Up @@ -115,6 +116,7 @@ class TilemapLayer {
bool fast_blit = false;

void CreateTileCache(const std::vector<short>& nmap_data);
void CreateTileCacheAt(int x, int y, int tile_id);
void GenerateAutotileAB(short ID, short animID);
void GenerateAutotileD(short ID);
void DrawTile(Bitmap& dst, Bitmap& tile, Bitmap& tone_tile, int x, int y, int row, int col, uint32_t tone_hash, bool allow_fast_blit = true);
Expand Down

0 comments on commit ad2557a

Please sign in to comment.