1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2004-2011 by The Allacrost Project
3 // Copyright (C) 2012-2019 by Bertram (Valyria Tear)
4 // All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "character_window.h"
12
13 #include "common/global/global.h"
14 #include "common/global/actors/global_character.h"
15
16 #include "engine/video/video.h"
17 #include "utils/ustring.h"
18
19 using namespace vt_global;
20 using namespace vt_video;
21 using namespace vt_utils;
22 using namespace vt_system;
23
24 namespace vt_common
25 {
26
27 // HP / SP bars
28 const float BAR_BASE_SIZE_X = 100.0f;
29 const float BAR_BASE_SIZE_Y = 5.0f;
30
CharacterWindow()31 CharacterWindow::CharacterWindow():
32 _char_id(vt_global::GLOBAL_CHARACTER_INVALID),
33 _hp_ratio(0.0f),
34 _sp_ratio(0.0f)
35 {
36 // Loads HP/SP icons
37 vt_global::GlobalMedia& media = vt_global::GlobalManager->Media();
38 _hp_icon = media.GetStatusIcon(vt_global::GLOBAL_STATUS_HP,
39 vt_global::GLOBAL_INTENSITY_NEUTRAL);
40 _sp_icon = media.GetStatusIcon(vt_global::GLOBAL_STATUS_SP,
41 vt_global::GLOBAL_INTENSITY_NEUTRAL);
42 }
43
SetCharacter(vt_global::GlobalCharacter * character)44 void CharacterWindow::SetCharacter(vt_global::GlobalCharacter* character)
45 {
46 if(!character || character->GetID() == vt_global::GLOBAL_CHARACTER_INVALID) {
47 _character_name.Clear();
48 _character_data.Clear();
49 _portrait = StillImage();
50 _char_id = vt_global::GLOBAL_CHARACTER_INVALID;
51 _hp_ratio = 0.0f;
52 _sp_ratio = 0.0f;
53 _UpdateActiveStatusEffects(nullptr);
54 return;
55 }
56
57 _char_id = character->GetID();
58
59 _portrait = character->GetPortrait();
60 // Only size up valid portraits
61 if(!_portrait.GetFilename().empty())
62 _portrait.SetDimensions(100.0f, 100.0f);
63
64 // the characters' name is already translated.
65 _character_name.SetText(character->GetName(), TextStyle("title22"));
66
67 // And the rest of the data
68 /// tr: level
69 ustring char_data = UTranslate("Lv: ") + MakeUnicodeString(NumberToString(character->GetExperienceLevel()) + " / ");
70 char_data += UTranslate("Next: ") + MakeUnicodeString(NumberToString(character->GetExperienceForNextLevel()) + "\n");
71 char_data += MakeUnicodeString(" " + NumberToString(character->GetHitPoints()) +
72 " / " + NumberToString(character->GetMaxHitPoints()) + "\n");
73 char_data += MakeUnicodeString(" " + NumberToString(character->GetSkillPoints()) +
74 " / " + NumberToString(character->GetMaxSkillPoints()) + "\n");
75 /// tr: experience points to be spent for skills
76 char_data += UTranslate("XP for skills: ") + MakeUnicodeString(NumberToString(character->GetUnspentExperiencePoints()));
77
78 _character_data.SetText(char_data, TextStyle("text20"));
79
80 _hp_ratio = static_cast<float>(character->GetHitPoints()) / static_cast<float>(character->GetMaxHitPoints());
81 _sp_ratio = static_cast<float>(character->GetSkillPoints()) / static_cast<float>(character->GetMaxSkillPoints());
82
83 _UpdateActiveStatusEffects(character);
84 }
85
Draw()86 void CharacterWindow::Draw()
87 {
88 // Call parent Draw method, if failed pass on fail result
89 MenuWindow::Draw();
90
91 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_TOP, 0);
92
93 // Get the window metrics
94 Position2D pos = GetPosition();
95 // Adjust the current position to make it look better
96 pos.y += 5;
97
98 // Draw character portrait
99 VideoManager->Move(pos.x + 12.0f, pos.y + 8.0f);
100 _portrait.Draw();
101
102 // Write character name
103 VideoManager->MoveRelative(150.0f, -5.0f);
104 _character_name.Draw();
105
106 if (_hp_ratio > 0.0f) {
107 VideoManager->MoveRelative(30.0f, 55.0f);
108 // HP
109 VideoManager->MoveRelative(0.0f, BAR_BASE_SIZE_Y - 2.0f);
110 VideoManager->DrawRectangle(BAR_BASE_SIZE_X, 2.0f, Color::white);
111 VideoManager->MoveRelative(0.0f, -BAR_BASE_SIZE_Y + 2.0f);
112 if (_hp_ratio < 0.25f) {
113 VideoManager->DrawRectangle(BAR_BASE_SIZE_X * _hp_ratio, BAR_BASE_SIZE_Y, Color::orange);
114 }
115 else {
116 VideoManager->DrawRectangle(BAR_BASE_SIZE_X * _hp_ratio, BAR_BASE_SIZE_Y, Color::green_hp);
117 }
118 // SP
119 VideoManager->MoveRelative(0.0f, 22.0f);
120 VideoManager->MoveRelative(0.0f, BAR_BASE_SIZE_Y - 2.0f);
121 VideoManager->DrawRectangle(BAR_BASE_SIZE_X, 2.0f, Color::white);
122 VideoManager->MoveRelative(0.0f, -BAR_BASE_SIZE_Y + 2.0f);
123 VideoManager->DrawRectangle(BAR_BASE_SIZE_X * _sp_ratio, BAR_BASE_SIZE_Y, Color::blue_sp);
124
125 VideoManager->MoveRelative(-30.0f, -77.0f);
126 }
127
128 // Level, HP, SP, XP to Next Lvl
129 VideoManager->MoveRelative(0.0f, 19.0f);
130 _character_data.Draw();
131
132 // HP/SP Icons
133 if(_char_id != vt_global::GLOBAL_CHARACTER_INVALID) {
134 VideoManager->MoveRelative(0.0f, 20.0f);
135 _hp_icon->Draw();
136 VideoManager->MoveRelative(0.0f, 20.0f);
137 _sp_icon->Draw();
138 VideoManager->MoveRelative(0.0f, -40.0f);
139 }
140
141 // Active status effects
142 VideoManager->MoveRelative(-30.0f, -17.0f);
143 uint32_t nb_effects = _active_status_effects.size();
144 for (uint32_t i = 0; i < nb_effects && i < 6; ++i) {
145 if (_active_status_effects[i])
146 _active_status_effects[i]->Draw();
147 VideoManager->MoveRelative(0.0f, 15.0f);
148 }
149
150 if (nb_effects < 6)
151 return;
152
153 // Show a second column when there are more than 6 active status effects
154 VideoManager->MoveRelative(-15.0f, -6.0f * 15.0f);
155 for (uint32_t i = 6; i < nb_effects && i < 12; ++i) {
156 if (_active_status_effects[i])
157 _active_status_effects[i]->Draw();
158 VideoManager->MoveRelative(0.0f, 15.0f);
159 }
160
161 if (nb_effects < 12)
162 return;
163
164 // Show a third column when there are more than 12 active status effects
165 // (maximum 15)
166 VideoManager->MoveRelative(-15.0f, -6.0f * 15.0f);
167 for (uint32_t i = 12; i < nb_effects; ++i) {
168 if (_active_status_effects[i])
169 _active_status_effects[i]->Draw();
170 VideoManager->MoveRelative(0.0f, 15.0f);
171 }
172 }
173
_UpdateActiveStatusEffects(vt_global::GlobalCharacter * character)174 void CharacterWindow::_UpdateActiveStatusEffects(vt_global::GlobalCharacter* character)
175 {
176 _active_status_effects.clear();
177 if (!character)
178 return;
179
180 GlobalMedia& media = GlobalManager->Media();
181
182 const std::vector<ActiveStatusEffect> effects =
183 character->GetActiveStatusEffects();
184 for (uint32_t i = 0; i < effects.size(); ++i) {
185 GLOBAL_STATUS status = effects[i].GetEffect();
186 GLOBAL_INTENSITY intensity = effects[i].GetIntensity();
187 if (status != GLOBAL_STATUS_INVALID &&
188 intensity != GLOBAL_INTENSITY_NEUTRAL) {
189 StillImage* image = media.GetStatusIcon(status, intensity);
190 if (image)
191 _active_status_effects.push_back(image);
192 }
193 }
194 }
195
196 } // namespace vt_common
197