bool Game_Character::IsPassable(int x, int y, int d) const { int new_x = x + (d == RPG::EventPage::Direction_right ? 1 : d == RPG::EventPage::Direction_left ? -1 : 0); int new_y = y + (d == RPG::EventPage::Direction_down ? 1 : d == RPG::EventPage::Direction_up ? -1 : 0); if (!Game_Map::IsValid(new_x, new_y)) return false; if (through) return true; if (!Game_Map::IsPassable(x, y, d, this)) return false; if (!Game_Map::IsPassable(new_x, new_y, (d + 2) % 4)) return false; for (tEventHash::iterator i = Game_Map::GetEvents().begin(); i != Game_Map::GetEvents().end(); i++) { Game_Event* evnt = i->second.get(); if (evnt->GetX() == new_x && evnt->GetY() == new_y) { if (!evnt->GetThrough() && evnt->GetPriorityType() == RPG::EventPage::Layers_same) { return false; } } } if (Main_Data::game_player->GetX() == new_x && Main_Data::game_player->GetY() == new_y) { if (!Main_Data::game_player->GetThrough() && !character_name.empty()) { return false; } } return true; }
/** * Checks whether a collision occurs between self and other if self * moves from (x,y) to (new_x, new_y) in direction d. * * If other is a tile event, also indicates if the player can use it * as a "bridge" to step across without hitting the underlying tile * layer. */ static CollisionResult TestCollisionDuringMove( int x, int y, int new_x, int new_y, int d, const Game_Character& self, const Game_Event& other ) { if (!other.GetActive()) { return NoCollision; } if (&self == &other) { return NoCollision; } if (other.GetThrough()) { return NoCollision; } if (!other.IsInPosition(x, y) && !other.IsInPosition(new_x, new_y)) { return NoCollision; } if (&self != Main_Data::game_player.get()) { if (other.IsInPosition(new_x, new_y) && (self.IsOverlapForbidden() || other.IsOverlapForbidden())) { return Collision; } } if (other.IsInPosition(new_x, new_y) && self.GetLayer() == other.GetLayer()) { return Collision; } if (other.GetLayer() == RPG::EventPage::Layers_below) { int tile_id = other.GetTileId(); if ((passages_up[tile_id] & Passable::Above) != 0) { return NoCollision; } if (other.IsInPosition(x,y) && (passages_up[tile_id] & DirToMask(d)) != 0) { return CanStepOffCurrentTile; } else if (other.IsInPosition(new_x, new_y) && (passages_up[tile_id] & DirToMask(Game_Character::ReverseDir(d))) != 0) { return CanStepOntoNewTile; } else { return Collision; } } return NoCollision; }
bool Game_Map::IsLandable(int x, int y, const Game_Character *self_event) { int tile_id; if (self_event) { for (tEventHash::iterator i = events.begin(); i != events.end(); ++i) { Game_Event* evnt = i->second.get(); if (evnt != self_event && evnt->GetX() == x && evnt->GetY() == y) { if (!evnt->GetThrough()) { if (evnt->GetLayer() == RPG::EventPage::Layers_same) { return false; } else if (evnt->GetTileId() >= 0 && evnt->GetLayer() == RPG::EventPage::Layers_below) { // Event layer Chipset Tile tile_id = i->second->GetTileId(); return (passages_up[tile_id] & Passable::Down || passages_up[tile_id] & Passable::Right || passages_up[tile_id] & Passable::Left || passages_up[tile_id] & Passable::Up); } } } } } int const tile_index = x + y * GetWidth(); tile_id = map->upper_layer[tile_index] - BLOCK_F; tile_id = map_info.upper_tiles[tile_id]; if ((passages_up[tile_id] & Passable::Down) == 0 && (passages_up[tile_id] & Passable::Right) == 0 && (passages_up[tile_id] & Passable::Left) == 0 && (passages_up[tile_id] & Passable::Up) == 0) { return false; } if ((passages_up[tile_id] & Passable::Above) == 0) return true; if (map->lower_layer[tile_index] >= BLOCK_E) { tile_id = map->lower_layer[tile_index] - BLOCK_E; tile_id = map_info.lower_tiles[tile_id]; tile_id += 18; if ((passages_down[tile_id] & Passable::Down) == 0 && (passages_down[tile_id] & Passable::Right) == 0 && (passages_down[tile_id] & Passable::Left) == 0 && (passages_down[tile_id] & Passable::Up) == 0) return false; } else if (map->lower_layer[tile_index] >= BLOCK_D) { tile_id = (map->lower_layer[tile_index] - BLOCK_D) / 50; int16_t autotile_id = map->lower_layer[tile_index] - BLOCK_D - tile_id * 50; tile_id += 6; if (((passages_down[tile_id] & Passable::Wall) != 0) && ( (autotile_id >= 20 && autotile_id <= 23) || (autotile_id >= 33 && autotile_id <= 37) || autotile_id == 42 || autotile_id == 43 || autotile_id == 45 )) return true; if ((passages_down[tile_id] & Passable::Down) == 0 && (passages_down[tile_id] & Passable::Right) == 0 && (passages_down[tile_id] & Passable::Left) == 0 && (passages_down[tile_id] & Passable::Up) == 0) return false; } else if (map->lower_layer[tile_index] >= BLOCK_C) { tile_id = (map->lower_layer[tile_index] - BLOCK_C) / 50 + 3; if ((passages_down[tile_id] & Passable::Down) == 0 && (passages_down[tile_id] & Passable::Right) == 0 && (passages_down[tile_id] & Passable::Left) == 0 && (passages_down[tile_id] & Passable::Up) == 0) return false; } else if (map->lower_layer[tile_index] < BLOCK_C) { tile_id = map->lower_layer[tile_index] / 1000; if ((passages_down[tile_id] & Passable::Down) == 0 && (passages_down[tile_id] & Passable::Right) == 0 && (passages_down[tile_id] & Passable::Left) == 0 && (passages_down[tile_id] & Passable::Up) == 0) return false; } return true; }
bool Game_Map::IsPassable(int x, int y, int d, const Game_Character* self_event) { if (!Game_Map::IsValid(x, y)) return false; uint8_t bit = 0; switch (d) { case RPG::EventPage::Direction_down: bit = Passable::Down; break; case RPG::EventPage::Direction_up: bit = Passable::Up; break; case RPG::EventPage::Direction_left: bit = Passable::Left; break; case RPG::EventPage::Direction_right: bit = Passable::Right; break; default: assert(false); } int tile_id; if (self_event) { bool pass = false; for (tEventHash::iterator i = events.begin(); i != events.end(); ++i) { Game_Event* evnt = i->second.get(); if (evnt != self_event && evnt->GetX() == x && evnt->GetY() == y) { if (!evnt->GetThrough()) { if (evnt->GetLayer() == self_event->GetLayer()) { if (self_event->GetX() == x && self_event->GetY() == y) pass = true; else return false; } else if (evnt->GetTileId() > 0 && evnt->GetLayer() == RPG::EventPage::Layers_below) { // Event layer Chipset Tile tile_id = evnt->GetTileId(); if ((passages_up[tile_id] & Passable::Above) != 0) if ((passages_down[tile_id] & bit) == 0) return false; if ((passages_up[tile_id] & bit) != 0) pass = true; else return false; } } } } if (pass) // All events here are passable return true; } int const tile_index = x + y * GetWidth(); tile_id = map->upper_layer[tile_index] - BLOCK_F; tile_id = map_info.upper_tiles[tile_id]; if ((passages_up[tile_id] & bit) == 0) { return false; } if ((passages_up[tile_id] & Passable::Above) == 0) return true; if (map->lower_layer[tile_index] >= BLOCK_E) { tile_id = map->lower_layer[tile_index] - BLOCK_E; tile_id = map_info.lower_tiles[tile_id]; tile_id += 18; if ((passages_down[tile_id] & bit) == 0) return false; } else if (map->lower_layer[tile_index] >= BLOCK_D) { tile_id = (map->lower_layer[tile_index] - BLOCK_D) / 50; int16_t autotile_id = map->lower_layer[tile_index] - BLOCK_D - tile_id * 50; tile_id += 6; if (((passages_down[tile_id] & Passable::Wall) != 0) && ( (autotile_id >= 20 && autotile_id <= 23) || (autotile_id >= 33 && autotile_id <= 37) || autotile_id == 42 || autotile_id == 43 || autotile_id == 45 )) return true; if ((passages_down[tile_id] & bit) == 0) return false; } else if (map->lower_layer[tile_index] >= BLOCK_C) { tile_id = (map->lower_layer[tile_index] - BLOCK_C) / 50 + 3; if ((passages_down[tile_id] & bit) == 0) return false; } else if (map->lower_layer[tile_index] < BLOCK_C) { tile_id = map->lower_layer[tile_index] / 1000; if ((passages_down[tile_id] & bit) == 0) return false; } return true; }