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 "scene_equip.h"
20 #include "game_actors.h"
21 #include "game_party.h"
22 #include "game_system.h"
23 #include "game_screen.h"
24 #include "input.h"
25 #include "player.h"
26 #include <lcf/reader_util.h>
27 #include "scene_menu.h"
28 #include <lcf/rpg/item.h>
29
Scene_Equip(Game_Actor & actor,int equip_index)30 Scene_Equip::Scene_Equip(Game_Actor& actor, int equip_index) :
31 actor(actor),
32 equip_index(equip_index) {
33 type = Scene::Equip;
34 }
35
Start()36 void Scene_Equip::Start() {
37 // Create the windows
38 help_window.reset(new Window_Help(0, 0, SCREEN_TARGET_WIDTH, 32));
39 equipstatus_window.reset(new Window_EquipStatus(0, 32, 124, 96, actor.GetId()));
40 equip_window.reset(new Window_Equip(124, 32, (SCREEN_TARGET_WIDTH-124),96, actor.GetId()));
41
42 equip_window->SetIndex(equip_index);
43
44 for (int i = 0; i < 5; ++i) {
45 item_windows.push_back(std::make_shared<Window_EquipItem>(actor.GetId(), i));
46 }
47
48 // Assign the help windows
49 for (size_t i = 0; i < item_windows.size(); ++i) {
50 item_windows[i]->SetVisible((unsigned)equip_window->GetIndex() == i);
51 item_windows[i]->SetHelpWindow(help_window.get());
52 item_windows[i]->SetActive(false);
53 item_windows[i]->Refresh();
54 }
55 equip_window->SetHelpWindow(help_window.get());
56 }
57
Update()58 void Scene_Equip::Update() {
59 help_window->Update();
60
61 UpdateEquipWindow();
62 UpdateStatusWindow();
63 UpdateItemWindows();
64
65 if (equip_window->GetActive()) {
66 UpdateEquipSelection();
67 } else if (item_window->GetActive()) {
68 UpdateItemSelection();
69 }
70 }
71
UpdateItemWindows()72 void Scene_Equip::UpdateItemWindows() {
73 for (size_t i = 0; i < item_windows.size(); ++i) {
74 item_windows[i]->SetVisible((unsigned)equip_window->GetIndex() == i);
75 item_windows[i]->Update();
76 }
77
78 item_window = item_windows[equip_window->GetIndex()];
79 }
80
UpdateEquipWindow()81 void Scene_Equip::UpdateEquipWindow() {
82 equip_window->Update();
83 }
84
UpdateStatusWindow()85 void Scene_Equip::UpdateStatusWindow() {
86 if (equip_window->GetActive()) {
87 equipstatus_window->ClearParameters();
88 } else if (item_window->GetActive()) {
89 const lcf::rpg::Item* current_item = item_window->GetItem();
90
91 const auto eidx = equip_window->GetIndex();
92
93 auto atk = actor.GetBaseAtk(Game_Battler::WeaponAll, true, false);
94 auto def = actor.GetBaseDef(Game_Battler::WeaponAll, true, false);
95 auto spi = actor.GetBaseSpi(Game_Battler::WeaponAll, true, false);
96 auto agi = actor.GetBaseAgi(Game_Battler::WeaponAll, true, false);
97
98 auto add_item = [&](const lcf::rpg::Item* item, int mod = 1) {
99 if (item) {
100 atk += item->atk_points1 * mod;
101 def += item->def_points1 * mod;
102 spi += item->spi_points1 * mod;
103 agi += item->agi_points1 * mod;
104 }
105 };
106
107 for (int i = 1; i <= 5; i++) {
108 auto* count_item = actor.GetEquipment(i);
109 add_item(count_item, 1);
110 }
111
112 auto* old_item = actor.GetEquipment(eidx + 1);
113 // If its a weapon or shield, get the other hand
114 const lcf::rpg::Item* other_old_item = nullptr;
115 if (eidx == 0) {
116 other_old_item = actor.GetEquipment(eidx + 2);
117 } else if (eidx == 1) {
118 other_old_item = actor.GetEquipment(eidx);
119 }
120
121 add_item(old_item, -1);
122 // If other hand had a two handed weapon, or we considering a 2 handed weapon, remove the other hand.
123 if (current_item && other_old_item &&
124 (other_old_item->two_handed || current_item->two_handed)) {
125 add_item(other_old_item, -1);
126 }
127 add_item(current_item, 1);
128
129 int limit = actor.MaxStatBaseValue();
130
131 atk = Utils::Clamp(atk, 1, limit);
132 def = Utils::Clamp(def, 1, limit);
133 spi = Utils::Clamp(spi, 1, limit);
134 agi = Utils::Clamp(agi, 1, limit);
135
136 atk = actor.CalcValueAfterAtkStates(atk);
137 def = actor.CalcValueAfterDefStates(def);
138 spi = actor.CalcValueAfterSpiStates(spi);
139 agi = actor.CalcValueAfterAgiStates(agi);
140
141 equipstatus_window->SetNewParameters(atk, def, spi, agi);
142
143 equipstatus_window->Refresh();
144 }
145
146 equipstatus_window->Update();
147 }
148
CanRemoveEquipment(const Game_Actor & actor,int index)149 static bool CanRemoveEquipment(const Game_Actor& actor, int index) {
150 if (actor.IsEquipmentFixed(true)) {
151 return false;
152 }
153 auto* item = actor.GetEquipment(index + 1);
154 if (item && item->cursed) {
155 return false;
156 }
157 return true;
158 }
159
UpdateEquipSelection()160 void Scene_Equip::UpdateEquipSelection() {
161 if (Input::IsTriggered(Input::CANCEL)) {
162 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel));
163 Scene::Pop();
164 } else if (Input::IsTriggered(Input::DECISION)) {
165 if (!CanRemoveEquipment(actor, equip_window->GetIndex())) {
166 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
167 return;
168 }
169
170 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
171 equip_window->SetActive(false);
172 item_window->SetActive(true);
173 item_window->SetIndex(0);
174 } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::RIGHT)) {
175 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor));
176 int actor_index = Main_Data::game_party->GetActorPositionInParty(actor.GetId());
177 actor_index = (actor_index + 1) % Main_Data::game_party->GetActors().size();
178 Scene::Push(std::make_shared<Scene_Equip>((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true);
179 } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::LEFT)) {
180 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor));
181 int actor_index = Main_Data::game_party->GetActorPositionInParty(actor.GetId());
182 actor_index = (actor_index + Main_Data::game_party->GetActors().size() - 1) % Main_Data::game_party->GetActors().size();
183 Scene::Push(std::make_shared<Scene_Equip>((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true);
184 }
185 }
186
UpdateItemSelection()187 void Scene_Equip::UpdateItemSelection() {
188 if (Input::IsTriggered(Input::CANCEL)) {
189 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel));
190 equip_window->SetActive(true);
191 item_window->SetActive(false);
192 item_window->SetIndex(-1);
193 } else if (Input::IsTriggered(Input::DECISION)) {
194 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
195
196 const lcf::rpg::Item* current_item = item_window->GetItem();
197 int current_item_id = current_item ? current_item->ID : 0;
198
199 actor.ChangeEquipment(
200 equip_window->GetIndex() + 1, current_item_id);
201
202 equip_window->SetActive(true);
203 item_window->SetActive(false);
204 item_window->SetIndex(-1);
205
206 equip_window->Refresh();
207
208 for (size_t i = 0; i < item_windows.size(); ++i) {
209 item_windows[i]->Refresh();
210 }
211 }
212 }
213