diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index ad2b61074d..04f298c492 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -1501,6 +1501,12 @@ bool Game_Interpreter::CommandChangeActorFace(RPG::EventCommand const& com) { // bool Game_Interpreter::CommandChangeVehicleGraphic(RPG::EventCommand const& com) { // code 10650 Game_Vehicle::Type vehicle_id = (Game_Vehicle::Type) (com.parameters[0] + 1); Game_Vehicle* vehicle = Game_Map::GetVehicle(vehicle_id); + + if (!vehicle) { + Output::Warning("ChangeVehicleGraphic: Invalid vehicle ID %d", vehicle_id); + return true; + } + const std::string& name = com.string; int vehicle_index = com.parameters[1]; @@ -1575,11 +1581,40 @@ bool Game_Interpreter::CommandMemorizeLocation(RPG::EventCommand const& com) { / bool Game_Interpreter::CommandSetVehicleLocation(RPG::EventCommand const& com) { // code 10850 Game_Vehicle::Type vehicle_id = (Game_Vehicle::Type) (com.parameters[0] + 1); Game_Vehicle* vehicle = Game_Map::GetVehicle(vehicle_id); + + if (!vehicle) { + // SetVehicleLocation moves the party, too, when she is in the referenced + // vehicle. In RPG_RT a party that is in no vehicle has the vehicle_id -1. + // Due to this implementation detail passing -1 as vehicle_id will move the + // party instead. + if (vehicle_id == 0) { + // 0 because we adjust all vehicle IDs by +1 to match the lcf values + Output::Debug("SetVehicleLocation: Party referenced"); + } else { + Output::Warning("SetVehicleLocation: Invalid vehicle ID %d", vehicle_id); + return true; + } + } + int map_id = ValueOrVariable(com.parameters[1], com.parameters[2]); int x = ValueOrVariable(com.parameters[1], com.parameters[3]); int y = ValueOrVariable(com.parameters[1], com.parameters[4]); - vehicle->SetPosition(map_id, x, y); + // Check if the party is in the current vehicle + if (Main_Data::game_player->GetVehicle() == vehicle) { + if (map_id != Game_Map::GetMapId()) { + Output::Warning("SetVehicleLocation: Can't move %s to new map %d while the party is boarded.", + Game_Vehicle::TypeNames[vehicle_id], map_id); + return true; + } + + // Transfer the party together with the vehicle + Main_Data::game_player->MoveTo(x, y); + } + + if (vehicle) { + vehicle->SetPosition(map_id, x, y); + } return true; } @@ -2300,10 +2335,19 @@ bool Game_Interpreter::CommandConditionalBranch(RPG::EventCommand const& com) { result = character->GetSpriteDirection() == com.parameters[2]; } break; - case 7: + case 7: { // Vehicle in use - result = Game_Map::GetVehicle((Game_Vehicle::Type) (com.parameters[1] + 1))->IsInUse(); + Game_Vehicle::Type vehicle_id = (Game_Vehicle::Type) (com.parameters[1] + 1); + Game_Vehicle* vehicle = Game_Map::GetVehicle(vehicle_id); + + if (!vehicle) { + Output::Warning("ConditionalBranch: Invalid vehicle ID %d", vehicle_id); + return true; + } + + result = vehicle->IsInUse(); break; + } case 8: // Key decision initiated this event result = triggered_by_decision_key; diff --git a/src/game_map.cpp b/src/game_map.cpp index 99a3e7085d..94ac3a8080 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -1150,10 +1150,13 @@ void Game_Map::SetChipset(int id) { } Game_Vehicle* Game_Map::GetVehicle(Game_Vehicle::Type which) { - if (which == Game_Vehicle::None) { - return NULL; + if (which == Game_Vehicle::Boat || + which == Game_Vehicle::Ship || + which == Game_Vehicle::Airship) { + return vehicles[which - 1].get(); } - return vehicles[which - 1].get(); + + return nullptr; } bool Game_Map::IsAnyEventStarting() { diff --git a/src/game_vehicle.cpp b/src/game_vehicle.cpp index da3aedeeff..fbe3c1aac1 100644 --- a/src/game_vehicle.cpp +++ b/src/game_vehicle.cpp @@ -25,6 +25,13 @@ #include "game_vehicle.h" #include "output.h" +const char Game_Vehicle::TypeNames[4][8] { + "Party", // RPG_RT special case, see CommandSetVehicleLocation + "Boat", + "Ship", + "Airship" +}; + Game_Vehicle::Game_Vehicle(Type _type) : data(_type == Boat ? Main_Data::game_data.boat_location : _type == Ship ? Main_Data::game_data.ship_location : diff --git a/src/game_vehicle.h b/src/game_vehicle.h index 55e5b41858..c3bb8b6528 100644 --- a/src/game_vehicle.h +++ b/src/game_vehicle.h @@ -36,6 +36,8 @@ class Game_Vehicle : public Game_Character { Airship }; + static const char TypeNames[4][8]; + Game_Vehicle(Type _type); /** diff --git a/src/message_overlay.cpp b/src/message_overlay.cpp index c1a056bfce..3c0cd309b4 100644 --- a/src/message_overlay.cpp +++ b/src/message_overlay.cpp @@ -92,6 +92,7 @@ void MessageOverlay::AddMessage(const std::string& message, Color color) { if (message == last_message) { // The message matches the previous message -> increase counter messages.back().repeat_count++; + messages.back().hidden = false; // Keep the old message (with a new counter) on the screen counter = 0; diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 414ae38c8e..cc71f73b9f 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -88,9 +88,14 @@ void Spriteset_Map::Update() { std::string name = Game_Map::Parallax::GetName(); if (name != panorama_name) { panorama_name = name; - FileRequestAsync* request = AsyncHandler::RequestFile("Panorama", panorama_name); - panorama_request_id = request->Bind(&Spriteset_Map::OnPanoramaSpriteReady, this); - request->Start(); + if (name.empty()) { + panorama->SetBitmap(BitmapRef()); + tilemap->SetFastBlitDown(true); + } else { + FileRequestAsync *request = AsyncHandler::RequestFile("Panorama", panorama_name); + panorama_request_id = request->Bind(&Spriteset_Map::OnPanoramaSpriteReady, this); + request->Start(); + } } panorama->SetOx(Game_Map::Parallax::GetX()); panorama->SetOy(Game_Map::Parallax::GetY());