Skip to content

Instantly share code, notes, and snippets.

@MarianoGnu
Created February 20, 2013 20:42
Show Gist options
  • Save MarianoGnu/4999426 to your computer and use it in GitHub Desktop.
Save MarianoGnu/4999426 to your computer and use it in GitHub Desktop.
/////////////////////////////////////////////////////////////////////////////
// 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 "scene_battle2k.h"
#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 "bitmap.h"
/***************************
* Scene related methods *
***************************/
////////////////////////////////////////////////////////////
Scene_Battle2k::Scene_Battle2k() {
Scene::type = Scene::Battle;
}
////////////////////////////////////////////////////////////
Scene_Battle2k::~Scene_Battle2k() {
Game_Battle::Quit();
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::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);
/*TODO: delete this?
cycle = 0;
auto_battle = false;
enemy_action = NULL;*/
CreateWindows();
/*TODO: use this?
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_Start);
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::Update() {
options_window->Update();
status_window->Update();
command_window->Update();
help_window->Update();
item_window->Update();
skill_window->Update();
/*if (!this->actions.empty())
ProcessActions();
DoAuto();*/
ProcessInput();
UpdateBackground();
/*UpdateSprites();*/
UpdateAnimations();
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::ProcessInput() {
RPG::Skill& skill = Data::skills[0];
RPG::Item& item = Data::items[0];
RPG::BattleCommand command = command_window->GetCommand();
if (Input::IsTriggered(Input::DECISION)) {
Game_System::SePlay(Data::system.decision_se);
switch (state) {
case State_Options:
switch (options_window->GetIndex()) {
case 0:
actions;
SetState(State_Battle);
break;
case 1:
SetState(State_AutoBattle);
break;
case 2:
//TODO: Escape();
break;
}
break;
case State_AutoBattle:
// no-op
break;
case State_Command:
current_action.command_id = command.type;
switch (command.type) {
case RPG::BattleCommand::Type_attack:
SetState(State_TargetEnemy);
break;
case RPG::BattleCommand::Type_skill:
SetState(State_Skill);
skill_window->SetSubset(RPG::Skill::Type_normal);
break;
case RPG::BattleCommand::Type_item:
SetState(State_Item);
break;
/*TODO: ein?*/
/*case RPG::BattleCommand::Type_escape:
Escape();
break;
case RPG::BattleCommand::Type_special:
Special();
break;*/
}
break;
case State_Skill:
current_action.skill = skill_window->GetSkillId();
skill = Data::skills[current_action.skill - 1];
switch (skill.scope) {
case RPG::Skill::Scope_ally:
SetState(State_TargetAlly);
return;
case RPG::Skill::Scope_enemy:
SetState(State_TargetEnemy);
return;
case RPG::Skill::Scope_self:
current_action.target = current_action.index;
if (status_window->GetActiveCharacter() == Game_Battle::allies.size() - 1)
SetState(State_Action);
else
SetState(State_Command);
break;
}
case State_Item:
current_action.item = item_window->GetItemId();
if (current_action.item <= 0) {
Game_System::SePlay(Data::system.buzzer_se);
return;
}
item = Data::items[current_action.item - 1];
switch (item.type) {
case RPG::Item::Type_normal:
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:
case RPG::Item::Type_book:
case RPG::Item::Type_material:
Game_System::SePlay(Data::system.buzzer_se);
return;
break;
case RPG::Item::Type_medicine:
if (!item.entire_party)
SetState(State_TargetAlly);
else
SetState(State_Command);
break;
case RPG::Item::Type_special:
if (item.skill_id <= 0)
break;
current_action.skill = item.skill_id;
skill = Data::skills[current_action.skill - 1];
switch (skill.scope) {
case RPG::Skill::Scope_ally:
SetState(State_TargetAlly);
return;
case RPG::Skill::Scope_enemy:
SetState(State_TargetEnemy);
return;
}
break;
case RPG::Item::Type_switch:
Game_Switches[item.switch_id] = true;
break;
}
if (status_window->GetActiveCharacter() == Game_Battle::allies.size() - 1)
SetState(State_Action);
else
SetState(State_Command);
break;
case State_TargetAlly:
if (status_window->GetIndex() >= 0){
current_action.target = status_window->GetIndex();
if (status_window->GetActiveCharacter() == Game_Battle::allies.size() - 1)
SetState(State_Action);
else
SetState(State_Command);
}
break;
case State_TargetEnemy:
current_action.target = enemytarget_window->GetIndex();
if (status_window->GetActiveCharacter() == Game_Battle::allies.size() - 1)
SetState(State_Action);
else
SetState(State_Command);
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_Command:
if (status_window->GetActiveCharacter() > 0){
actions.pop_back();
current_action.reset();
status_window->SetActiveCharacter(status_window->GetActiveCharacter() - 1);
}
else
SetState(State_Battle, true);
break;
case State_Item:
case State_Skill:
SetState(State_Command, true);
break;
case State_TargetAlly:
case State_TargetEnemy:
if (target_state == State_Item || target_state == State_Skill)
SetState(target_state, true);
else
SetState(State_Command, true);
break;
case State_Victory:
case State_Defeat:
Scene::Pop();
break;
}
}
}
/***************************
* State related methods *
***************************/
////////////////////////////////////////////////////////////
void Scene_Battle2k::SetState(Scene_Battle2k::State new_state, bool cancel) {
if (state == new_state)
return;
/* Terminate previus state interface*/
switch (state) {
case State_Start:
//TODO?
break;
case State_Options:
options_window->SetActive(false);
break;
case State_Battle:
//TODO?
break;
case State_AutoBattle:
//TODO?
break;
case State_Command:
//TODO?
break;
case State_Item:
item_window->SetActive(false);
item_window->SetVisible(false);
break;
case State_Skill:
skill_window->SetActive(false);
skill_window->SetVisible(false);
break;
case State_TargetEnemy:
if (enemytarget_window != 0){
enemytarget_window->SetActive(false);
enemytarget_window->SetVisible(false);
}
break;
case State_TargetAlly:
status_window->SetActorSelection(false);
status_window->SetActive(false);
status_window->SetZ(1000);
break;
case State_Action:
//TODO?
break;
case State_Victory:
//TODO?
break;
case State_Defeat:
//TODO?
break;
}
state = new_state;
/* Initialize new state interface*/
std::vector<std::string> enemy_names; //For State_TargetEnemy
switch (state) {
case State_Start:
//TODO:: show initial message;
break;
case State_Options:
printf("State Options\n");
options_window->SetActive(true);
break;
case State_Battle:
printf("State Battle\n");
status_window->SetActiveCharacter(-1);
break;
case State_AutoBattle:
printf("State AutoBatle: not implemented\n");
SetState(State_Options);
break;
case State_Command:
printf("State Command ");
if (cancel){
status_window->SetActiveCharacter(status_window->GetActiveCharacter() - 1);
actions.pop_back();
}
else
status_window->SetActiveCharacter(status_window->GetActiveCharacter() + 1);
command_window->SetActor(status_window->GetActiveCharacter());
printf("- Current Character: %i\n", status_window->GetActiveCharacter());
command_window->SetActive(true);
current_action.reset();
break;
case State_TargetEnemy:
printf("State TargetEnemy\n");
for (std::vector<Battle::Enemy>::iterator it = Game_Battle::enemies.begin(); it != Game_Battle::enemies.end(); it++)
if (!it->game_enemy->IsDead())
enemy_names.push_back(it->rpg_enemy->name);
enemytarget_window.reset(new Window_Command(enemy_names, 136));
enemytarget_window->SetY(160);
enemytarget_window->SetHeight(80);
enemytarget_window->SetZ(1002);
enemytarget_window->SetIndex(0);
enemytarget_window->SetVisible(true);
enemytarget_window->SetActive(true);
break;
case State_TargetAlly:
printf("State TargetAlly\n");
status_window->SetActorSelection(true);
status_window->SetActive(true);
status_window->SetIndex(0);
status_window->SetZ(1002);
break;
case State_Item:
printf("State Item\n");
item_window->SetActive(true);
item_window->Refresh();
item_window->SetVisible(true);
item_window->SetHelpWindow(help_window.get());
help_window->SetVisible(true);
break;
case State_Skill:
printf("State Skill\n");
skill_window->SetActive(true);
skill_window->SetActor(Game_Battle::GetActiveActor());
skill_window->SetIndex(0);
skill_window->SetVisible(true);
skill_window->SetHelpWindow(help_window.get());
help_window->SetVisible(true);
break;
case State_Action:
printf("State Action\n");
break;
case State_Victory:
printf("State Victory\n");
//TODO?
break;
case State_Defeat:
printf("State Defeat\n");
//TODO?
break;
}
}
/***************************
* Window related methods *
***************************/
////////////////////////////////////////////////////////////
void Scene_Battle2k::CreateWindows() {
help_window.reset(new Window_Help(0, 0, 320, 32));
help_window->SetVisible(false);
help_window->SetZ(1000);
help_window->SetActive(false);
options_window.reset(new Window_BattleOption(0, 160, 76, 80));
options_window->SetZ(1000);
options_window->SetActive(false);
status_window.reset(new Window_BattleStatus());
status_window->SetZ(1000);
status_window->SetActive(false);
command_window.reset(new Window_BattleCommand(320, 160, 76, 80));
command_window->SetZ(1000);
command_window->SetActive(false);
skill_window.reset(new Window_BattleSkill(0, 160, 320, 80));
skill_window->SetZ(1001);
skill_window->SetVisible(false);
skill_window->SetActive(false);
item_window.reset(new Window_BattleItem(0, 160, 320, 80));
item_window->SetZ(1001);
item_window->SetVisible(false);
item_window->Refresh();
item_window->SetIndex(0);
item_window->SetActive(false);
message_window.reset(new Window_Message(0, 160, 320, 80));
message_window->SetZ(1003);
message_window->SetVisible(false);
message_window->SetActive(false);
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::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));
}
}
/***************************
*Animation related methods*
***************************/
bool Scene_Battle2k::IsAnimationRuning(){
return (!animations.empty());
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::UpdateAnimations() {
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();
}
}
/* Delete finished animations */
std::deque<EASYRPG_SHARED_PTR<BattleAnimation> >::iterator end;
end = std::remove(animations.begin(), animations.end(), EASYRPG_SHARED_PTR<BattleAnimation>());
animations.erase(end, animations.end());
}
////////////////////////////////////////////////////////////
void Scene_Battle2k::ShowAnimation(int animation_id, bool enemies, Battle::Ally* ally, Battle::Enemy* enemy) {
const RPG::Animation* rpg_anim = &Data::animations[animation_id - 1];
int x, y;
if (ally != NULL) {
x = ally->sprite->GetX();
y = ally->sprite->GetY();
animations.push_back(EASYRPG_MAKE_SHARED<BattleAnimation>(x, y, rpg_anim));
return;
}
else if (enemy != NULL) {
x = enemy->sprite->GetX();
y = enemy->sprite->GetY();
animations.push_back(EASYRPG_MAKE_SHARED<BattleAnimation>(x, y, rpg_anim));
return;
}
else if (enemies) {
for (std::vector<Battle::Enemy>::iterator it = Game_Battle::enemies.begin(); it != Game_Battle::enemies.end(); it++){
if (!it->game_enemy->IsDead()){
x = it->sprite->GetX();
y = it->sprite->GetY();
animations.push_back(EASYRPG_MAKE_SHARED<BattleAnimation>(x, y, rpg_anim));
}
}
}
else {
Game_Battle::EnemiesCentroid(x, y);
animations.push_back(EASYRPG_MAKE_SHARED<BattleAnimation>(x, y, rpg_anim));
}
}
/////////////////////////////////////////////////////////////////////////////
// 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_Battle2k_H_
#define _Scene_Battle2k_H_
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "scene.h"
#include "battle_interface.h"
#include "battle_battler.h"
#include "battle_animation.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 "window_command.h"
#include "window_message.h"
#include "rpg_troopmember.h"
#include "rpg_actor.h"
#include "rpg_enemy.h"
#include "game_actor.h"
#include "game_enemy.h"
#include "drawable.h"
#include "zobj.h"
#include "background.h"
#include <deque>
#include <boost/scoped_ptr.hpp>
////////////////////////////////////////////////////////////
/// Scene_Battle2k class.
/// Manages the battles for RM2k games.
////////////////////////////////////////////////////////////
class Scene_Battle2k : public Scene, public Battle_Interface {
public:
/***************************
* Scene related methods *
***************************/
Scene_Battle2k();
~Scene_Battle2k();
void Start();
void Update();
void ProcessInput();
private:
/***************************
* Action related methods *
***************************/
struct BattleAction { //Struct: contains the information of the action for a given actor.
bool is_actor; //true-(index points to an actor) false-(index points to a enemy).
int index; //index-who executes this action.
int command_id; //0-Attack 1-Skill 2-Defend 3-Item.
int target; //index of the target(Actor or Enemy is defined by action scope).
int skill; //id of the selected skill (if any).
int item; //id the the selected item (if any).
int speed; //battle speed, to decide who attacs first (real speed+-20%).
void reset(){is_actor = true; index= -1; command_id= -1; target= -1; skill= -1;item= -1;speed= -1; };
};
BattleAction current_action; //Action if the current Actor.
std::vector<BattleAction> actions; //List of all actions used in a turn.
/***************************
* State related methods *
***************************/
enum State { //Enum: List of all posible states of the interface.
State_Start, //Start: Initial Message.
State_Options, //Options: Select 0-Fight 1-Autobattle 2-Flee.
State_Battle, //Battle: Transition beatwhen Options to Command.
State_AutoBattle, //AutoBattle: Ramdomly selects actors's actions.
State_Command, //Command: 0-Attack 1-Skill 2-Defend 3-Item.
State_Item, //Item: Chose an item.
State_Skill, //Skill: Chose a Skill.
State_TargetEnemy, //TargetEnemy: select an enemy.
State_TargetAlly, //TargetAlly: select an ally.
State_Action, //Action: animate and show battle messages.
State_Victory, //Victory: Show victory message and calculate experience and item reward.
State_Defeat //Defeat: Show defeat message and manage GameOver or event based result.
};
State state; //Current state.
State target_state; //Previus state, to return from target state.
void SetState(State new_state, bool cancel = false); //Set new_state as current state.
void UpdateState();
/***************************
* Window related methods *
***************************/ //Initialize the Windows.
boost::scoped_ptr<Window_Help> help_window; //Help window for Skill & Item windows.
boost::scoped_ptr<Window_BattleOption> options_window; //Command window: 0-Fight 1-Autobattle 2-Flee.
boost::scoped_ptr<Window_BattleStatus> status_window; //Status window: displays information for party members. Also used to target an Ally.
boost::scoped_ptr<Window_BattleCommand> command_window; //Command window: 0-Attack 1-Skill 2-Defend 3-Item.
boost::scoped_ptr<Window_BattleItem> item_window; //Item window.
boost::scoped_ptr<Window_BattleSkill> skill_window; //Skill window.
boost::scoped_ptr<Window_Command> enemytarget_window; //Command window: list of alive enemies.
boost::scoped_ptr<Window_Message> message_window; //Message Window: to display battle information.
boost::scoped_ptr<Background> background; //Current background.
void CreateWindows();
void UpdateBackground();
/***************************
*Animation related methods*
***************************/
std::deque<EASYRPG_SHARED_PTR<BattleAnimation>> animations; //List of all animations being executed.
bool Scene_Battle2k::IsAnimationRuning(); //Used to decide if animatios should be updated.
void UpdateAnimations(); //Update Animations.
void ShowAnimation(int animation_id, bool enemies, Battle::Ally* ally, Battle::Enemy* enemy); //Add an animation to the query.
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment