1 /*
2 BStone: A Source port of
3 Blake Stone: Aliens of Gold and Blake Stone: Planet Strike
4
5 Copyright (c) 1992-2013 Apogee Entertainment, LLC
6 Copyright (c) 2013-2015 Boris I. Bendovsky (bibendovsky@hotmail.com)
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24
25 #include "3d_def.h"
26
27
28 void VH_UpdateScreen();
29
30 void TakeDamage(
31 int16_t points,
32 objtype* attacker);
33
34 void SetPlaneViewSize();
35
36 void HealSelf(
37 int16_t points);
38
39 void GiveWeapon(
40 int weapon);
41
42 void DrawScore();
43 void SetPlaneViewSize();
44
45
46 /*
47 =============================================================================
48
49 LOCAL CONSTANTS
50
51 =============================================================================
52 */
53
54 #define VIEWTILEX (viewwidth / 16)
55 #define VIEWTILEY (viewheight / 16)
56
57
58 /*
59 =============================================================================
60
61 GLOBAL VARIABLES
62
63 =============================================================================
64 */
65
66 bool ForceLoadDefault = false;
67
68 int16_t DebugKeys();
69
70
71 /*
72 =============================================================================
73
74 LOCAL VARIABLES
75
76 =============================================================================
77 */
78
79 bool PP_step = false;
80
81 int16_t maporgx;
82 int16_t maporgy;
83
84 void ViewMap();
85
86
DebugMemory()87 void DebugMemory()
88 {
89 ::CenterWindow(22, 15);
90
91 ::US_Print("k\nTics :");
92 ::US_PrintUnsigned(tics);
93 ::US_Print("\nReal Tics :");
94 ::US_PrintUnsigned(realtics);
95
96 if ((gamestate.flags & GS_DRAW_CEILING) != 0) {
97 ::US_Print("\n\nCeiling TEX: ");
98 ::US_PrintUnsigned(CeilingTile - START_TEXTURES);
99
100 ::US_Print(" Floor TEX: ");
101 ::US_PrintUnsigned(FloorTile - START_TEXTURES);
102 } else {
103 ::US_Print("\n\nTop COL: ");
104 ::US_PrintUnsigned(TopColor & 0xFF);
105
106 ::US_Print(" Bottom COL: ");
107 ::US_PrintUnsigned(BottomColor & 0xFF);
108 }
109
110 if ((gamestate.flags & GS_LIGHTING) != 0) {
111 ::US_Print("\nShade div :");
112 ::US_PrintUnsigned(normalshade_div);
113
114 ::US_Print("\nShade max :");
115 ::US_PrintUnsigned(shade_max);
116 }
117
118 VW_UpdateScreen();
119 ::IN_Ack();
120
121 ::WindowW = 253;
122 ::WindowH = 8;
123 ::fontnumber = 2;
124
125 ::LatchDrawPic(0, 0, TOP_STATUSBARPIC);
126 ::ShadowPrintLocationText(sp_normal);
127 }
128
CountObjects()129 void CountObjects()
130 {
131 int16_t i, total, count, active, inactive, doors;
132 objtype* obj;
133
134 CenterWindow(16, 7);
135 active = inactive = count = doors = 0;
136
137 US_Print("Total statics :");
138 total = static_cast<int16_t>(laststatobj - &statobjlist[0]);
139 US_PrintUnsigned(total);
140
141 US_Print("\nIn use statics:");
142 for (i = 0; i < total; i++) {
143 if (statobjlist[i].shapenum != -1) {
144 count++;
145 } else {
146 doors++; // debug
147 }
148 }
149 US_PrintUnsigned(count);
150
151 US_Print("\nDoors :");
152 US_PrintUnsigned(doornum);
153
154 for (obj = player->next; obj; obj = obj->next) {
155 if (obj->active) {
156 active++;
157 } else {
158 inactive++;
159 }
160 }
161
162 US_Print("\nTotal actors :");
163 US_PrintUnsigned(active + inactive);
164
165 US_Print("\nActive actors :");
166 US_PrintUnsigned(active);
167
168 VW_UpdateScreen();
169 IN_Ack();
170 }
171
CountTotals()172 void CountTotals()
173 {
174 CenterWindow(20, 11);
175
176 US_Print(" CURRENT MAP TOTALS\n");
177
178 US_Print("\nTotal Enemy:\n");
179 US_PrintUnsigned(gamestuff.level[gamestate.mapon].stats.total_enemy);
180
181 US_Print("\nTotal Points:\n");
182 US_PrintUnsigned(gamestuff.level[gamestate.mapon].stats.total_points);
183
184 US_Print("\nTotal Informants:\n");
185 US_PrintUnsigned(gamestuff.level[gamestate.mapon].stats.total_inf);
186
187 VW_UpdateScreen();
188 IN_Ack();
189 }
190
ShowMap()191 void ShowMap()
192 {
193 objtype old_player;
194
195 memcpy(&old_player, player, sizeof(objtype));
196 player->angle = 90;
197 player->x = player->y = ((int32_t)32 << TILESHIFT) + (TILEGLOBAL / 2);
198
199 CenterWindow(20, 11);
200
201 US_CPrint("CURRENT MAP\n\n ");
202
203 auto old_flags = ::ExtraRadarFlags;
204 ::ExtraRadarFlags |= OV_ACTORS | OV_PUSHWALLS;
205
206 ShowOverhead(160 - 32, py, 32, 0, OV_ACTORS | OV_SHOWALL | OV_KEYS | OV_PUSHWALLS);
207 VW_UpdateScreen();
208
209 ::ExtraRadarFlags = old_flags;
210
211 memcpy(player, &old_player, sizeof(objtype));
212 IN_Ack();
213 }
214
215
216 // ---------------------------------------------------------------------------
217 // IncRange - Incs a value to a MAX value (including max value)
218 //
219 // NOTE: Assumes that 0 is the lowest value
220 // ---------------------------------------------------------------------------
IncRange(uint16_t Value,uint16_t MaxValue)221 uint16_t IncRange(
222 uint16_t Value,
223 uint16_t MaxValue)
224 {
225 if (Value == MaxValue) {
226 Value = 0;
227 } else {
228 Value++;
229 }
230
231 return Value;
232 }
233
234 // ---------------------------------------------------------------------------
235 // DecRange - Decs a value to 0 and resets to MAX_VALUE
236 //
237 // NOTE: Assumes that 0 is the lowest value
238 // ---------------------------------------------------------------------------
DecRange(uint16_t Value,uint16_t MaxValue)239 uint16_t DecRange(
240 uint16_t Value,
241 uint16_t MaxValue)
242 {
243 if (Value == 0) {
244 Value = MaxValue;
245 } else {
246 Value--;
247 }
248
249 return Value;
250 }
251
252
DebugKeys()253 int16_t DebugKeys()
254 {
255 char string[3];
256 bool esc;
257 int16_t level;
258
259 if (Keyboard[ScanCode::sc_a]) { // A = Show Actors on AutoMap
260 ExtraRadarFlags ^= OV_ACTORS;
261 CenterWindow(24, 3);
262 if (ExtraRadarFlags & OV_ACTORS) {
263 US_PrintCentered("AUTOMAP: Show Actors ON");
264 } else {
265 US_PrintCentered("AUTOMAP: Show Actors OFF");
266 }
267 VW_UpdateScreen();
268 IN_Ack();
269 return 1;
270 }
271
272 if (Keyboard[ScanCode::sc_k]) { // K = Map Content totals
273 CountTotals();
274 return 1;
275 } else if (Keyboard[ScanCode::sc_c]) { // C = count objects
276 CountObjects();
277 return 1;
278 } else if (Keyboard[ScanCode::sc_r]) { // R = show full map
279 ShowMap();
280 return 1;
281 } else if (Keyboard[ScanCode::sc_d]) { // D = Dumb/Blind Objects (Player Invisable)
282 CenterWindow(19, 3);
283 ::PlayerInvisable = !::PlayerInvisable;
284 if (PlayerInvisable) {
285 US_PrintCentered("Player Invisible!");
286 } else {
287 US_PrintCentered("Player visible");
288 }
289
290 VW_UpdateScreen();
291 IN_Ack();
292 return 1;
293 } else if (Keyboard[ScanCode::sc_e]) { // E = Win Mission
294 CenterWindow(19, 3);
295 US_PrintCentered("Instant Wiener!");
296 InstantWin = 1;
297 playstate = ex_victorious;
298 VW_UpdateScreen();
299 IN_Ack();
300 return 1;
301 } else if (Keyboard[ScanCode::sc_f]) { // F = facing spot
302 CenterWindow(18, 5);
303 US_Print("X:");
304 US_PrintUnsigned(player->x);
305 US_Print(" ");
306 US_PrintUnsigned(player->x >> TILESHIFT);
307 US_Print("\nY:");
308 US_PrintUnsigned(player->y);
309 US_Print(" ");
310 US_PrintUnsigned(player->y >> TILESHIFT);
311 US_Print("\nA:");
312 US_PrintUnsigned(player->angle);
313 US_Print("\nD:");
314 US_PrintUnsigned(player->dir);
315 VW_UpdateScreen();
316 IN_Ack();
317 return 1;
318 }
319
320 if (Keyboard[ScanCode::sc_g]) { // G = god mode
321 CenterWindow(12, 2);
322 if (godmode) {
323 US_PrintCentered("God mode OFF");
324 } else {
325 US_PrintCentered("God mode ON");
326 }
327 VW_UpdateScreen();
328 IN_Ack();
329 ::godmode = !::godmode;
330 return 1;
331 }
332
333
334 if (Keyboard[ScanCode::sc_h]) { // H = hurt self
335 IN_ClearKeysDown();
336 TakeDamage(1, nullptr);
337 } else if (Keyboard[ScanCode::sc_i]) { // I = item cheat
338 CenterWindow(12, 3);
339 US_PrintCentered("Free items!");
340 VW_UpdateScreen();
341 HealSelf(99);
342 GiveToken(5);
343
344 const auto n = static_cast<int16_t>(::is_ps() ? wp_bfg_cannon : wp_grenade);
345
346 for (int i = wp_autocharge; i <= n; i++) {
347 if (!(gamestate.weapons & (1 << i))) {
348 GiveWeapon(i);
349 break;
350 }
351 }
352
353 gamestate.ammo += 50;
354 if (gamestate.ammo > MAX_AMMO) {
355 gamestate.ammo = MAX_AMMO;
356 }
357 DrawAmmo(true);
358 DrawScore();
359 IN_Ack();
360 return 1;
361 } else if (Keyboard[ScanCode::sc_m]) { // M = memory info
362 DebugMemory();
363 return 1;
364 }
365 else if (Keyboard[ScanCode::sc_q]) { // Q = fast quit
366 Quit();
367 }
368 else if (Keyboard[ScanCode::sc_o]) { // O = Show Push Walls
369 ExtraRadarFlags ^= OV_PUSHWALLS;
370 CenterWindow(24, 3);
371 if (ExtraRadarFlags & OV_PUSHWALLS) {
372 US_PrintCentered("AUTOMAP: Show PWalls ON");
373 } else {
374 US_PrintCentered("AUTOMAP: Show PWalls OFF");
375 }
376 VW_UpdateScreen();
377 IN_Ack();
378 return 1;
379 } else if (Keyboard[ScanCode::sc_u]) { // Unlock All Floors
380 CenterWindow(24, 3);
381 US_PrintCentered("Unlock All Floors!");
382 VW_UpdateScreen();
383 IN_Ack();
384
385 for (int i = 0; i < ::MAPS_WITH_STATS; ++i) {
386 gamestuff.level[i].locked = false;
387 }
388
389 return 1;
390 } else if (Keyboard[ScanCode::sc_s]) { // S = slow motion
391 ::singlestep = !::singlestep;
392 CenterWindow(18, 3);
393 if (singlestep) {
394 US_PrintCentered("Slow motion ON");
395 } else {
396 US_PrintCentered("Slow motion OFF");
397 }
398 VW_UpdateScreen();
399 IN_Ack();
400 return 1;
401 } else if (Keyboard[ScanCode::sc_w]) { // W = warp to level
402 ForceLoadDefault = Keyboard[ScanCode::sc_left_shift] | Keyboard[ScanCode::sc_right_shift] | Keyboard[ScanCode::sc_caps_lock];
403
404 CenterWindow(26, 5);
405 PrintY += 6;
406 if (ForceLoadDefault) {
407 US_Print(" --- LOAD DEFAULT ---\n");
408 }
409 US_Print(" Current map: ");
410 US_PrintUnsigned(gamestate.mapon);
411 US_Print("\n Enter map number: ");
412 VW_UpdateScreen();
413 esc = !US_LineInput(px, py, string, nullptr, true, 2, 0);
414 if (!esc && string[0] != '\0') {
415 const int MAX_WARP_LEVEL = (::is_aog() ? 10 : 23);
416 level = static_cast<int16_t>(atoi(string));
417 if (level > -1 && level <= MAX_WARP_LEVEL) {
418 gamestate.lastmapon = gamestate.mapon;
419 playstate = ex_warped;
420 if (ForceLoadDefault) {
421 BONUS_QUEUE = 0;
422 BONUS_SHOWN = 0;
423 }
424 gamestate.mapon = level - 1;
425 }
426 }
427 return 1;
428 } else if (Keyboard[ScanCode::sc_home]) { // Dec top color
429 if (gamestate.flags & GS_DRAW_CEILING) {
430 CeilingTile = DecRange(CeilingTile, static_cast<uint16_t>(NUM_TILES - 1));
431 SetPlaneViewSize(); // Init new textures
432 return 1;
433 } else {
434 TopColor = DecRange((TopColor & 0xff), 0xff);
435 TopColor |= (TopColor << 8);
436 }
437 } else if (Keyboard[ScanCode::sc_page_up]) { // Inc top color
438 if (gamestate.flags & GS_DRAW_CEILING) {
439 CeilingTile = IncRange(CeilingTile, static_cast<uint16_t>(NUM_TILES - 1));
440 SetPlaneViewSize(); // Init new textures
441 return 1;
442 } else {
443 TopColor = IncRange((TopColor & 0xff), 0xff);
444 TopColor |= (TopColor << 8);
445 }
446 } else if (Keyboard[ScanCode::sc_end]) { // Dec bottom color
447 if (gamestate.flags & GS_DRAW_FLOOR) {
448 FloorTile = DecRange(FloorTile, static_cast<uint16_t>(NUM_TILES - 1));
449 SetPlaneViewSize(); // Init new textures
450 return 1;
451 } else {
452 BottomColor = DecRange((BottomColor & 0xff), 0xff);
453 BottomColor |= (BottomColor << 8);
454 }
455 } else if (Keyboard[ScanCode::sc_page_down]) { // Inc bottom color
456 if (gamestate.flags & GS_DRAW_FLOOR) {
457 FloorTile = IncRange(FloorTile, static_cast<uint16_t>(NUM_TILES - 1));
458 SetPlaneViewSize(); // Init new textures
459 return 1;
460 } else {
461 BottomColor = IncRange((BottomColor & 0xff), 0xff);
462 BottomColor |= (BottomColor << 8);
463 }
464 }
465
466 if (gamestate.flags & GS_LIGHTING) { // Shading adjustments
467 if (Keyboard[ScanCode::sc_equals] && normalshade_div < 12) {
468 normalshade_div++;
469 } else if (Keyboard[ScanCode::sc_minus] && normalshade_div > 1) {
470 normalshade_div--;
471 }
472
473 normalshade = (3 * (maxscale >> 2)) / normalshade_div;
474
475 if (Keyboard[ScanCode::sc_right_bracket] && shade_max < 63) {
476 shade_max++;
477 } else if (Keyboard[ScanCode::sc_left_bracket] && shade_max > 5) {
478 shade_max--;
479 }
480 }
481
482 return 0;
483 }
484