BattleAnimation::BattleAnimation(const RPG::Animation& anim) : animation(anim), frame(0), z(1500), frame_update(false), large(false) { const std::string& name = animation.animation_name; BitmapRef graphic; if (name.empty()) return; // Emscripten handled special here because of the FileFinder checks // Filefinder is not reliable for Emscripten because the files must be // downloaded first. // And we can't rely on "success" state of FileRequest because it's always // true on desktop. #ifdef EMSCRIPTEN FileRequestAsync* request = AsyncHandler::RequestFile("Battle", animation.animation_name); request_id = request->Bind(&BattleAnimation::OnBattleSpriteReady, this); request->Start(); #else if (!FileFinder::FindImage("Battle", name).empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Battle", animation.animation_name); request_id = request->Bind(&BattleAnimation::OnBattleSpriteReady, this); request->Start(); } else if (!FileFinder::FindImage("Battle2", name).empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Battle2", animation.animation_name); request_id = request->Bind(&BattleAnimation::OnBattle2SpriteReady, this); request->Start(); } else { Output::Warning("Couldn't find animation: %s", name.c_str()); } #endif }
void Sprite_Battler::CreateSprite() { sprite_name = battler->GetSpriteName(); hue = battler->GetHue(); SetX(battler->GetBattleX()); SetY(battler->GetBattleY()); SetZ(battler->GetBattleY()); // Not a typo // Not animated -> Monster if (battler->GetBattleAnimationId() == 0) { if (sprite_name.empty()) { graphic = Bitmap::Create(0, 0); SetOx(graphic->GetWidth() / 2); SetOy(graphic->GetHeight() / 2); SetBitmap(graphic); } else { FileRequestAsync* request = AsyncHandler::RequestFile("Monster", sprite_name); request_id = request->Bind(&Sprite_Battler::OnMonsterSpriteReady, this); request->Start(); } } else { // animated SetOx(24); SetOy(24); SetAnimationState(anim_state); idling = true; } SetVisible(!battler->IsHidden()); }
void Window_Base::DrawFace(const std::string& face_name, int face_index, int cx, int cy, bool flip) { if (face_name.empty()) { return; } FileRequestAsync* request = AsyncHandler::RequestFile("FaceSet", face_name); face_request_ids.push_back(request->Bind(&Window_Base::OnFaceReady, this, face_index, cx, cy, flip)); request->Start(); }
void Game_System::BgmPlay(RPG::Music const& bgm) { RPG::Music previous_music = data.current_music; data.current_music = bgm; // (OFF) means play nothing // A Polish RPG Maker translation overtranslated the (OFF) reserved string. // This particular translation uses (Brak) in editor for these cases. // Because RPG_RT doesn't show warnings about audios not found, // theses strings are ignored to prevent filling the log. // Though RPG_RT plays files named (Brak) is still preferred to ignore it. if (!bgm.name.empty() && bgm.name != "(OFF)" && bgm.name != "(Brak)") { // Same music: Only adjust volume and speed if (previous_music.name == bgm.name) { if (previous_music.volume != bgm.volume) { if (!bgm_pending) { // Delay if not ready Audio().BGM_Volume(bgm.volume); } } if (previous_music.tempo != bgm.tempo) { if (!bgm_pending) { // Delay if not ready Audio().BGM_Pitch(bgm.tempo); } } } else { Audio().BGM_Stop(); bgm_pending = true; FileRequestAsync* request = AsyncHandler::RequestFile("Music", bgm.name); request->Bind(&Game_System::OnBgmReady); request->Start(); } } else { BgmStop(); } }
void Game_Picture::RequestPictureSprite() { const std::string& name = GetData().name; if (name.empty()) return; FileRequestAsync* request = AsyncHandler::RequestFile("Picture", name); request_id = request->Bind(&Game_Picture::OnPictureSpriteReady, this); request->Start(); }
void Scene_Battle_Rpg2k3::CreateCursors() { ally_cursor.reset(new Sprite()); enemy_cursor.reset(new Sprite()); FileRequestAsync* request = AsyncHandler::RequestFile("System2", Data::system.system2_name); request->Bind(&Scene_Battle_Rpg2k3::OnSystem2Ready, this); request->Start(); }
void Window_BattleStatus::RefreshGauge() { if (Player::IsRPG2k3()) { if (Data::battlecommands.battle_type != RPG::BattleCommands::BattleType_gauge) { contents->ClearRect(Rect(198, 0, 25 + 16, 15 * item_max)); } for (int i = 0; i < item_max; ++i) { Game_Battler* actor; if (enemy) { actor = &(*Main_Data::game_enemyparty)[i]; } else { actor = &(*Main_Data::game_party)[i]; } if (!enemy && Data::battlecommands.battle_type == RPG::BattleCommands::BattleType_gauge) { FileRequestAsync* request = AsyncHandler::RequestFile("System2", Data::system.system2_name); if (!request->IsReady()) { request_id = request->Bind(&Window_BattleStatus::OnSystem2Ready, this); request->Start(); break; } else { BitmapRef system2 = Cache::System2(Data::system.system2_name); // Clear number drawing area contents->ClearRect(Rect(40 + 80 * i, 24, 8 * 4, 16)); contents->ClearRect(Rect(40 + 80 * i, 24 + 12 + 4, 8 * 4, 16)); // Number clearing removed part of the face, but both, clear and redraw // are needed because some games don't have face graphics that are huge enough // to clear the number area (e.g. Ara Fell) DrawActorFace(static_cast<Game_Actor*>(actor), 80 * i, 24); // Background contents->StretchBlit(Rect(32 + i * 80, 24, 57, 48), *system2, Rect(0, 32, 48, 48), Opacity::opaque); // HP DrawGaugeSystem2(48 + i * 80, 24, actor->GetHp(), actor->GetMaxHp(), 0); // SP DrawGaugeSystem2(48 + i * 80, 24 + 16, actor->GetSp(), actor->GetMaxSp(), 1); // Gauge DrawGaugeSystem2(48 + i * 80, 24 + 16 * 2, actor->GetGauge() * actor->GetMaxGauge() / 100, actor->GetMaxGauge(), 2); // Numbers DrawNumberSystem2(40 + 80 * i, 24, actor->GetHp()); DrawNumberSystem2(40 + 80 * i, 24 + 12 + 4, actor->GetSp()); } } else { int y = 2 + i * 16; DrawGauge(actor, 198 - 10, y - 2); DrawActorSp(actor, 198, y, false); } } } }
void Scene_Gameover::Start() { if (!Data::system.gameover_name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("GameOver", Data::system.gameover_name); request_id = request->Bind(&Scene_Gameover::OnBackgroundReady, this); request->Start(); } // Play gameover music Game_System::BgmPlay(Game_System::GetSystemBGM(Game_System::BGM_GameOver)); }
Frame::Frame() { if (!Data::system.frame_name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Frame", Data::system.frame_name); request_id = request->Bind(&Frame::OnFrameGraphicReady, this); request->Start(); } Graphics::RegisterDrawable(this); }
void Scene_Title::CreateTitleGraphic() { // Load Title Graphic if (!title && !Data::system.title_name.empty()) // No need to recreate Title on Resume { title.reset(new Sprite()); FileRequestAsync* request = AsyncHandler::RequestFile("Title", Data::system.title_name); request->Bind(&Scene_Title::OnTitleSpriteReady, this); request->Start(); } }
void BattleAnimation::OnBattleSpriteReady(FileRequestResult* result) { if (result->success) { screen = Cache::Battle(result->file); } else { // Try battle2 FileRequestAsync* request = AsyncHandler::RequestFile("Battle2", result->file); request->Bind(&BattleAnimation::OnBattle2SpriteReady, this); request->Start(); } }
void Spriteset_Map::ChipsetUpdated() { if (!Game_Map::GetChipsetName().empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("ChipSet", Game_Map::GetChipsetName()); tilemap_request_id = request->Bind(&Spriteset_Map::OnTilemapSpriteReady, this); request->SetImportantFile(true); request->SetGraphicFile(true); request->Start(); } else { OnTilemapSpriteReady(NULL); } }
void Game_System::SePlay(RPG::Sound const& se) { if (!se.name.empty() && se.name != "(OFF)" && se.name != "(Brak)") { // Yume Nikki plays hundreds of sound effects at 0% volume on // startup. Probably for caching. This triggers "No free channels" // warnings. if (se.volume > 0) { FileRequestAsync* request = AsyncHandler::RequestFile("Sound", se.name); request->Bind(boost::bind(&Game_System::OnSeReady, _1, se.volume, se.tempo)); request->Start(); } } }
void BattleAnimation::OnBattleSpriteReady(FileRequestResult* result) { if (result->success) { sprite.reset(new Sprite()); sprite->SetBitmap(Cache::Battle(result->file)); sprite->SetSrcRect(Rect(0, 0, 0, 0)); } else { // Try battle2 FileRequestAsync* request = AsyncHandler::RequestFile("Battle2", result->file); request_id = request->Bind(&BattleAnimation::OnBattle2SpriteReady, this); request->Start(); } }
// Update void Spriteset_Map::Update() { Tone new_tone = Main_Data::game_screen->GetTone(); tilemap->SetOx(Game_Map::GetDisplayX() / (SCREEN_TILE_SIZE / TILE_SIZE)); tilemap->SetOy(Game_Map::GetDisplayY() / (SCREEN_TILE_SIZE / TILE_SIZE)); tilemap->SetTone(new_tone); tilemap->Update(); for (size_t i = 0; i < character_sprites.size(); i++) { character_sprites[i]->Update(); character_sprites[i]->SetTone(new_tone); } std::string name = Game_Map::Parallax::GetName(); if (name != panorama_name) { panorama_name = name; if (name.empty()) { panorama->SetBitmap(BitmapRef()); tilemap->SetFastBlitDown(true); } else { FileRequestAsync *request = AsyncHandler::RequestFile("Panorama", panorama_name); request->SetGraphicFile(true); panorama_request_id = request->Bind(&Spriteset_Map::OnPanoramaSpriteReady, this); request->Start(); } } panorama->SetOx(Game_Map::Parallax::GetX()); panorama->SetOy(Game_Map::Parallax::GetY()); panorama->SetTone(new_tone); Game_Vehicle* vehicle; int map_id = Game_Map::GetMapId(); for (int i = 1; i <= 3; ++i) { vehicle = Game_Map::GetVehicle((Game_Vehicle::Type) i); if (!vehicle_loaded[i - 1] && vehicle->GetMapId() == map_id) { vehicle_loaded[i - 1] = true; CreateSprite(vehicle, need_x_clone, need_y_clone); } } for (auto& shadow : airship_shadows) { shadow->SetTone(new_tone); shadow->Update(); } timer1->Update(); timer2->Update(); weather->SetTone(new_tone); }
void Game_System::BgmPlay(RPG::Music const& bgm) { RPG::Music previous_music = data.current_music; data.current_music = bgm; // Validate if (bgm.volume < 0 || bgm.volume > 100) { data.current_music.volume = 100; Output::Debug("BGM %s has invalid volume %d", bgm.name.c_str(), bgm.volume); } if (bgm.fadein < 0 || bgm.fadein > 10000) { data.current_music.fadein = 0; Output::Debug("BGM %s has invalid fadein %d", bgm.name.c_str(), bgm.fadein); } if (bgm.tempo < 50 || bgm.tempo > 200) { data.current_music.tempo = 100; Output::Debug("BGM %s has invalid tempo %d", bgm.name.c_str(), bgm.tempo); } // (OFF) means play nothing if (!bgm.name.empty() && bgm.name != "(OFF)") { // Same music: Only adjust volume and speed if (!force_bgm_play && previous_music.name == bgm.name) { if (previous_music.volume != data.current_music.volume) { if (!bgm_pending) { // Delay if not ready Audio().BGM_Volume(data.current_music.volume); } } if (previous_music.tempo != data.current_music.tempo) { if (!bgm_pending) { // Delay if not ready Audio().BGM_Pitch(data.current_music.tempo); } } } else { Audio().BGM_Stop(); bgm_pending = true; FileRequestAsync* request = AsyncHandler::RequestFile("Music", bgm.name); music_request_id = request->Bind(&Game_System::OnBgmReady); request->Start(); } } else { BgmStop(); } force_bgm_play = false; }
void Game_System::SePlay(const RPG::Sound& se, bool stop_sounds) { static bool ineluki_warning_shown = false; if (se.name.empty()) { return; } else if (se.name == "(OFF)") { if (stop_sounds) { Audio().SE_Stop(); } return; } std::string end = ".script"; if (se.name.length() >= end.length() && 0 == se.name.compare(se.name.length() - end.length(), end.length(), end)) { if (!ineluki_warning_shown) { Output::Warning("This game seems to use Ineluki's key patch to support " "additional keys, mouse or scripts. Such patches are " "unsupported, so this functionality will not work!"); ineluki_warning_shown = true; } return; } // NOTE: Yume Nikki plays hundreds of sound effects at 0% volume on startup, // probably for caching. This avoids "No free channels" warnings. if (se.volume == 0) return; int volume = se.volume; int tempo = se.tempo; // Validate if (se.volume < 0 || se.volume > 100) { Output::Debug("SE %s has invalid volume %d", se.name.c_str(), se.volume); volume = 100; } if (se.tempo < 50 || se.tempo > 200) { Output::Debug("SE %s has invalid tempo %d", se.name.c_str(), se.tempo); tempo = 100; } FileRequestAsync* request = AsyncHandler::RequestFile("Sound", se.name); se_request_ids[se.name] = request->Bind(std::bind(&Game_System::OnSeReady, std::placeholders::_1, volume, tempo, stop_sounds)); request->Start(); }
void BattleAnimation::OnBattleSpriteReady(FileRequestResult* result) { if (result->success) { //Normally only battle2 sprites are "large" sprites - but the check doesn't hurt. BitmapRef bitmap = Cache::Battle(result->file); if (bitmap->GetWidth() == 640) { large = true; } SetBitmap(bitmap); SetSrcRect(Rect(0, 0, 0, 0)); } else { // Try battle2 FileRequestAsync* request = AsyncHandler::RequestFile("Battle2", result->file); request_id = request->Bind(&BattleAnimation::OnBattle2SpriteReady, this); request->Start(); } }
Window_ShopParty::Window_ShopParty(int ix, int iy, int iwidth, int iheight) : Window_Base(ix, iy, iwidth, iheight) { SetContents(Bitmap::Create(width - 16, height - 16)); cycle = 0; item_id = 0; const std::vector<Game_Actor*>& actors = Main_Data::game_party->GetActors(); for (size_t i = 0; i < actors.size() && i < 4; i++) { const std::string& sprite_name = actors[i]->GetSpriteName(); FileRequestAsync* request = AsyncHandler::RequestFile("CharSet", sprite_name); request_ids.push_back(request->Bind(&Window_ShopParty::OnCharsetSpriteReady, this, (int)i)); request->Start(); } Refresh(); }
void Window_BattleStatus::Refresh() { contents->Clear(); if (enemy) { item_max = Main_Data::game_enemyparty->GetBattlerCount(); } else { item_max = Main_Data::game_party->GetBattlerCount(); } item_max = std::min(item_max, 4); for (int i = 0; i < item_max; i++) { Game_Battler* actor; if (enemy) { actor = &(*Main_Data::game_enemyparty)[i]; } else { actor = &(*Main_Data::game_party)[i]; } if (!enemy && Data::battlecommands.battle_type == RPG::BattleCommands::BattleType_gauge) { FileRequestAsync* request = AsyncHandler::RequestFile("System2", Data::system.system2_name); if (!request->IsReady()) { request_id = request->Bind(&Window_BattleStatus::OnSystem2Ready, this); request->Start(); break; } else { DrawActorFace(static_cast<Game_Actor*>(actor), 80 * i, 24); } } else { int y = 2 + i * 16; DrawActorName(actor, 4, y); DrawActorState(actor, 84, y); DrawActorHp(actor, 126, y, true); DrawActorSp(actor, 198, y, false); } } RefreshGauge(); }
void Sprite_Battler::SetAnimationState(int state, LoopState loop) { // Default value is 100 (function called with val+1) // 100 maps all states to "Bad state" (7) if (state == 101) { state = 7; } anim_state = state; flash_counter = 0; loop_state = loop; cycle = 0; idling = false; if (Player::IsRPG2k3()) { if (battler->GetBattleAnimationId() > 0) { const RPG::BattlerAnimation& anim = Data::battleranimations[battler->GetBattleAnimationId() - 1]; const RPG::BattlerAnimationExtension& ext = anim.base_data[anim_state - 1]; sprite_file = ext.battler_name; if (ext.animation_type == RPG::BattlerAnimationExtension::AnimType_animation) { SetBitmap(BitmapRef()); animation.reset(new BattleAnimationBattlers(Data::animations[ext.animation_id - 1], *battler)); animation->SetZ(GetZ()); } else { animation.reset(); if (!sprite_file.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("BattleCharSet", sprite_file); request_id = request->Bind(boost::bind(&Sprite_Battler::OnBattlercharsetReady, this, _1, ext.battler_index)); request->Start(); } } } } }
void Scene_Battle_Rpg2k3::CreateUi() { Scene_Battle::CreateUi(); CreateBattleTargetWindow(); CreateBattleCommandWindow(); // No escape. FIXME: Only enabled when party has initiative. options_window->DisableItem(2); enemy_status_window.reset(new Window_BattleStatus(0, 0, SCREEN_TARGET_WIDTH - 76, 80, true)); enemy_status_window->SetVisible(false); ally_cursor.reset(new Sprite()); enemy_cursor.reset(new Sprite()); if (Data::battlecommands.battle_type == RPG::BattleCommands::BattleType_gauge) { item_window->SetY(64); skill_window->SetY(64); // Default window too small for 4 actors status_window.reset(new Window_BattleStatus(0, SCREEN_TARGET_HEIGHT - 80, SCREEN_TARGET_WIDTH, 80)); } if (Data::battlecommands.battle_type != RPG::BattleCommands::BattleType_traditional) { int transp = Data::battlecommands.transparency == RPG::BattleCommands::Transparency_transparent ? 128 : 255; options_window->SetBackOpacity(transp); item_window->SetBackOpacity(transp); skill_window->SetBackOpacity(transp); help_window->SetBackOpacity(transp); status_window->SetBackOpacity(transp); enemy_status_window->SetBackOpacity(transp); } FileRequestAsync* request = AsyncHandler::RequestFile("System2", Data::system.system2_name); request->Bind(&Scene_Battle_Rpg2k3::OnSystem2Ready, this); request->Start(); }