Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partially implement Maniacs Command 3015: RewriteMap #3306

Merged
33 changes: 31 additions & 2 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4547,12 +4547,41 @@ 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;

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
6 changes: 6 additions & 0 deletions src/game_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,12 @@ int Game_Map::SubstituteUp(int old_id, int new_id) {
return DoSubstitute(map_info.upper_tiles, old_id, new_id);
}

void Game_Map::ReplaceTileAt(int x, int y, int new_id, int layer) {
auto pos = x + y * map->width;
auto& layer_vec = layer >= 1 ? map->upper_layer : map->lower_layer;
layer_vec[pos] = static_cast<int16_t>(new_id);
}

std::string Game_Map::ConstructMapName(int map_id, bool is_easyrpg) {
std::stringstream ss;
ss << "Map" << std::setfill('0') << std::setw(4) << map_id;
Expand Down
1 change: 1 addition & 0 deletions src/game_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ namespace Game_Map {
Game_Vehicle* GetVehicle(Game_Vehicle::Type which);
int SubstituteDown(int old_id, int new_id);
int SubstituteUp(int old_id, int new_id);
void ReplaceTileAt(int x, int y, int new_id, int layer);

/**
* Checks if its possible to step onto the tile at (x,y)
Expand Down
33 changes: 33 additions & 0 deletions src/map_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ static constexpr int NUM_LOWER_TILES = BLOCK_F_INDEX;
static constexpr int NUM_UPPER_TILES = BLOCK_F_TILES;
static constexpr int NUM_TILES = NUM_LOWER_TILES + NUM_UPPER_TILES;

// Bit positions for neighbors
static constexpr uint8_t NEIGHBOR_NW = 0x80; // 0b10000000
static constexpr uint8_t NEIGHBOR_N = 0x40; // 0b01000000
static constexpr uint8_t NEIGHBOR_NE = 0x20; // 0b00100000
static constexpr uint8_t NEIGHBOR_W = 0x10; // 0b00010000
static constexpr uint8_t NEIGHBOR_E = 0x08; // 0b00001000
static constexpr uint8_t NEIGHBOR_SW = 0x04; // 0b00000100
static constexpr uint8_t NEIGHBOR_S = 0x02; // 0b00000010
static constexpr uint8_t NEIGHBOR_SE = 0x01; // 0b00000001


/** Passability flags. */
namespace Passable {
enum Passable {
Expand Down Expand Up @@ -94,4 +105,26 @@ inline int ChipIdToIndex(int chip_id) {
return 0;
}

inline int IndexToChipId(int index) {
if (index >= BLOCK_A_INDEX && index < BLOCK_B_INDEX) {
return BLOCK_A + (index - BLOCK_A_INDEX) * BLOCK_A_STRIDE;
}
else if (index >= BLOCK_B_INDEX && index < BLOCK_C_INDEX) {
return BLOCK_B + (index - BLOCK_B_INDEX) * BLOCK_B_STRIDE;
}
else if (index >= BLOCK_C_INDEX && index < BLOCK_D_INDEX) {
return BLOCK_C + (index - BLOCK_C_INDEX) * BLOCK_C_STRIDE;
}
else if (index >= BLOCK_D_INDEX && index < BLOCK_E_INDEX) {
return BLOCK_D + (index - BLOCK_D_INDEX) * BLOCK_D_STRIDE;
}
else if (index >= BLOCK_E_INDEX && index < BLOCK_F_INDEX) {
return BLOCK_E + (index - BLOCK_E_INDEX) * BLOCK_E_STRIDE;
}
else if (index >= BLOCK_F_INDEX) {
return BLOCK_F + (index - BLOCK_F_INDEX) * BLOCK_F_STRIDE;
}
return 0;
}

#endif
11 changes: 11 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,16 @@ 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);
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);
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
Loading
Loading