1 /*
2  * This file is part of EasyRPG Player.
3  *
4  * EasyRPG Player is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * EasyRPG Player is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 // Headers
19 #include <lcf/data.h>
20 #include "color.h"
21 #include "cache.h"
22 #include "input.h"
23 #include "player.h"
24 #include "game_system.h"
25 #include "game_actors.h"
26 #include "window_battlecommand.h"
27 #include "bitmap.h"
28 
Window_BattleCommand(int x,int y,int width,int height)29 Window_BattleCommand::Window_BattleCommand(int x, int y, int width, int height) :
30 	Window_Base(x, y, width, height) {
31 
32 	SetActor(0);
33 
34 	disabled.resize(commands.size());
35 	index = -1;
36 	top_row = 0;
37 	cycle = 0;
38 
39 	SetContents(Bitmap::Create(width - 16, height - 16));
40 
41 	num_rows = contents->GetHeight() / 16;
42 
43 	Refresh();
44 }
45 
SetEnabled(int index,bool enabled)46 void Window_BattleCommand::SetEnabled(int index, bool enabled) {
47 	disabled[index] = enabled;
48 	Refresh();
49 }
50 
SetActive(bool active)51 void Window_BattleCommand::SetActive(bool active) {
52 	index = active ? 0 : -1;
53 	top_row = 0;
54 	Window::SetActive(active);
55 	Refresh();
56 }
57 
Update()58 void Window_BattleCommand::Update() {
59 	Window_Base::Update();
60 
61 	size_t num_commands = commands.size();
62 	int old_index = index;
63 	if (active && num_commands > 0 && index >= 0) {
64 		if (Input::IsRepeated(Input::DOWN) || Input::IsTriggered(Input::SCROLL_DOWN)) {
65 			Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor));
66 			index++;
67 		}
68 
69 		if (Input::IsRepeated(Input::UP) || Input::IsTriggered(Input::SCROLL_UP)) {
70 			Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor));
71 			index--;
72 		}
73 
74 		index += num_commands;
75 		index %= num_commands;
76 
77 		if (index < top_row)
78 			top_row = index;
79 		if (index > top_row + num_rows - 1)
80 			top_row = index - num_rows + 1;
81 
82 		cycle++;
83 		if (cycle % 20 == 0 || old_index != index)
84 			Refresh();
85 	}
86 
87 	UpdateCursorRect();
88 }
89 
UpdateCursorRect()90 void Window_BattleCommand::UpdateCursorRect() {
91 	if (index >= 0)
92 		SetCursorRect(Rect(0, (index - top_row) * 16, contents->GetWidth(), 16));
93 	else
94 		SetCursorRect(Rect());
95 }
96 
Refresh()97 void Window_BattleCommand::Refresh() {
98 	if (!contents)
99 		return;
100 
101 	size_t num_commands = commands.size();
102 
103 	contents->Clear();
104 	for (unsigned int i = 0; i < num_commands; i++) {
105 		Font::SystemColor color = disabled[i] ? Font::ColorDisabled : Font::ColorDefault;
106 		DrawItem(i, color);
107 	}
108 
109 	SetUpArrow(false);
110 	SetDownArrow(false);
111 	if (active && (cycle / 20) % 2 == 0) {
112 		if (top_row > 0)
113 			SetUpArrow(true);
114 		if (top_row + num_rows < (int) num_commands)
115 			SetDownArrow(true);
116 	}
117 }
118 
DrawItem(int index,Font::SystemColor color)119 void Window_BattleCommand::DrawItem(int index, Font::SystemColor color) {
120 	int y = 16 * (index - top_row);
121 	if (y < 0 || y + 16 > contents->GetHeight())
122 		return;
123 	contents->ClearRect(Rect(0, y, contents->GetWidth(), 16));
124 	contents->TextDraw(2, y + 2, color, commands[index]);
125 }
126 
GetIndex()127 int Window_BattleCommand::GetIndex() {
128 	return index;
129 }
130 
SetIndex(int _index)131 void Window_BattleCommand::SetIndex(int _index) {
132 	index = _index;
133 }
134 
SetActor(int _actor_id)135 void Window_BattleCommand::SetActor(int _actor_id) {
136 	actor_id = (Player::IsRPG2k()) ? 0 : _actor_id;
137 	commands.clear();
138 
139 	if (actor_id == 0) {
140 		commands.push_back(!lcf::Data::terms.command_attack.empty() ? ToString(lcf::Data::terms.command_attack) : "Attack");
141 		commands.push_back(!lcf::Data::terms.command_defend.empty() ? ToString(lcf::Data::terms.command_defend) : "Defend");
142 		commands.push_back(!lcf::Data::terms.command_item.empty() ? ToString(lcf::Data::terms.command_item) : "Item");
143 		commands.push_back(!lcf::Data::terms.command_skill.empty() ? ToString(lcf::Data::terms.command_skill) : "Skill");
144 	}
145 	else {
146 		Game_Actor* actor = Main_Data::game_actors->GetActor(actor_id);
147 		const std::vector<const lcf::rpg::BattleCommand*> bcmds = actor->GetBattleCommands();
148 		for (const lcf::rpg::BattleCommand* command : bcmds) {
149 			commands.push_back(ToString(command->name));
150 		}
151 	}
152 
153 	disabled.resize(commands.size());
154 	Refresh();
155 }
156 
GetSkillSubset()157 int Window_BattleCommand::GetSkillSubset() {
158 	if (actor_id == 0)
159 		return lcf::rpg::Skill::Type_normal;
160 
161 	Game_Actor* actor = Main_Data::game_actors->GetActor(actor_id);
162 	const std::vector<const lcf::rpg::BattleCommand*> bcmds = actor->GetBattleCommands();
163 	int bcmd = bcmds[index]->ID;
164 
165 	int idx = 4;
166 	for (int i = 0; i < bcmd - 1; i++) {
167 		const lcf::rpg::BattleCommand& command = lcf::Data::battlecommands.commands[i];
168 		if (command.type == lcf::rpg::BattleCommand::Type_subskill)
169 			idx++;
170 	}
171 
172 	return idx;
173 }
174