Beispiel #1
0
bool Game_Map::AirshipLandOk(int const x, int const y) {
	const RPG::Terrain* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x, y));
	if (!terrain) {
		Output::Warning("AirshipLandOk: Invalid terrain at (%d, %d)", x, y);
		return false;
	}

	return terrain->airship_land;
}
Beispiel #2
0
int Game_Map::GetBushDepth(int x, int y) {
	if (!Game_Map::IsValid(x, y)) return 0;

	const RPG::Terrain* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x,y));
	if (!terrain) {
		Output::Warning("GetBushDepth: Invalid terrain at (%d, %d)", x, y);
		return 0;
	}
	return terrain->bush_depth;
}
Beispiel #3
0
bool Game_Map::IsPassableVehicle(int x, int y, Game_Vehicle::Type vehicle_type) {
	if (!Game_Map::IsValid(x, y)) return false;

	const RPG::Terrain* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x, y));
	if (!terrain) {
		Output::Warning("IsPassableVehicle: Invalid terrain at (%d, %d)", x, y);
	} else if (vehicle_type == Game_Vehicle::Boat) {
		if (!terrain->boat_pass)
			return false;
	} else if (vehicle_type == Game_Vehicle::Ship) {
		if (!terrain->ship_pass)
			return false;
	} else if (vehicle_type == Game_Vehicle::Airship) {
		return terrain->airship_pass;
	}

	int tile_id;
	std::vector<Game_Event*> events;
	std::vector<Game_Event*>::iterator it;

	Game_Map::GetEventsXY(events, x, y);
	for (it = events.begin(); it != events.end(); ++it) {
		if ((*it)->GetThrough()) {
			continue;
		} else if ((*it)->GetLayer() == 1) {
			return false;
		} else if ((*it)->GetTileId() > 0 && (*it)->GetLayer() == RPG::EventPage::Layers_below) {
			// Event layer Chipset Tile
			tile_id = (*it)->GetTileId();
			if ((passages_up[tile_id] & Passable::Above) == 0)
				return false;
		}
	}

	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::Above) == 0)
		return false;

	for (int i = 0; i < 3; i++) {
		if (i+1 == vehicle_type)
			continue;
		Game_Vehicle* vehicle = vehicles[i].get();
		if (vehicle->IsInCurrentMap() && vehicle->IsInPosition(x, y) && !vehicle->GetThrough())
			return false;
	}

	return true;
}
Beispiel #4
0
void Game_Map::SetupBattle() {
	int x = Main_Data::game_player->GetX();
	int y = Main_Data::game_player->GetY();

	Game_Battle::SetTerrainId(GetTerrainTag(x, y));
	Game_Temp::battle_escape_mode = -1;

	int current_index = GetMapIndex(location.map_id);
	while (Data::treemap.maps[current_index].background_type == 0 && GetMapIndex(Data::treemap.maps[current_index].parent_map) != current_index) {
		current_index = GetMapIndex(Data::treemap.maps[current_index].parent_map);
	}
	if (Data::treemap.maps[current_index].background_type == 2) {
		Game_Temp::battle_background = Data::treemap.maps[current_index].background_name;
	}
}
Beispiel #5
0
std::vector<int> Game_Map::GetEncountersAt(int x, int y) {
	int terrain_tag = GetTerrainTag(Main_Data::game_player->GetX(), Main_Data::game_player->GetY());

	std::function<bool(int)> is_acceptable = [=](int troop_id) {
		const RPG::Troop* troop = ReaderUtil::GetElement(Data::troops, troop_id);
		if (!troop) {
			Output::Warning("GetEncountersAt: Invalid troop ID %d in encounter list", troop_id);
			return false;
		}

		const std::vector<bool>& terrain_set = troop->terrain_set;

		// RPG_RT optimisation: Omitted entries are the default value (true)
		return terrain_set.size() <= (unsigned)(terrain_tag - 1) ||
				terrain_set[terrain_tag - 1];
	};

	std::vector<int> out;

	for (unsigned int i = 0; i < Data::treemap.maps.size(); ++i) {
		RPG::MapInfo& map = Data::treemap.maps[i];

		if (map.ID == location.map_id) {
			for (const RPG::Encounter& enc : map.encounters) {
				if (is_acceptable(enc.troop_id)) {
					out.push_back(enc.troop_id);
				}
			}
		} else if (map.parent_map == location.map_id && map.type == RPG::TreeMap::MapType_area) {
			// Area
			Rect area_rect(map.area_rect.l, map.area_rect.t, map.area_rect.r - map.area_rect.l, map.area_rect.b - map.area_rect.t);
			Rect player_rect(x, y, 1, 1);

			if (!player_rect.IsOutOfBounds(area_rect)) {
				for (const RPG::Encounter& enc : map.encounters) {
					if (is_acceptable(enc.troop_id)) {
						out.push_back(enc.troop_id);
					}
				}
			}
		}
	}

	return out;
}
Beispiel #6
0
void Game_Map::UpdateEncounterSteps() {
	if (Player::debug_flag &&
		Input::IsPressed(Input::DEBUG_THROUGH)) {
			return;
	}

	int x = Main_Data::game_player->GetX();
	int y = Main_Data::game_player->GetY();
	int terrain_id = GetTerrainTag(x, y);
	const RPG::Terrain& terrain = Data::terrains[terrain_id - 1];

	location.encounter_steps -= terrain.encounter_rate;

	if (location.encounter_steps <= 0) {
		ResetEncounterSteps();
		PrepareEncounter();
	}
}
Beispiel #7
0
bool Game_Map::CanLandAirship(int x, int y) {
	if (!Game_Map::IsValid(x, y)) return false;

	const auto* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x, y));
	if (!terrain) {
		Output::Warning("CanLandAirship: Invalid terrain at (%d, %d)", x, y);
		return false;
	}
	if (!terrain->airship_land) {
		return false;
	}

	for (auto& ev: events) {
		if (ev.IsInPosition(x, y)
				&& ev.IsActive()
				&& ev.GetActivePage() != nullptr) {
			return false;
		}
	}
	for (auto vid: { Game_Vehicle::Boat, Game_Vehicle::Ship }) {
		auto& vehicle = vehicles[vid - 1];
		if (vehicle->IsInCurrentMap() && vehicle->IsInPosition(x, y)) {
			return false;
		}
	}

	const int bit = Passable::Down | Passable::Right | Passable::Left | Passable::Up;

	int tile_index = x + y * GetWidth();

	if (!IsPassableLowerTile(bit, tile_index)) {
		return false;
	}

	int tile_id = map->upper_layer[tile_index] - BLOCK_F;
	tile_id = map_info.upper_tiles[tile_id];

	return (passages_up[tile_id] & bit) != 0;
}
Beispiel #8
0
bool Game_Map::AirshipLandOk(int const x, int const y) {
	return Data::data.terrains[GetTerrainTag(x, y) -1].airship_land;
}
Beispiel #9
0
int Game_Map::GetBushDepth(int x, int y) {
	return Data::data.terrains[GetTerrainTag(x,y) - 1].bush_depth;
}
Beispiel #10
0
void Game_Map::UpdateEncounterSteps() {
	if (Player::debug_flag &&
		Input::IsPressed(Input::DEBUG_THROUGH)) {
			return;
	}

	if(Main_Data::game_player->InAirship()) {
		return;
	}

	if (GetEncounterRate() <= 0) {
		location.encounter_steps = 0;
		return;
	}

	int x = Main_Data::game_player->GetX();
	int y = Main_Data::game_player->GetY();

	const RPG::Terrain* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x,y));
	if (!terrain) {
		Output::Warning("UpdateEncounterSteps: Invalid terrain at (%d, %d)", x, y);
		return;
	}

	location.encounter_steps += terrain->encounter_rate;

	struct Row {
		int ratio;
		float pmod;
	};

#if 1
	static constexpr Row enc_table[] = {
		{ 0, 0.0625},
		{ 20, 0.125 },
		{ 40, 0.25 },
		{ 60, 0.5 },
		{ 100, 2.0 },
		{ 140, 4.0 },
		{ 160, 8.0 },
		{ 180, 16.0 },
		{ INT_MAX, 16.0 }
	};
#else
	//Old versions of RM2k used this table.
	//Left here for posterity.
	static constexpr Row enc_table[] = {
		{ 0, 0.5 },
		{ 20, 2.0 / 3.0 },
		{ 50, 5.0 / 6.0 },
		{ 100, 6.0 / 5.0 },
		{ 200, 3.0 / 2.0 },
		{ INT_MAX, 3.0 / 2.0 }
	};
#endif
	const auto encounter_rate = GetEncounterRate();
	const auto ratio = location.encounter_steps / encounter_rate;

	auto& idx = last_encounter_idx;
	while (ratio > enc_table[idx+1].ratio) {
		++idx;
	}
	const auto& row = enc_table[idx];

	const auto pmod = row.pmod;
	const auto p = (1.0f / float(encounter_rate)) * pmod * (float(terrain->encounter_rate) / 100.0f);

	if (Utils::PercentChance(p)) {
		SetEncounterSteps(0);
		PrepareEncounter();
	}
}
Beispiel #11
0
bool Game_Map::IsPassableTile(const Game_Character* self, int bit, int x, int y) {
	if (!IsValid(x, y)) return false;

	auto vehicle_type = (self != nullptr)
		? self->GetVehicleType() : Game_Vehicle::None;

	if (vehicle_type != Game_Vehicle::None) {
		const auto* terrain = ReaderUtil::GetElement(Data::terrains, GetTerrainTag(x, y));
		if (!terrain) {
			Output::Warning("IsPassableTile: Invalid terrain at (%d, %d)", x, y);
			return false;
		}
		if (vehicle_type == Game_Vehicle::Boat && !terrain->boat_pass) {
			return false;
		}
		if (vehicle_type == Game_Vehicle::Ship && !terrain->ship_pass) {
			return false;
		}
		if (vehicle_type == Game_Vehicle::Airship) {
			return terrain->airship_pass;
		}
	}

	// Highest ID event with layer=below, not through, and a tile graphic wins.
	int event_tile_id = 0;
	for (auto& ev: events) {
		if (self == &ev) {
			continue;
		}
		if (!ev.IsActive() || ev.GetThrough()) {
			continue;
		}
		if (ev.IsInPosition(x, y) && ev.GetLayer() == RPG::EventPage::Layers_below) {
			int tile_id = ev.GetTileId();
			if (tile_id > 0) {
				event_tile_id = tile_id;
			}
		}
	}

	// If there was a below tile event, and the tile is not above
	// Override the chipset with event tile behavior.
	if (event_tile_id > 0
			&& ((passages_up[event_tile_id] & Passable::Above) == 0)) {
		switch (vehicle_type) {
			case Game_Vehicle::None:
				return ((passages_up[event_tile_id] & bit) != 0);
			case Game_Vehicle::Boat:
			case Game_Vehicle::Ship:
				return false;
			case Game_Vehicle::Airship:
				break;
		};
	}

	int tile_index = x + y * GetWidth();
	int tile_id = map->upper_layer[tile_index] - BLOCK_F;
	tile_id = map_info.upper_tiles[tile_id];

	if (vehicle_type == Game_Vehicle::Boat || vehicle_type == Game_Vehicle::Ship) {
		if ((passages_up[tile_id] & Passable::Above) == 0)
			return false;
		return true;
	}

	if ((passages_up[tile_id] & bit) == 0)
		return false;

	if ((passages_up[tile_id] & Passable::Above) == 0)
		return true;

	return IsPassableLowerTile(bit, tile_index);
}