1 /*
2 * This file is part of Dune Legacy.
3 *
4 * Dune Legacy 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 2 of the License, or
7 * (at your option) any later version.
8 *
9 * Dune Legacy 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 Dune Legacy. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <Menu/MentatMenu.h>
19
20 #include <globals.h>
21
22 #include <FileClasses/GFXManager.h>
23
24 #include <mmath.h>
25
26 #include <algorithm>
27
MentatMenu(int newHouse)28 MentatMenu::MentatMenu(int newHouse)
29 : MenuBase(), currentMentatTextIndex(-1), nextMentatTextSwitch(0)
30 {
31 nextSpecialAnimation = SDL_GetTicks() + getRandomInt(8000, 20000);
32
33 Animation* anim;
34
35 disableQuiting(true);
36 house = newHouse;
37
38 // set up window
39 SDL_Texture *pBackground;
40 if(house == HOUSE_INVALID) {
41 pBackground = pGFXManager->getUIGraphic(UI_MentatBackgroundBene);
42 } else {
43 pBackground = pGFXManager->getUIGraphic(UI_MentatBackground,house);
44 }
45
46 setBackground(pBackground, false);
47
48 setCurrentPosition(calcAlignedDrawingRect(pBackground, HAlign::Center, VAlign::Center));
49
50 setWindowWidget(&windowWidget);
51
52 switch(house) {
53 case HOUSE_HARKONNEN: {
54 anim = pGFXManager->getAnimation(Anim_HarkonnenEyes);
55 eyesAnim.setAnimation(anim);
56 windowWidget.addWidget(&eyesAnim,Point(64,176),eyesAnim.getMinimumSize());
57
58 anim = pGFXManager->getAnimation(Anim_HarkonnenMouth);
59 mouthAnim.setAnimation(anim);
60 windowWidget.addWidget(&mouthAnim,Point(64,208),mouthAnim.getMinimumSize());
61
62 anim = pGFXManager->getAnimation(Anim_HarkonnenShoulder);
63 shoulderAnim.setAnimation(anim);
64 // don't add shoulderAnim, draw it in DrawSpecificStuff
65 } break;
66
67 case HOUSE_ATREIDES: {
68 anim = pGFXManager->getAnimation(Anim_AtreidesEyes);
69 eyesAnim.setAnimation(anim);
70 windowWidget.addWidget(&eyesAnim,Point(80,160),eyesAnim.getMinimumSize());
71
72 anim = pGFXManager->getAnimation(Anim_AtreidesMouth);
73 mouthAnim.setAnimation(anim);
74 windowWidget.addWidget(&mouthAnim,Point(80,192),mouthAnim.getMinimumSize());
75
76 anim = pGFXManager->getAnimation(Anim_AtreidesBook);
77 specialAnim.setAnimation(anim);
78 windowWidget.addWidget(&specialAnim,Point(145,305),specialAnim.getMinimumSize());
79
80 anim = pGFXManager->getAnimation(Anim_AtreidesShoulder);
81 shoulderAnim.setAnimation(anim);
82 // don't add shoulderAnim, draw it in DrawSpecificStuff
83 } break;
84
85 case HOUSE_ORDOS: {
86 anim = pGFXManager->getAnimation(Anim_OrdosEyes);
87 eyesAnim.setAnimation(anim);
88 windowWidget.addWidget(&eyesAnim,Point(32,160),eyesAnim.getMinimumSize());
89
90 anim = pGFXManager->getAnimation(Anim_OrdosMouth);
91 mouthAnim.setAnimation(anim);
92 windowWidget.addWidget(&mouthAnim,Point(32,192),mouthAnim.getMinimumSize());
93
94 anim = pGFXManager->getAnimation(Anim_OrdosRing);
95 specialAnim.setAnimation(anim);
96 specialAnim.getAnimation()->setCurrentFrameNumber(specialAnim.getAnimation()->getNumberOfFrames()-1);
97 windowWidget.addWidget(&specialAnim,Point(178,289),specialAnim.getMinimumSize());
98
99 anim = pGFXManager->getAnimation(Anim_OrdosShoulder);
100 shoulderAnim.setAnimation(anim);
101 // don't add shoulderAnim, draw it in DrawSpecificStuff
102 } break;
103
104 case HOUSE_FREMEN: {
105 anim = pGFXManager->getAnimation(Anim_FremenEyes);
106 eyesAnim.setAnimation(anim);
107 windowWidget.addWidget(&eyesAnim,Point(80,160),eyesAnim.getMinimumSize());
108
109 anim = pGFXManager->getAnimation(Anim_FremenMouth);
110 mouthAnim.setAnimation(anim);
111 windowWidget.addWidget(&mouthAnim,Point(80,192),mouthAnim.getMinimumSize());
112
113 anim = pGFXManager->getAnimation(Anim_FremenBook);
114 specialAnim.setAnimation(anim);
115 windowWidget.addWidget(&specialAnim,Point(145,305),specialAnim.getMinimumSize());
116
117 anim = pGFXManager->getAnimation(Anim_FremenShoulder);
118 shoulderAnim.setAnimation(anim);
119 // don't add shoulderAnim, draw it in DrawSpecificStuff
120 } break;
121
122 case HOUSE_SARDAUKAR: {
123 anim = pGFXManager->getAnimation(Anim_SardaukarEyes);
124 eyesAnim.setAnimation(anim);
125 windowWidget.addWidget(&eyesAnim,Point(64,176),eyesAnim.getMinimumSize());
126
127 anim = pGFXManager->getAnimation(Anim_SardaukarMouth);
128 mouthAnim.setAnimation(anim);
129 windowWidget.addWidget(&mouthAnim,Point(64,208),mouthAnim.getMinimumSize());
130
131 anim = pGFXManager->getAnimation(Anim_SardaukarShoulder);
132 shoulderAnim.setAnimation(anim);
133 // don't add shoulderAnim, draw it in DrawSpecificStuff
134 } break;
135
136 case HOUSE_MERCENARY: {
137 anim = pGFXManager->getAnimation(Anim_MercenaryEyes);
138 eyesAnim.setAnimation(anim);
139 windowWidget.addWidget(&eyesAnim,Point(32,160),eyesAnim.getMinimumSize());
140
141 anim = pGFXManager->getAnimation(Anim_MercenaryMouth);
142 mouthAnim.setAnimation(anim);
143 windowWidget.addWidget(&mouthAnim,Point(32,192),mouthAnim.getMinimumSize());
144
145 anim = pGFXManager->getAnimation(Anim_MercenaryRing);
146 specialAnim.setAnimation(anim);
147 specialAnim.getAnimation()->setCurrentFrameNumber(specialAnim.getAnimation()->getNumberOfFrames()-1);
148 windowWidget.addWidget(&specialAnim,Point(178,289),specialAnim.getMinimumSize());
149
150 anim = pGFXManager->getAnimation(Anim_MercenaryShoulder);
151 shoulderAnim.setAnimation(anim);
152 // don't add shoulderAnim, draw it in DrawSpecificStuff
153 } break;
154
155 default: {
156 // bene gese
157 anim = pGFXManager->getAnimation(Anim_BeneEyes);
158 eyesAnim.setAnimation(anim);
159 windowWidget.addWidget(&eyesAnim,Point(128,160),eyesAnim.getMinimumSize());
160
161 anim = pGFXManager->getAnimation(Anim_BeneMouth);
162 mouthAnim.setAnimation(anim);
163 windowWidget.addWidget(&mouthAnim,Point(112,192),mouthAnim.getMinimumSize());
164 } break;
165 }
166
167 textLabel.setTextColor(COLOR_WHITE, COLOR_TRANSPARENT);
168 textLabel.setAlignment((Alignment_Enum) (Alignment_Left | Alignment_Top));
169 textLabel.setVisible(false);
170 }
171
~MentatMenu()172 MentatMenu::~MentatMenu() {
173 }
174
update()175 void MentatMenu::update() {
176 // speedup blink of the eye
177 eyesAnim.getAnimation()->setFrameRate((eyesAnim.getAnimation()->getCurrentFrameNumber() == MentatEyesClosed) ? 4.0 : 0.5);
178
179 if(SDL_GetTicks() > nextMentatTextSwitch) {
180 currentMentatTextIndex++;
181
182 std::string text;
183 if(currentMentatTextIndex >= (int) mentatTexts.size()) {
184 onMentatTextFinished();
185 nextMentatTextSwitch = 0xFFFFFFFF;
186 text = "";
187 } else {
188 text = mentatTexts[currentMentatTextIndex];
189 if(text.empty()) {
190 onMentatTextFinished();
191 nextMentatTextSwitch = 0xFFFFFFFF;
192 currentMentatTextIndex = mentatTexts.size();
193 } else {
194 nextMentatTextSwitch = SDL_GetTicks() + text.length() * 75 + 1000;
195 }
196 }
197
198 mouthAnim.getAnimation()->setNumLoops(text.empty() ? 0 : text.length()/25 + 1);
199
200 textLabel.setText(text);
201 textLabel.setVisible(true);
202 textLabel.resize(620,240);
203 }
204
205 if(specialAnim.getAnimation() != nullptr && specialAnim.getAnimation()->isFinished()) {
206 if(nextSpecialAnimation < SDL_GetTicks()) {
207 specialAnim.getAnimation()->setNumLoops(1);
208 nextSpecialAnimation = SDL_GetTicks() + getRandomInt(8000, 20000);
209 }
210 }
211
212 const Point mouse(drawnMouseX - getPosition().x, drawnMouseY - getPosition().y);
213 bool bPressed = (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(SDL_BUTTON_LEFT));
214
215 const Point eyesPos = windowWidget.getWidgetPosition(&eyesAnim);
216 const Point& eyesSize = eyesAnim.getSize();
217 const Point eyesCenter = eyesPos + eyesSize/2;
218 const Point mouseEyePos = mouse - eyesCenter;
219
220 eyesAnim.getAnimation()->resetFrameOverride();
221
222 if((mouseEyePos.x >= -eyesSize.x/2 - 30) && (mouseEyePos.x <= -eyesSize.x/2) && (mouseEyePos.y >= -eyesSize.y/2 - 20) && (mouseEyePos.y <= eyesSize.y/2)) {
223 eyesAnim.getAnimation()->setFrameOverride(MentatEyesLeft);
224 } else if((mouseEyePos.x <= eyesSize.x/2 + 30) && (mouseEyePos.x >= eyesSize.x/2) && (mouseEyePos.y >= -eyesSize.y/2 - 20) && (mouseEyePos.y <= eyesSize.y/2)) {
225 eyesAnim.getAnimation()->setFrameOverride(MentatEyesRight);
226 } else if((abs(mouseEyePos.x) < eyesSize.x) && (mouseEyePos.y >= -eyesSize.y/2 - 20) && (mouseEyePos.y <= eyesSize.y/2)) {
227 eyesAnim.getAnimation()->setFrameOverride(MentatEyesNormal);
228 } else if((abs(mouseEyePos.x) < eyesSize.x) && (mouseEyePos.y > eyesSize.y/2) && (mouseEyePos.y <= eyesSize.y/2 + 15)) {
229 eyesAnim.getAnimation()->setFrameOverride(MentatEyesDown);
230 }
231
232 if(bPressed && (abs(mouseEyePos.x) <= eyesSize.x/2) && (abs(mouseEyePos.y) <= eyesSize.y/2)) {
233 eyesAnim.getAnimation()->setFrameOverride(MentatEyesClosed);
234 }
235
236 const Point mouthPos = windowWidget.getWidgetPosition(&mouthAnim);
237 const Point& mouthSize = mouthAnim.getSize();
238 const Point mouthCenter = mouthPos + mouthSize/2;
239 const Point mouseMouthPos = mouse - mouthCenter;
240
241 if(bPressed) {
242 if((abs(mouseMouthPos.x) <= mouthSize.x/2) && (abs(mouseMouthPos.y) <= mouthSize.y/2)) {
243 if(mouthAnim.getAnimation()->getCurrentFrameOverride() == INVALID_FRAME) {
244 mouthAnim.getAnimation()->setFrameOverride(getRandomOf(4, MentatMouthOpen1, MentatMouthOpen2, MentatMouthOpen3, MentatMouthOpen4));
245 }
246 } else {
247 mouthAnim.getAnimation()->resetFrameOverride();
248 }
249 } else {
250 mouthAnim.getAnimation()->resetFrameOverride();
251 }
252 }
253
drawSpecificStuff()254 void MentatMenu::drawSpecificStuff() {
255 Point shoulderPos;
256 switch(house) {
257 case HOUSE_HARKONNEN:
258 case HOUSE_SARDAUKAR: {
259 shoulderPos = Point(256,209) + getPosition();
260 } break;
261
262 case HOUSE_ATREIDES:
263 case HOUSE_FREMEN: {
264 shoulderPos = Point(256,257) + getPosition();
265 } break;
266
267 case HOUSE_ORDOS:
268 case HOUSE_MERCENARY: {
269 shoulderPos = Point(256,257) + getPosition();
270 } break;
271
272 default: {
273 shoulderPos = Point(256,257) + getPosition();
274 } break;
275 }
276
277 shoulderAnim.draw(shoulderPos);
278 textLabel.draw(Point(10,5) + getPosition());
279 }
280
281
282
getMissionSpecificAnim(int missionnumber) const283 int MentatMenu::getMissionSpecificAnim(int missionnumber) const {
284
285 static const int missionnumber2AnimID[] = { Anim_ConstructionYard,
286 Anim_Harvester,
287 Anim_Radar,
288 Anim_Quad,
289 Anim_Tank,
290 Anim_RepairYard,
291 Anim_HeavyFactory,
292 Anim_IX,
293 Anim_Palace,
294 Anim_Sardaukar };
295
296 if(missionnumber < 0 || missionnumber > 9) {
297 return missionnumber2AnimID[0];
298 } else {
299 return missionnumber2AnimID[missionnumber];
300 }
301 }
302