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

Fix regression of MakeWay() from MakeWay()/CheckWay() split #3130

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/game_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,10 +476,10 @@ bool Game_Character::CheckWay(int from_x, int from_y, int to_x, int to_y) {
}


bool Game_Character::CheckWayEx(
bool Game_Character::CheckWay(
int from_x, int from_y, int to_x, int to_y, bool ignore_all_events,
std::unordered_set<int> *ignore_some_events_by_id) {
return Game_Map::CheckWayEx(*this, from_x, from_y, to_x, to_y,
return Game_Map::CheckWay(*this, from_x, from_y, to_x, to_y,
ignore_all_events, ignore_some_events_by_id);
}

Expand Down
25 changes: 6 additions & 19 deletions src/game_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,22 +586,6 @@ class Game_Character {
*/
virtual bool MakeWay(int from_x, int from_y, int to_x, int to_y);

/**
* Check if this can move to the given tile, but without
* affecting the map. This is usually what you want to use
* for planning, e.g. path finding, where the move isn't
* meant to be actually executed just yet.
*
* @param from_x Moving from x position
* @param from_y Moving from y position
* @param to_x Moving from x position
* @param to_y Moving from y position
*
* @return true if the hypothetical movement of
* this event from (to_x, to_y) from (from_x, from_y) is possible
*/
virtual bool CheckWay(int from_x, int from_y, int to_x, int to_y);

/**
* Like CheckWay, but allows ignoring all events in the check,
* or only some events specified by event id.
Expand All @@ -610,15 +594,18 @@ class Game_Character {
* @param from_y See CheckWay.
* @param to_x See CheckWay.
* @param to_y See Checkway.
* @param ignore_all_events If true, only consider map collision
* @param ignore_all_events (Optional) If true, only consider map collision
* and completely ignore any events in the way.
* @param ignore_some_events_by_id If specified, all events with
* @param ignore_some_events_by_id (Optional) If specified, all events with
* ids found in this list will be ignored in the collision check.
* @return true See CheckWay.
*/
virtual bool CheckWayEx(int from_x, int from_y, int to_x, int to_y,
virtual bool CheckWay(int from_x, int from_y, int to_x, int to_y,
bool ignore_all_events, std::unordered_set<int> *ignore_some_events_by_id);

/** Short version of CheckWay. **/
virtual bool CheckWay(int from_x, int from_y, int to_x, int to_y);

/**
* Turns the character 90 Degree to the left.
*/
Expand Down
104 changes: 33 additions & 71 deletions src/game_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,48 +578,38 @@ bool Game_Map::CheckWay(const Game_Character& self,
int to_x, int to_y
)
{
return CheckWayEx(
self, from_x, from_y, to_x, to_y, false, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr
return CheckOrMakeWayEx(
self, from_x, from_y, to_x, to_y, true, nullptr, false
);
}

bool Game_Map::CheckWayEx(const Game_Character& self,
bool Game_Map::CheckWay(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y,
bool ignore_events_and_vehicles,
bool check_events_and_vehicles,
std::unordered_set<int> *ignore_some_events_by_id) {
return CheckWayEx(
return CheckOrMakeWayEx(
self, from_x, from_y, to_x, to_y,
ignore_events_and_vehicles,
ignore_some_events_by_id,
nullptr, nullptr, nullptr, nullptr, nullptr
check_events_and_vehicles,
ignore_some_events_by_id, false
);
}

bool Game_Map::CheckWayEx(const Game_Character& self,
bool Game_Map::CheckOrMakeWayEx(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y,
bool ignore_events_and_vehicles,
bool check_events_and_vehicles,
std::unordered_set<int> *ignore_some_events_by_id,
int *out_bit_from,
int *out_bit_to,
int *out_to_x,
int *out_to_y,
bool *out_self_conflict
bool make_way
)
{
// Infer directions before we do any rounding.
const int bit_from = GetPassableMask(from_x, from_y, to_x, to_y);
const int bit_to = GetPassableMask(to_x, to_y, from_x, from_y);
if (out_bit_from) *out_bit_from = bit_from;
if (out_bit_to) *out_bit_to = bit_to;

// Now round for looping maps.
to_x = Game_Map::RoundX(to_x);
to_y = Game_Map::RoundY(to_y);
if (out_to_x) *out_to_x = to_x;
if (out_to_y) *out_to_y = to_y;

// Note, even for diagonal, if the tile is invalid we still check vertical/horizontal first!
if (!Game_Map::IsValid(to_x, to_y)) {
Expand All @@ -632,6 +622,19 @@ bool Game_Map::CheckWayEx(const Game_Character& self,

const auto vehicle_type = GetCollisionVehicleType(&self);
bool self_conflict = false;

// Depending on whether we're supposed to call MakeWayCollideEvent
// (which might change the map) or not, choose what to call:
auto CheckOrMakeCollideEvent = [&](auto& other) {
if (make_way) {
return MakeWayCollideEvent(to_x, to_y, self, other, self_conflict);
} else {
return CheckWayTestCollideEvent(
to_x, to_y, self, other, self_conflict
);
}
};

if (!self.IsJumping()) {
// Check for self conflict.
// If this event has a tile graphic and the tile itself has passage blocked in the direction
Expand Down Expand Up @@ -659,35 +662,34 @@ bool Game_Map::CheckWayEx(const Game_Character& self,
}
}
}
if (out_self_conflict) *out_self_conflict = self_conflict;
if (vehicle_type != Game_Vehicle::Airship && !ignore_events_and_vehicles) {
if (vehicle_type != Game_Vehicle::Airship && check_events_and_vehicles) {
// Check for collision with events on the target tile.
for (auto& other: GetEvents()) {
if (ignore_some_events_by_id != NULL &&
ignore_some_events_by_id->find(other.GetId()) !=
ignore_some_events_by_id->end())
continue;
if (CheckWayTestCollideEvent(to_x, to_y, self, other, self_conflict)) {
if (CheckOrMakeCollideEvent(other)) {
return false;
}
}
auto& player = Main_Data::game_player;
if (player->GetVehicleType() == Game_Vehicle::None) {
if (CheckWayTestCollideEvent(to_x, to_y, self, *Main_Data::game_player, self_conflict)) {
if (CheckOrMakeCollideEvent(*Main_Data::game_player)) {
return false;
}
}
for (auto vid: { Game_Vehicle::Boat, Game_Vehicle::Ship}) {
auto& other = vehicles[vid - 1];
if (other.IsInCurrentMap()) {
if (CheckWayTestCollideEvent(to_x, to_y, self, other, self_conflict)) {
if (CheckOrMakeCollideEvent(other)) {
return false;
}
}
}
auto& airship = vehicles[Game_Vehicle::Airship - 1];
if (airship.IsInCurrentMap() && self.GetType() != Game_Character::Player) {
if (CheckWayTestCollideEvent(to_x, to_y, self, airship, self_conflict)) {
if (CheckOrMakeCollideEvent(airship)) {
return false;
}
}
Expand All @@ -698,7 +700,7 @@ bool Game_Map::CheckWayEx(const Game_Character& self,
}

return IsPassableTile(
&self, bit, to_x, to_y, !ignore_events_and_vehicles, true
&self, bit, to_x, to_y, check_events_and_vehicles, true
);
}

Expand All @@ -707,52 +709,12 @@ bool Game_Map::MakeWay(const Game_Character& self,
int to_x, int to_y
)
{
// First, check basic passability but ignoring all events:
int bit_from, bit_to;
bool self_conflict;
if (!CheckWayEx(self, from_x, from_y, to_x, to_y, true, NULL,
&bit_from, &bit_to,
&to_x, &to_y, &self_conflict))
return false;

const auto vehicle_type = GetCollisionVehicleType(&self);
if (vehicle_type != Game_Vehicle::Airship) {
// Check for collision with events on the target tile.
for (auto& other: GetEvents()) {
if (MakeWayCollideEvent(to_x, to_y, self, other, self_conflict)) {
return false;
}
}
auto& player = Main_Data::game_player;
if (player->GetVehicleType() == Game_Vehicle::None) {
if (MakeWayCollideEvent(to_x, to_y, self, *Main_Data::game_player, self_conflict)) {
return false;
}
}
for (auto vid: { Game_Vehicle::Boat, Game_Vehicle::Ship}) {
auto& other = vehicles[vid - 1];
if (other.IsInCurrentMap()) {
if (MakeWayCollideEvent(to_x, to_y, self, other, self_conflict)) {
return false;
}
}
}
auto& airship = vehicles[Game_Vehicle::Airship - 1];
if (airship.IsInCurrentMap() && self.GetType() != Game_Character::Player) {
if (MakeWayCollideEvent(to_x, to_y, self, airship, self_conflict)) {
return false;
}
}
}

int bit = bit_to;
if (self.IsJumping()) {
bit = Passable::Down | Passable::Up | Passable::Left | Passable::Right;
}

return IsPassableTile(&self, bit, to_x, to_y, true, false);
return CheckOrMakeWayEx(
self, from_x, from_y, to_x, to_y, true, NULL, true
);
}


bool Game_Map::CanLandAirship(int x, int y) {
if (!Game_Map::IsValid(x, y)) return false;

Expand Down
65 changes: 32 additions & 33 deletions src/game_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,49 +210,48 @@ namespace Game_Map {
* @param from_y from tile y.
* @param to_x to new tile x.
* @param to_y to new tile y.
* @param check_events_and_events (Optional) Whether to check
* events, or only consider map collision.
* @param ignore_some_events_by_id (Optional) A set of
* specific event IDs to ignore.
* @return whether move is possible.
*/
bool CheckWay(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y,
bool check_events_and_vehicles,
std::unordered_set<int> *ignore_some_events_by_id);

/** Shorter version of CheckWay. */
bool CheckWay(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y);

/**
* Extended function of CheckWay that spits out some
* additional computed values for use in MakeWay.
*
* @param self See CheckWay.
* @param from_x See CheckWay.
* @param from_y See CheckWay.
* @param to_x See CheckWay.
* @param to_y See CheckWay.
* @param ignore_events_and_vehicles Whether to ignore
* all events and vehicles and only check map geometry.
* @param ignore_some_events_by_id Ignore some specific
* events by ID.
* @param out_bit_from Outputs bitmap mask for passability.
* @param out_bit_to Outputs bitmap mask for passability.
* @param out_to_x Target pos adjusted for map repeat.
* @param out_to_y Target pos adjusted for map repeat.
* @param out_self_conflict Outputs whether the moving self
* has a tile graphic that conflicts with the movement
* direction.
* @return See CheckWay.
*/
bool CheckWayEx(const Game_Character& self,
* Extended function behind MakeWay and CheckWay
* that allows controlling exactly which events are
* ignored in the collision, and whether events should
* be prompted to make way with side effects (for MakeWay)
* or not (for CheckWay).
*
* @param self See CheckWay or MakeWay.
* @param from_x See CheckWay or MakeWay.
* @param from_y See CheckWay or MakeWay.
* @param to_x See CheckWay or MakeWay.
* @param to_y See CheckWay or MakeWay.
* @param check_events_and_vehicles whether to check
* events, or only consider map collision.
* @param make_way Whether to cause side effects.
* @param ignore_some_events_by_id A set of
* specific event IDs to ignore.
* @return See CheckWay or MakeWay.
*/
bool CheckOrMakeWayEx(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y,
bool ignore_events_and_vehicles,
bool check_events_and_vehicles,
std::unordered_set<int> *ignore_some_events_by_id,
int *out_bit_from,
int *out_bit_to,
int *out_to_x,
int *out_to_y,
bool *out_self_conflict);
bool CheckWayEx(const Game_Character& self,
int from_x, int from_y,
int to_x, int to_y,
bool ignore_all_events,
std::unordered_set<int> *ignore_some_events_by_id);
bool make_way);

/**
* Gets if possible to land the airship at (x,y)
Expand Down
Loading