Created
February 20, 2013 20:46
-
-
Save MarianoGnu/4999469 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////// | |
// This file is part of EasyRPG Player. | |
// | |
// EasyRPG Player is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// | |
// EasyRPG Player is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details. | |
// | |
// You should have received a copy of the GNU General Public License | |
// along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>. | |
///////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////// | |
// Headers | |
//////////////////////////////////////////////////////////// | |
#include <algorithm> | |
#include <sstream> | |
#include "rpg_battlecommand.h" | |
#include "input.h" | |
#include "output.h" | |
#include "player.h" | |
#include "sprite.h" | |
#include "graphics.h" | |
#include "filefinder.h" | |
#include "cache.h" | |
#include "game_system.h" | |
#include "game_temp.h" | |
#include "game_party.h" | |
#include "game_enemy.h" | |
#include "game_switches.h" | |
#include "game_battle.h" | |
#include "battle_battler.h" | |
#include "battle_animation.h" | |
#include "battle_actions.h" | |
#include "scene_battle2k3.h" | |
#include "bitmap.h" | |
//////////////////////////////////////////////////////////// | |
Scene_Battle2k3::Scene_Battle2k3() { | |
Scene::type = Scene::Battle; | |
} | |
//////////////////////////////////////////////////////////// | |
Scene_Battle2k3::~Scene_Battle2k3() { | |
Game_Battle::Quit(); | |
} | |
//////////////////////////////////////////////////////////// | |
Scene_Battle2k3::FloatText::FloatText(int x, int y, int color, const std::string& text, int _duration) { | |
Rect rect = Font::Default()->GetSize(text); | |
BitmapRef graphic = Bitmap::Create(rect.width, rect.height); | |
graphic->Clear(); | |
graphic->TextDraw(-rect.x, -rect.y, color, text); | |
sprite.reset(new Sprite()); | |
sprite->SetBitmap(graphic); | |
sprite->SetOx(rect.width / 2); | |
sprite->SetOy(rect.height + 5); | |
sprite->SetX(x); | |
sprite->SetY(y); | |
sprite->SetZ(500+y); | |
duration = _duration; | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CreateCursors() { | |
BitmapRef system2 = Cache::System2(Data::system.system2_name); | |
ally_cursor.reset(new Sprite()); | |
ally_cursor->SetBitmap(system2); | |
ally_cursor->SetSrcRect(Rect(0, 16, 16, 16)); | |
ally_cursor->SetZ(999); | |
ally_cursor->SetVisible(false); | |
enemy_cursor.reset(new Sprite()); | |
enemy_cursor->SetBitmap(system2); | |
enemy_cursor->SetSrcRect(Rect(0, 0, 16, 16)); | |
enemy_cursor->SetZ(999); | |
enemy_cursor->SetVisible(false); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CreateWindows() { | |
help_window.reset(new Window_Help(0, 0, 320, 32)); | |
help_window->SetVisible(false); | |
options_window.reset(new Window_BattleOption(0, 172, 76, 68)); | |
status_window.reset(new Window_BattleStatus()); | |
command_window.reset(new Window_BattleCommand(244, 172, 76, 68)); | |
skill_window.reset(new Window_BattleSkill(0, 172, 320, 68)); | |
skill_window->SetVisible(false); | |
item_window.reset(new Window_BattleItem(0, 172, 320, 68)); | |
item_window->SetVisible(false); | |
item_window->Refresh(); | |
item_window->SetIndex(0); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Start() { | |
if (Player::battle_test_flag) { | |
if (Player::battle_test_troop_id <= 0) { | |
Output::Error("Invalid Monster Party Id"); | |
} else { | |
Game_Temp::battle_troop_id = Player::battle_test_troop_id; | |
// ToDo: Rpg2k does specify a background graphic instead | |
Game_Temp::battle_terrain_id = 1; | |
} | |
} | |
Game_Battle::Init(this); | |
cycle = 0; | |
auto_battle = false; | |
enemy_action = NULL; | |
CreateCursors(); | |
CreateWindows(); | |
animation.reset(); | |
animations.clear(); | |
if (!Game_Temp::battle_background.empty()) | |
background.reset(new Background(Game_Temp::battle_background)); | |
else | |
background.reset(new Background(Game_Temp::battle_terrain_id)); | |
SetState(State_Options); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::SetState(Scene_Battle2k3::State new_state) { | |
target_state = state; | |
state = new_state; | |
if (state == State_Battle && auto_battle) | |
state = State_AutoBattle; | |
options_window->SetActive(false); | |
status_window->SetActive(false); | |
command_window->SetActive(false); | |
item_window->SetActive(false); | |
skill_window->SetActive(false); | |
switch (state) { | |
case State_Options: | |
options_window->SetActive(true); | |
break; | |
case State_Battle: | |
status_window->SetActive(true); | |
break; | |
case State_AutoBattle: | |
break; | |
case State_Command: | |
command_window->SetActive(true); | |
command_window->SetActor(Game_Battle::GetActiveActor()); | |
break; | |
case State_TargetEnemy: | |
break; | |
case State_TargetAlly: | |
status_window->SetActive(true); | |
break; | |
case State_Item: | |
item_window->SetActive(true); | |
item_window->SetActor(Game_Battle::GetActiveActor()); | |
item_window->Refresh(); | |
break; | |
case State_Skill: | |
skill_window->SetActive(true); | |
skill_window->SetActor(Game_Battle::GetActiveActor()); | |
skill_window->SetIndex(0); | |
break; | |
case State_AllyAction: | |
case State_EnemyAction: | |
case State_Victory: | |
case State_Defeat: | |
break; | |
} | |
options_window->SetVisible(false); | |
status_window->SetVisible(false); | |
command_window->SetVisible(false); | |
item_window->SetVisible(false); | |
skill_window->SetVisible(false); | |
help_window->SetVisible(false); | |
item_window->SetHelpWindow(NULL); | |
skill_window->SetHelpWindow(NULL); | |
switch (state) { | |
case State_Options: | |
options_window->SetVisible(true); | |
status_window->SetVisible(true); | |
status_window->SetX(76); | |
break; | |
case State_Battle: | |
case State_AutoBattle: | |
case State_Command: | |
case State_TargetEnemy: | |
case State_TargetAlly: | |
case State_AllyAction: | |
case State_EnemyAction: | |
status_window->SetVisible(true); | |
status_window->SetX(0); | |
command_window->SetVisible(true); | |
break; | |
case State_Item: | |
item_window->SetVisible(true); | |
item_window->SetHelpWindow(help_window.get()); | |
help_window->SetVisible(true); | |
break; | |
case State_Skill: | |
skill_window->SetVisible(true); | |
skill_window->SetHelpWindow(help_window.get()); | |
help_window->SetVisible(true); | |
break; | |
case State_Victory: | |
case State_Defeat: | |
status_window->SetVisible(true); | |
status_window->SetX(0); | |
command_window->SetVisible(true); | |
help_window->SetVisible(true); | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Message(const std::string& msg, bool pause) { | |
help_window->SetText(msg); | |
help_window->SetVisible(true); | |
help_window->SetPause(pause); | |
if (!pause) | |
message_timer = 60; | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Floater(const Sprite* ref, int color, const std::string& text, int duration) { | |
int x = ref->GetX(); | |
int y = ref->GetY() - ref->GetOy(); | |
floaters.push_back(EASYRPG_MAKE_SHARED<FloatText>(x, y, color, text, duration)); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Floater(const Sprite* ref, int color, int value, int duration) { | |
std::ostringstream out; | |
out << value; | |
Floater(ref, color, out.str(), duration); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::SetAnimState(Battle::Ally& ally, int state) { | |
ally.SetAnimState(state); | |
ally.UpdateAnim(cycle); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateAnimState() { | |
Battle::Ally& ally = Game_Battle::GetActiveAlly(); | |
int anim_state = Battle::Ally::Idle; | |
if (ally.defending) | |
anim_state = Battle::Ally::Defending; | |
const RPG::State* state = ally.GetActor()->GetState(); | |
if (state) | |
anim_state = state->battler_animation_id == 100 | |
? 7 | |
: state->battler_animation_id + 1; | |
SetAnimState(ally, anim_state); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Restart() { | |
UpdateAnimState(); | |
SetState(State_Battle); | |
Game_Battle::GetActiveAlly().last_command = pending_command; | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Command() { | |
RPG::BattleCommand command = command_window->GetCommand(); | |
pending_command = command.ID; | |
switch (command.type) { | |
case RPG::BattleCommand::Type_attack: | |
Game_Battle::SetTargetEnemy(0); | |
SetState(State_TargetEnemy); | |
break; | |
case RPG::BattleCommand::Type_skill: | |
SetState(State_Skill); | |
skill_window->SetSubset(RPG::Skill::Type_normal); | |
break; | |
case RPG::BattleCommand::Type_subskill: | |
{ | |
int subset = command_window->GetSkillSubset(); | |
SetState(State_Skill); | |
skill_window->SetSubset(subset); | |
} | |
break; | |
case RPG::BattleCommand::Type_defense: | |
Defend(); | |
break; | |
case RPG::BattleCommand::Type_item: | |
SetState(State_Item); | |
break; | |
case RPG::BattleCommand::Type_escape: | |
Escape(); | |
break; | |
case RPG::BattleCommand::Type_special: | |
Special(); | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Escape() { | |
if (Game_Battle::Escape()) | |
Scene::Pop(); | |
else | |
Game_Battle::Restart(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Special() { | |
// FIXME: special commands (link to event) | |
Game_Battle::Restart(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Defend() { | |
Game_Battle::Defend(); | |
Game_Battle::Restart(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Item() { | |
int item_id = item_window->GetItemId(); | |
if (item_id <= 0) { | |
Game_System::SePlay(Data::system.buzzer_se); | |
return; | |
} | |
const RPG::Item& item = Data::items[item_id - 1]; | |
switch (item.type) { | |
case RPG::Item::Type_normal: | |
Game_System::SePlay(Data::system.buzzer_se); | |
break; | |
case RPG::Item::Type_weapon: | |
case RPG::Item::Type_shield: | |
case RPG::Item::Type_armor: | |
case RPG::Item::Type_helmet: | |
case RPG::Item::Type_accessory: | |
if (item.use_skill) | |
ItemSkill(item); | |
else | |
// can't be used | |
Game_System::SePlay(Data::system.buzzer_se); | |
break; | |
case RPG::Item::Type_medicine: | |
if (item.entire_party) | |
BeginItem(); | |
else { | |
Game_Battle::TargetActiveAlly(); | |
SetState(State_TargetAlly); | |
} | |
break; | |
case RPG::Item::Type_book: | |
case RPG::Item::Type_material: | |
// can't be used in battle? | |
Game_System::SePlay(Data::system.buzzer_se); | |
break; | |
case RPG::Item::Type_special: | |
ItemSkill(item); | |
break; | |
case RPG::Item::Type_switch: | |
Game_Switches[item.switch_id] = true; | |
Game_Battle::Restart(); | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Skill() { | |
int skill_id = skill_window->GetSkillId(); | |
if (skill_id <= 0) { | |
Game_System::SePlay(Data::system.buzzer_se); | |
return; | |
} | |
const RPG::Skill& skill = Data::skills[skill_id - 1]; | |
Skill(skill); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::ItemSkill(const RPG::Item& item) { | |
const RPG::Skill& skill = Data::skills[item.skill_id - 1]; | |
Skill(skill); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Skill(const RPG::Skill& skill) { | |
skill_id = skill.ID; | |
switch (skill.type) { | |
case RPG::Skill::Type_teleport: | |
case RPG::Skill::Type_escape: | |
case RPG::Skill::Type_switch: | |
BeginSkill(); | |
return; | |
case RPG::Skill::Type_normal: | |
default: | |
break; | |
} | |
switch (skill.scope) { | |
case RPG::Skill::Scope_enemy: | |
Game_Battle::SetTargetEnemy(0); | |
SetState(State_TargetEnemy); | |
return; | |
case RPG::Skill::Scope_ally: | |
Game_Battle::TargetActiveAlly(); | |
SetState(State_TargetAlly); | |
break; | |
case RPG::Skill::Scope_enemies: | |
case RPG::Skill::Scope_self: | |
case RPG::Skill::Scope_party: | |
BeginSkill(); | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::TargetDone() { | |
switch (target_state) { | |
case State_Command: | |
BeginAttack(); | |
break; | |
case State_Item: | |
BeginItem(); | |
break; | |
case State_Skill: | |
BeginSkill(); | |
break; | |
default: | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::BeginAttack() { | |
Battle::Ally& ally = Game_Battle::GetActiveAlly(); | |
Battle::Enemy& enemy = Game_Battle::GetTargetEnemy(); | |
int x0 = ally.rpg_actor->battle_x; | |
int x1 = enemy.sprite->GetX() - enemy.sprite->GetOx() + enemy.sprite->GetWidth() + | |
ally.sprite->GetOx(); | |
actions.clear(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::SpriteAction>(&ally, Battle::Ally::WalkingLeft)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::MoveAction>(ally.sprite.get(), x0, x1, 8)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::SpriteAction>(&ally, Battle::Ally::RightHand)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(15)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::Attack)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::SpriteAction>(&ally, Battle::Ally::WalkingRight)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::MoveAction>(ally.sprite.get(), x1, x0, 8)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::Restart)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
SetState(State_AllyAction); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::BeginItem() { | |
Battle::Ally& ally = Game_Battle::GetActiveAlly(); | |
Game_Battle::SetItem(item_window->GetItemId()); | |
actions.clear(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::SpriteAction>(&ally, Battle::Ally::Item)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(60)); | |
actions.push_back(EASYRPG_SHARED_PTR<Battle::CommandAction>(new Battle::CommandAction(&Game_Battle::UseItem))); | |
actions.push_back(EASYRPG_SHARED_PTR<Battle::CommandAction>(new Battle::CommandAction(&Game_Battle::Restart))); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
SetState(State_AllyAction); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::BeginSkill() { | |
Battle::Ally& ally = Game_Battle::GetActiveAlly(); | |
const RPG::Skill& skill = Data::skills[skill_id - 1]; | |
int anim_state = SkillAnimation(skill, ally); | |
const RPG::Animation* animation = (skill.animation_id != 0) | |
? &Data::animations[skill.animation_id - 1] | |
: NULL; | |
EASYRPG_SHARED_PTR<Battle::Action> action; | |
int x, y; | |
switch (skill.type) { | |
case RPG::Skill::Type_teleport: | |
case RPG::Skill::Type_escape: | |
case RPG::Skill::Type_switch: | |
break; | |
case RPG::Skill::Type_normal: | |
default: | |
switch (skill.scope) { | |
case RPG::Skill::Scope_enemy: | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(Game_Battle::GetTargetEnemy().sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_enemies: | |
if (animation != NULL) { | |
Game_Battle::EnemiesCentroid(x, y); | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(x, y, animation); | |
} | |
break; | |
case RPG::Skill::Scope_self: | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(ally.sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_ally: | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(Game_Battle::GetTargetAlly().sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_party: | |
if (animation != NULL) { | |
Game_Battle::AlliesCentroid(x, y); | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(x, y, animation); | |
} | |
default: | |
break; | |
} | |
} | |
if (action == NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::WaitAction>(10); | |
actions.clear(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::SpriteAction>(&ally, anim_state)); | |
actions.push_back(action); | |
actions.push_back(EASYRPG_SHARED_PTR<Battle::CommandAction>(new Battle::CommandAction(&Game_Battle::UseSkill))); | |
actions.push_back(EASYRPG_SHARED_PTR<Battle::CommandAction>(new Battle::CommandAction(&Game_Battle::Restart))); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
SetState(State_AllyAction); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::DoItem() { | |
Game_Battle::UseItem(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::DoSkill() { | |
Game_Battle::SetSkill(skill_id); | |
Game_Battle::UseSkill(); | |
} | |
//////////////////////////////////////////////////////////// | |
int Scene_Battle2k3::SkillAnimation(const RPG::Skill& skill, const Battle::Ally& ally) { | |
const std::vector<RPG::BattlerAnimationData>& anim_data = skill.battler_animation_data; | |
std::vector<RPG::BattlerAnimationData>::const_iterator it; | |
for (it = anim_data.begin(); it != anim_data.end(); it++) { | |
const RPG::BattlerAnimationData& data = *it; | |
if (data.ID != ally.game_actor->GetId()) | |
continue; | |
return data.pose == 0 ? Battle::Ally::SkillUse : data.pose; | |
} | |
return Battle::Ally::SkillUse; | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::EnemyAction() { | |
Battle::Enemy& enemy = Game_Battle::GetActiveEnemy(); | |
if (!enemy.game_enemy->Exists()) | |
return; | |
enemy.defending = false; | |
enemy_action = Game_Battle::ChooseEnemyAction(enemy); | |
if (enemy_action == NULL) | |
return; | |
actions.clear(); | |
switch (enemy_action->kind) { | |
case RPG::EnemyAction::Kind_basic: | |
EnemyActionBasic(); | |
break; | |
case RPG::EnemyAction::Kind_skill: | |
EnemyActionSkill(); | |
break; | |
case RPG::EnemyAction::Kind_transformation: | |
Game_Battle::SetMorph(enemy_action->enemy_id); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyTransform)); | |
break; | |
} | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyActionDone)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction1>(&Scene_Battle2k3::EnemyActionDone, (void*) this)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
SetState(State_EnemyAction); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::EnemyActionBasic() { | |
switch (enemy_action->basic) { | |
case RPG::EnemyAction::Basic_attack: | |
{ | |
Game_Battle::TargetRandomAlly(); | |
Battle::Ally &ally = Game_Battle::GetTargetAlly(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::AnimationAction>(ally.sprite.get(), &Data::animations[0])); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction1>(&Game_Battle::EnemyAttack, (void*) &ally)); | |
break; | |
} | |
case RPG::EnemyAction::Basic_dual_attack: | |
{ | |
Game_Battle::TargetRandomAlly(); | |
Battle::Ally &ally1 = Game_Battle::GetTargetAlly(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::AnimationAction>(ally1.sprite.get(), &Data::animations[0])); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction1>(&Game_Battle::EnemyAttack, (void*) &ally1)); | |
Game_Battle::TargetRandomAlly(); | |
Battle::Ally &ally2 = Game_Battle::GetTargetAlly(); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::AnimationAction>(ally2.sprite.get(), &Data::animations[0])); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction1>(&Game_Battle::EnemyAttack, (void*) &ally2)); | |
break; | |
} | |
case RPG::EnemyAction::Basic_defense: | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyDefend)); | |
break; | |
case RPG::EnemyAction::Basic_observe: | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyObserve)); | |
break; | |
case RPG::EnemyAction::Basic_charge: | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyCharge)); | |
break; | |
case RPG::EnemyAction::Basic_autodestruction: | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::CommandAction>(&Game_Battle::EnemyDestruct)); | |
case RPG::EnemyAction::Basic_nothing: | |
actions.push_back(EASYRPG_MAKE_SHARED<Battle::WaitAction>(20)); | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::EnemyActionSkill() { | |
Battle::Enemy& enemy = Game_Battle::GetActiveEnemy(); | |
const RPG::Skill& skill = Data::skills[enemy_action->skill_id - 1]; | |
const RPG::Animation* animation = (skill.animation_id != 0) | |
? &Data::animations[skill.animation_id - 1] | |
: NULL; | |
EASYRPG_SHARED_PTR<Battle::Action> action; | |
int x, y; | |
Game_Battle::SetSkill(enemy_action->skill_id); | |
switch (skill.type) { | |
case RPG::Skill::Type_teleport: | |
case RPG::Skill::Type_escape: | |
action = EASYRPG_MAKE_SHARED<Battle::MoveAction>(enemy.sprite.get(), enemy.sprite->GetX(), -enemy.sprite->GetWidth(), 8); | |
break; | |
case RPG::Skill::Type_switch: | |
break; | |
case RPG::Skill::Type_normal: | |
default: | |
switch (skill.scope) { | |
case RPG::Skill::Scope_enemy: | |
Game_Battle::TargetRandomAlly(); | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(Game_Battle::GetTargetAlly().sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_self: | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(enemy.sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_ally: | |
Game_Battle::TargetRandomEnemy(); | |
if (animation != NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(Game_Battle::GetTargetEnemy().sprite.get(), animation); | |
break; | |
case RPG::Skill::Scope_enemies: | |
if (animation != NULL) { | |
Game_Battle::AlliesCentroid(x, y); | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(x, y, animation); | |
} | |
break; | |
case RPG::Skill::Scope_party: | |
if (animation != NULL) { | |
Game_Battle::EnemiesCentroid(x, y); | |
action = EASYRPG_MAKE_SHARED<Battle::AnimationAction>(x, y, animation); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
if (action == NULL) | |
action = EASYRPG_MAKE_SHARED<Battle::WaitAction>(30); | |
actions.push_back(action); | |
actions.push_back(EASYRPG_SHARED_PTR<Battle::CommandAction>(new Battle::CommandAction(&Game_Battle::EnemySkill))); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::EnemyActionDone(void* param) { | |
Scene_Battle2k3* thiz = (Scene_Battle2k3*) param; | |
thiz->SetState(State_Battle); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::ProcessActions() { | |
switch (state) { | |
case State_Battle: | |
case State_AutoBattle: | |
Game_Battle::Update(); | |
CheckWin(); | |
CheckLose(); | |
CheckAbort(); | |
CheckFlee(); | |
if (help_window->GetVisible() && message_timer > 0) { | |
message_timer--; | |
if (message_timer <= 0) | |
help_window->SetVisible(false); | |
} | |
while (Game_Battle::NextActiveEnemy()) | |
EnemyAction(); | |
break; | |
case State_AllyAction: | |
case State_EnemyAction: | |
if (!actions.empty()) { | |
Battle::Action& action = *actions.front(); | |
if (action()) { | |
actions.pop_front(); | |
} | |
} | |
default: | |
break; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::ProcessInput() { | |
if (Input::IsTriggered(Input::DECISION)) { | |
Game_System::SePlay(Data::system.decision_se); | |
switch (state) { | |
case State_Options: | |
switch (options_window->GetIndex()) { | |
case 0: | |
auto_battle = false; | |
SetState(State_Battle); | |
break; | |
case 1: | |
auto_battle = true; | |
SetState(State_Battle); | |
break; | |
case 2: | |
Escape(); | |
break; | |
} | |
break; | |
case State_Battle: | |
Game_Battle::SetActiveAlly(status_window->GetActiveCharacter()); | |
if (Game_Battle::HaveActiveAlly()) | |
SetState(State_Command); | |
break; | |
case State_AutoBattle: | |
// no-op | |
break; | |
case State_Command: | |
Command(); | |
break; | |
case State_TargetEnemy: | |
case State_TargetAlly: | |
TargetDone(); | |
break; | |
case State_Item: | |
Item(); | |
break; | |
case State_Skill: | |
Skill(); | |
break; | |
case State_AllyAction: | |
case State_EnemyAction: | |
break; | |
case State_Victory: | |
case State_Defeat: | |
Scene::Pop(); | |
break; | |
} | |
} | |
if (Input::IsTriggered(Input::CANCEL)) { | |
Game_System::SePlay(Data::system.cancel_se); | |
switch (state) { | |
case State_Options: | |
Scene::Pop(); | |
break; | |
case State_Battle: | |
case State_AutoBattle: | |
SetState(State_Options); | |
break; | |
case State_Command: | |
SetState(State_Battle); | |
break; | |
case State_TargetEnemy: | |
case State_Item: | |
case State_Skill: | |
SetState(State_Command); | |
break; | |
case State_TargetAlly: | |
SetState(State_Item); | |
break; | |
case State_AllyAction: | |
case State_EnemyAction: | |
break; | |
case State_Victory: | |
case State_Defeat: | |
Scene::Pop(); | |
break; | |
} | |
} | |
if (state == State_TargetEnemy && Game_Battle::HaveTargetEnemy()) { | |
if (Input::IsRepeated(Input::DOWN)) | |
Game_Battle::TargetNextEnemy(); | |
if (Input::IsRepeated(Input::UP)) | |
Game_Battle::TargetPreviousEnemy(); | |
Game_Battle::ChooseEnemy(); | |
} | |
if (state == State_TargetAlly && Game_Battle::HaveTargetAlly()) { | |
if (Input::IsRepeated(Input::DOWN)) | |
Game_Battle::TargetNextAlly(); | |
if (Input::IsRepeated(Input::UP)) | |
Game_Battle::TargetPreviousAlly(); | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::DoAuto() { | |
if (state != State_AutoBattle) | |
return; | |
Game_Battle::SetActiveAlly(status_window->GetActiveCharacter()); | |
if (!Game_Battle::HaveActiveAlly()) | |
return; | |
// FIXME: this assumes that the character has an "Attack" command. | |
// FIXME: should try to use some intelligence | |
Game_Battle::ChooseEnemy(); | |
if (!Game_Battle::HaveTargetEnemy()) | |
return; | |
pending_command = 1; | |
Game_Battle::Attack(); | |
Game_Battle::Restart(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateBackground() { | |
if (Game_Temp::battle_background != Game_Battle::background_name) { | |
Game_Temp::battle_background = Game_Battle::background_name; | |
background.reset(new Background(Game_Temp::battle_background)); | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateCursors() { | |
if (Game_Battle::HaveActiveAlly()) { | |
const Battle::Ally& ally = state == State_TargetAlly && Game_Battle::HaveTargetAlly() | |
? Game_Battle::GetTargetAlly() | |
: Game_Battle::GetActiveAlly(); | |
ally_cursor->SetVisible(true); | |
ally_cursor->SetX(ally.rpg_actor->battle_x - ally_cursor->GetWidth() / 2); | |
ally_cursor->SetY(ally.rpg_actor->battle_y - ally.sprite->GetHeight() / 2 - ally_cursor->GetHeight() - 2); | |
static const int frames[] = {0,1,2,1}; | |
int frame = frames[(cycle / 15) % 4]; | |
ally_cursor->SetSrcRect(Rect(frame * 16, 16, 16, 16)); | |
} | |
else | |
ally_cursor->SetVisible(false); | |
if (state == State_TargetEnemy && Game_Battle::HaveTargetEnemy()) { | |
const Battle::Enemy& enemy = Game_Battle::GetTargetEnemy(); | |
enemy_cursor->SetVisible(true); | |
enemy_cursor->SetX(enemy.member->x + enemy.sprite->GetWidth() / 2 + 2); | |
enemy_cursor->SetY(enemy.member->y - enemy_cursor->GetHeight() / 2); | |
static const int frames[] = {0,1,2,1}; | |
int frame = frames[(cycle / 15) % 4]; | |
enemy_cursor->SetSrcRect(Rect(frame * 16, 0, 16, 16)); | |
} | |
else | |
enemy_cursor->SetVisible(false); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateSprites() { | |
for (std::vector<Battle::Enemy>::iterator it = Game_Battle::enemies.begin(); it != Game_Battle::enemies.end(); it++) { | |
if (it->sprite->GetVisible() && !it->game_enemy->Exists() && it->fade == 0) | |
it->fade = 60; | |
if (it->fade > 0) { | |
it->sprite->SetOpacity(it->fade * 255 / 60); | |
it->fade--; | |
if (it->fade == 0) | |
it->sprite->SetVisible(false); | |
} | |
if (!it->rpg_enemy->levitate) | |
continue; | |
int y = (int) (3 * sin(cycle / 30.0)); | |
it->sprite->SetY(it->member->y + y); | |
it->sprite->SetZ(it->member->y + y); | |
} | |
for (std::vector<Battle::Ally>::iterator it = Game_Battle::allies.begin(); it != Game_Battle::allies.end(); it++) | |
it->UpdateAnim(cycle); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateFloaters() { | |
std::vector<EASYRPG_SHARED_PTR<FloatText> >::iterator it; | |
std::vector<EASYRPG_SHARED_PTR<FloatText> >::iterator dst = floaters.begin(); | |
for (it = floaters.begin(); it != floaters.end(); it++) { | |
FloatText* floater = it->get(); | |
floater->duration--; | |
if (floater->duration <= 0) | |
it->reset(); | |
else | |
*dst++ = *it; | |
} | |
floaters.erase(dst, floaters.end()); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::ShowAnimation(int animation_id, bool allies, Battle::Ally* ally, Battle::Enemy* enemy, bool wait) { | |
const RPG::Animation* rpg_anim = &Data::animations[animation_id - 1]; | |
int x, y; | |
if (ally != NULL) { | |
x = ally->sprite->GetX(); | |
y = ally->sprite->GetY(); | |
} | |
else if (enemy != NULL) { | |
x = enemy->sprite->GetX(); | |
y = enemy->sprite->GetY(); | |
} | |
else if (allies) | |
Game_Battle::AlliesCentroid(x, y); | |
else | |
Game_Battle::EnemiesCentroid(x, y); | |
EASYRPG_SHARED_PTR<BattleAnimation> new_animation = | |
EASYRPG_MAKE_SHARED<BattleAnimation>(x, y, rpg_anim); | |
if (wait) { | |
animation = new_animation; | |
} | |
else | |
animations.push_back(new_animation); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::UpdateAnimations() { | |
if (animation != NULL) { | |
animation->Update(); | |
if (animation->IsDone()) { | |
animation.reset(); | |
} | |
} | |
for (std::deque<EASYRPG_SHARED_PTR<BattleAnimation> >::iterator it = animations.begin(); it != animations.end(); it++) { | |
BattleAnimation* anim = it->get(); | |
if (anim == NULL) | |
continue; | |
anim->Update(); | |
if (anim->IsDone()) { | |
it->reset(); | |
} | |
} | |
std::deque<EASYRPG_SHARED_PTR<BattleAnimation> >::iterator end; | |
end = std::remove(animations.begin(), animations.end(), EASYRPG_SHARED_PTR<BattleAnimation>()); | |
animations.erase(end, animations.end()); | |
} | |
//////////////////////////////////////////////////////////// | |
bool Scene_Battle2k3::IsAnimationWaiting() { | |
return animation != NULL; | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::Update() { | |
options_window->Update(); | |
status_window->Update(); | |
command_window->Update(); | |
help_window->Update(); | |
item_window->Update(); | |
skill_window->Update(); | |
Game_Battle::SetActiveAlly(status_window->GetActiveCharacter()); | |
command_window->SetActor(Game_Battle::GetActiveActor()); | |
cycle++; | |
ProcessActions(); | |
ProcessInput(); | |
DoAuto(); | |
UpdateBackground(); | |
UpdateCursors(); | |
UpdateSprites(); | |
UpdateFloaters(); | |
UpdateAnimations(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CheckWin() { | |
if (state == State_Victory || state == State_Defeat) | |
return; | |
if (!Game_Battle::CheckWin()) | |
return; | |
for (std::vector<Battle::Ally>::iterator it = Game_Battle::allies.begin(); it != Game_Battle::allies.end(); it++) | |
it->SetAnimState(Battle::Ally::Victory); | |
Game_Temp::battle_result = Game_Temp::BattleVictory; | |
SetState(State_Victory); | |
Message(Data::terms.victory.empty() ? Data::terms.victory : "Victory"); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CheckLose() { | |
if (state == State_Victory || state == State_Defeat) | |
return; | |
if (!Game_Battle::CheckLose()) | |
return; | |
Game_Temp::battle_result = Game_Temp::BattleDefeat; | |
SetState(State_Defeat); | |
Message(!Data::terms.defeat.empty() ? Data::terms.defeat : "Defeat"); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CheckAbort() { | |
if (!Game_Battle::terminate) | |
return; | |
Game_Temp::battle_result = Game_Temp::BattleAbort; | |
Scene::Pop(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Scene_Battle2k3::CheckFlee() { | |
if (!Game_Battle::allies_flee) | |
return; | |
Game_Battle::allies_flee = false; | |
Game_Temp::battle_result = Game_Temp::BattleEscape; | |
Scene::Pop(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////// | |
// This file is part of EasyRPG Player. | |
// | |
// EasyRPG Player is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// | |
// EasyRPG Player is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details. | |
// | |
// You should have received a copy of the GNU General Public License | |
// along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>. | |
///////////////////////////////////////////////////////////////////////////// | |
#ifndef _SCENE_BATTLE2K3_H_ | |
#define _SCENE_BATTLE2K3_H_ | |
//////////////////////////////////////////////////////////// | |
// Headers | |
//////////////////////////////////////////////////////////// | |
#include <deque> | |
#include "rpg_troopmember.h" | |
#include "rpg_actor.h" | |
#include "rpg_enemy.h" | |
#include "game_actor.h" | |
#include "game_enemy.h" | |
#include "scene.h" | |
#include "background.h" | |
#include "drawable.h" | |
#include "zobj.h" | |
#include "window_help.h" | |
#include "window_battleitem.h" | |
#include "window_battleskill.h" | |
#include "window_battleoption.h" | |
#include "window_battlecommand.h" | |
#include "window_battlestatus.h" | |
#include "battle_battler.h" | |
#include "battle_animation.h" | |
#include "battle_interface.h" | |
#include <boost/scoped_ptr.hpp> | |
namespace Battle { | |
class Action; | |
class SpriteAction; | |
} | |
//////////////////////////////////////////////////////////// | |
/// Scene_Battle2k3 class. | |
/// Manages the battles fo RPG Maker 2003 games. | |
//////////////////////////////////////////////////////////// | |
class Scene_Battle2k3 : public Scene, public Battle_Interface { | |
public: | |
Scene_Battle2k3(); | |
~Scene_Battle2k3(); | |
void Start(); | |
void Update(); | |
enum State { | |
State_Options, | |
State_Battle, | |
State_AutoBattle, | |
State_Command, | |
State_Item, | |
State_Skill, | |
State_TargetEnemy, | |
State_TargetAlly, | |
State_AllyAction, | |
State_EnemyAction, | |
State_Victory, | |
State_Defeat | |
}; | |
struct FloatText { | |
FloatText(int x, int y, int color, const std::string& text, int duration); | |
int duration; | |
boost::scoped_ptr<Sprite> sprite; | |
}; | |
private: | |
friend class Battle::SpriteAction; | |
State state; | |
State target_state; | |
bool auto_battle; | |
int cycle; | |
int attack_state; | |
int message_timer; | |
const RPG::EnemyAction* enemy_action; | |
std::deque<EASYRPG_SHARED_PTR<Battle::Action> > actions; | |
int skill_id; | |
int pending_command; | |
boost::scoped_ptr<Window_Help> help_window; | |
boost::scoped_ptr<Window_BattleOption> options_window; | |
boost::scoped_ptr<Window_BattleStatus> status_window; | |
boost::scoped_ptr<Window_BattleCommand> command_window; | |
boost::scoped_ptr<Window_BattleItem> item_window; | |
boost::scoped_ptr<Window_BattleSkill> skill_window; | |
boost::scoped_ptr<Background> background; | |
EASYRPG_SHARED_PTR<BattleAnimation> animation; | |
std::deque<EASYRPG_SHARED_PTR<BattleAnimation> > animations; | |
std::vector<EASYRPG_SHARED_PTR<FloatText> > floaters; | |
boost::scoped_ptr<Sprite> ally_cursor, enemy_cursor; | |
void CreateCursors(); | |
void CreateWindows(); | |
void Message(const std::string& msg, bool pause = true); | |
void Floater(const Sprite* ref, int color, const std::string& text, int duration); | |
void Floater(const Sprite* ref, int color, int value, int duration); | |
void ShowAnimation(int animation_id, bool allies, Battle::Ally* ally, Battle::Enemy* enemy, bool wait); | |
void UpdateAnimations(); | |
bool IsAnimationWaiting(); | |
void SetState(State state); | |
void SetAnimState(Battle::Ally& ally, int state); | |
void UpdateAnimState(); | |
void Restart(); | |
void Command(); | |
void Escape(); | |
void Special(); | |
void Attack(); | |
void Defend(); | |
void Item(); | |
void Skill(); | |
void ItemSkill(const RPG::Item& item); | |
void Skill(const RPG::Skill& skill); | |
void TargetDone(); | |
void BeginAttack(); | |
void BeginItem(); | |
void BeginSkill(); | |
void DoAttack(); | |
void DoItem(); | |
void DoSkill(); | |
int SkillAnimation(const RPG::Skill& skill, const Battle::Ally& ally); | |
void EnemyAction(); | |
void EnemyActionBasic(); | |
void EnemyActionSkill(); | |
static void EnemyActionDone(void* param); | |
void ProcessActions(); | |
void ProcessInput(); | |
void ChooseEnemy(); | |
void DoAuto(); | |
void UpdateBackground(); | |
void UpdateCursors(); | |
void UpdateAttack(); | |
void UpdateSprites(); | |
void UpdateFloaters(); | |
void CheckWin(); | |
void CheckLose(); | |
void CheckAbort(); | |
void CheckFlee(); | |
// battle_algorithms.cpp | |
void AttackEnemy(Battle::Ally& ally, Battle::Enemy& enemy); | |
void UseItem(Battle::Ally& ally, const RPG::Item& item); | |
void UseItemAlly(Battle::Ally& ally, const RPG::Item& item, Battle::Ally& target); | |
void UseSkill(Battle::Ally& ally, const RPG::Skill& skill); | |
void UseSkillAlly(Battle::Battler& ally, const RPG::Skill& skill, Battle::Battler& target); | |
void UseSkillEnemy(Battle::Battler& ally, const RPG::Skill& skill, Battle::Battler& target); | |
bool EnemyActionValid(const RPG::EnemyAction& action, Battle::Enemy& enemy); | |
const RPG::EnemyAction* ChooseEnemyAction(Battle::Enemy& enemy); | |
void EnemyAttackAlly(Battle::Enemy& enemy, Battle::Ally& ally); | |
void EnemySkill(Battle::Enemy& enemy, const RPG::Skill& skill); | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment