1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4
5 This file is part of Shadow Warrior version 1.2
6
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the 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 Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26
27 #undef MAIN
28 #include "build.h"
29
30 #include "keys.h"
31 #include "names2.h"
32 #include "panel.h"
33 #include "game.h"
34 #include "pal.h"
35 #include "text.h"
36 #include "colormap.h"
37 #include "player.h"
38
39 //#define SAVE_EXTERN
40 //#include "_save.h"
41 //#undef SAVE_EXTERN
42
43 extern short NormalVisibility;
44
45 // indexed by gs.BorderNum 130,172
46 short InventoryBarXpos[] = {110, 110, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80};
47 short InventoryBarYpos[] = {172, 172, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130};
48
49 VOID PlayerUpdateInventory(PLAYERp pp, short InventoryNum);
50 void SpawnInventoryBar(PLAYERp pp);
51 VOID InventoryBarUpdatePosition(PLAYERp pp);
52 VOID InvBorderRefresh(PLAYERp pp);
53 VOID InventoryUse(PLAYERp pp);
54 VOID InventoryStop(PLAYERp pp, short InventoryNum);
55 VOID KillInventoryBar(PLAYERp pp);
56 VOID PlayerUpdateInventoryPercent(PLAYERp pp);
57 VOID PlayerUpdateInventoryPic(PLAYERp pp);
58 VOID PlayerUpdateInventoryState(PLAYERp pp);
59
60
61 //#define INVENTORY_ICON_WIDTH 32
62 #define INVENTORY_ICON_WIDTH 28
63
64 VOID UseInventoryRepairKit(PLAYERp pp);
65 VOID UseInventoryMedkit(PLAYERp pp);
66 VOID UseInventoryRepairKit(PLAYERp pp);
67 VOID UseInventoryCloak(PLAYERp pp);
68 VOID UseInventoryEnvironSuit(PLAYERp pp);
69 VOID UseInventoryNightVision(PLAYERp pp);
70 VOID UseInventoryChemBomb(PLAYERp pp);
71 VOID UseInventoryFlashBomb(PLAYERp pp);
72 VOID UseInventoryCaltrops(PLAYERp pp);
73
74 VOID StopInventoryRepairKit(PLAYERp pp, short);
75 VOID StopInventoryMedkit(PLAYERp pp, short);
76 VOID StopInventoryRepairKit(PLAYERp pp, short);
77 VOID StopInventoryCloak(PLAYERp pp, short);
78 VOID StopInventoryEnvironSuit(PLAYERp pp, short);
79 VOID StopInventoryNightVision(PLAYERp pp, short);
80
81 extern PANEL_STATE ps_PanelEnvironSuit[];
82 extern PANEL_STATE ps_PanelCloak[];
83 extern PANEL_STATE ps_PanelMedkit[];
84 extern PANEL_STATE ps_PanelRepairKit[];
85 extern PANEL_STATE ps_PanelSelectionBox[];
86 extern PANEL_STATE ps_PanelNightVision[];
87 extern PANEL_STATE ps_PanelChemBomb[];
88 extern PANEL_STATE ps_PanelFlashBomb[];
89 extern PANEL_STATE ps_PanelCaltrops[];
90
91
92 INVENTORY_DATA InventoryData[MAX_INVENTORY+1] =
93 {
94 {"PORTABLE MEDKIT", UseInventoryMedkit, NULL, ps_PanelMedkit, 0, 1, (1<<16), 0},
95 {"REPAIR KIT", NULL, NULL, ps_PanelRepairKit, 100, 1, (1<<16), INVF_AUTO_USE},
96 {"SMOKE BOMB", UseInventoryCloak, StopInventoryCloak, ps_PanelCloak, 4, 1, (1<<16), INVF_TIMED},
97 {"NIGHT VISION", UseInventoryNightVision, StopInventoryNightVision, ps_PanelNightVision,3, 1, (1<<16), INVF_TIMED},
98 {"GAS BOMB", UseInventoryChemBomb, NULL, ps_PanelChemBomb, 0, 1, (1<<16), INVF_COUNT},
99 {"FLASH BOMB", UseInventoryFlashBomb, NULL, ps_PanelFlashBomb, 0, 2, (1<<16), INVF_COUNT},
100 {"CALTROPS", UseInventoryCaltrops, NULL, ps_PanelCaltrops, 0, 3, (1<<16), INVF_COUNT},
101 {NULL, NULL, NULL, NULL, 0, 0, 0, 0}
102 };
103
104 VOID PanelInvTestSuicide(PANEL_SPRITEp psp);
105
UpdateMiniBar(PLAYERp pp)106 VOID UpdateMiniBar(PLAYERp pp)
107 {
108 USERp u = User[pp->PlayerSprite];
109 short i;
110 int x,y;
111 BOOL found;
112 INVENTORY_DATAp id;
113 extern BOOL PanelUpdateMode;
114
115 #define MINI_BAR_Y 174
116
117 #define MINI_BAR_HEALTH_BOX_PIC 2437
118 #define MINI_BAR_AMMO_BOX_PIC 2437
119 #define MINI_BAR_INVENTORY_BOX_PIC 2438
120
121 #define MINI_BAR_HEALTH_BOX_X 4
122 #define MINI_BAR_AMMO_BOX_X 32
123 #define MINI_BAR_INVENTORY_BOX_X 64
124 #define MINI_BAR_INVENTORY_BOX_Y MINI_BAR_Y
125
126 if (!PanelUpdateMode)
127 return;
128
129 if (gs.BorderNum != BORDER_MINI_BAR)
130 return;
131
132 x = MINI_BAR_HEALTH_BOX_X;
133 y = 200 - 26;
134
135 rotatesprite(x << 16, y << 16, (1 << 16), 0,
136 MINI_BAR_HEALTH_BOX_PIC, 0, 0,
137 ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
138
139 x = MINI_BAR_HEALTH_BOX_X+3;
140 DisplayMiniBarNumber(pp, x, y+5, u->Health);
141
142 if (u->WeaponNum != WPN_SWORD && u->WeaponNum != WPN_FIST)
143 {
144 x = MINI_BAR_AMMO_BOX_X;
145
146 rotatesprite(x << 16, y << 16, (1 << 16), 0,
147 MINI_BAR_AMMO_BOX_PIC, 0, 0,
148 ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
149
150 x = MINI_BAR_AMMO_BOX_X+3;
151 DisplayMiniBarNumber(pp, x, y+5, pp->WpnAmmo[u->WeaponNum]);
152 }
153
154 if (!pp->InventoryAmount[pp->InventoryNum])
155 return;
156
157 // Inventory Box
158 x = MINI_BAR_INVENTORY_BOX_X;
159
160 rotatesprite(x << 16, y << 16, (1 << 16), 0,
161 MINI_BAR_INVENTORY_BOX_PIC, 0, 0,
162 ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
163
164 id = &InventoryData[pp->InventoryNum];
165
166 // Inventory pic
167 x = MINI_BAR_INVENTORY_BOX_X + 2;
168 y += 2;
169
170 rotatesprite(x << 16, y << 16, (1 << 16), 0,
171 id->State->picndx, 0, 0,
172 ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
173
174 // will update the AUTO and % inventory values
175 PlayerUpdateInventory(pp, pp->InventoryNum);
176 }
177
178
179 VOID
PanelInvTestSuicide(PANEL_SPRITEp psp)180 PanelInvTestSuicide(PANEL_SPRITEp psp)
181 {
182 if (TEST(psp->flags, PANF_SUICIDE))
183 {
184 pKillSprite(psp);
185 }
186 }
187
188 PANEL_SPRITEp
SpawnInventoryIcon(PLAYERp pp,short InventoryNum)189 SpawnInventoryIcon(PLAYERp pp, short InventoryNum)
190 {
191 PANEL_SPRITEp psp;
192 short x,y;
193
194 // check invalid value
195 ASSERT(InventoryNum < MAX_INVENTORY);
196
197 // check to see if its already spawned
198 if (pp->InventorySprite[InventoryNum])
199 return(NULL);
200
201 // check for Icon panel state
202 if (!InventoryData[InventoryNum].State)
203 return(NULL);
204
205 x = InventoryBarXpos[gs.BorderNum] + (InventoryNum*INVENTORY_ICON_WIDTH);
206 y = InventoryBarYpos[gs.BorderNum];
207 psp = pSpawnSprite(pp, InventoryData[InventoryNum].State, PRI_FRONT, x, y);
208 pp->InventorySprite[InventoryNum] = psp;
209
210 psp->x1 = 0;
211 psp->y1 = 0;
212 psp->x2 = xdim - 1;
213 psp->y2 = ydim - 1;
214 psp->scale = InventoryData[InventoryNum].Scale;
215 SET(psp->flags, PANF_STATUS_AREA | PANF_SCREEN_CLIP);
216
217 return(psp);
218 }
219
220 VOID
KillPanelInv(PLAYERp pp,short InventoryNum)221 KillPanelInv(PLAYERp pp, short InventoryNum)
222 {
223 ASSERT(pp->InventorySprite[InventoryNum]);
224 ASSERT(InventoryNum < MAX_INVENTORY);
225
226 pp->InventoryTics[InventoryNum] = 0;
227 SET(pp->InventorySprite[InventoryNum]->flags, PANF_SUICIDE);
228 pp->InventorySprite[InventoryNum] = NULL;
229 }
230
231 VOID
KillPlayerIcon(PLAYERp UNUSED (pp),PANEL_SPRITEp * pspp)232 KillPlayerIcon(PLAYERp UNUSED(pp), PANEL_SPRITEp *pspp)
233 {
234 SET((*pspp)->flags, PANF_SUICIDE);
235 (*pspp) = NULL;
236 }
237
238 VOID
KillAllPanelInv(PLAYERp pp)239 KillAllPanelInv(PLAYERp pp)
240 {
241 short i;
242
243 for (i = 0; i < MAX_INVENTORY; i++)
244 {
245 if (!pp->InventorySprite[i])
246 continue;
247
248 pp->InventoryTics[i] = 0;
249 SET(pp->InventorySprite[i]->flags, PANF_SUICIDE);
250 pp->InventorySprite[i]->numpages = 0;
251 pp->InventorySprite[i] = NULL;
252 }
253 }
254
255 PANEL_SPRITEp
SpawnIcon(PLAYERp pp,PANEL_STATEp state)256 SpawnIcon(PLAYERp pp, PANEL_STATEp state)
257 {
258 PANEL_SPRITEp psp;
259 short i;
260
261 psp = pSpawnSprite(pp, state, PRI_FRONT, 0, 0);
262
263 psp->x1 = 0;
264 psp->y1 = 0;
265 psp->x2 = xdim - 1;
266 psp->y2 = ydim - 1;
267 SET(psp->flags, PANF_STATUS_AREA | PANF_SCREEN_CLIP);
268 return(psp);
269 }
270
271 //////////////////////////////////////////////////////////////////////
272 //
273 // MEDKIT
274 //
275 //////////////////////////////////////////////////////////////////////
276
AutoPickInventory(PLAYERp pp)277 VOID AutoPickInventory(PLAYERp pp)
278 {
279 int i;
280
281 // auto pick only if run out of currently selected one
282
283 if (pp->InventoryAmount[pp->InventoryNum] <= 0)
284 {
285 for (i = 0; i < MAX_INVENTORY; i++)
286 {
287 if (i == INVENTORY_REPAIR_KIT)
288 continue;
289
290 if (pp->InventoryAmount[i])
291 {
292 pp->InventoryNum = i;
293 return;
294 }
295 }
296
297 // only take this if there is nothing else
298 if (pp->InventoryAmount[INVENTORY_REPAIR_KIT])
299 pp->InventoryNum = INVENTORY_REPAIR_KIT;
300 }
301 }
302
303 VOID
UseInventoryMedkit(PLAYERp pp)304 UseInventoryMedkit(PLAYERp pp)
305 {
306 USERp u = User[pp->PlayerSprite];
307 short diff;
308 short inv = INVENTORY_MEDKIT;
309 short amt;
310
311
312 if (!pp->InventoryAmount[inv])
313 return;
314
315 diff = 100 - u->Health;
316 if (diff <= 0)
317 return;
318
319 if(diff > pp->InventoryPercent[inv]) // If not enough to get to 100, use what's left
320 amt = pp->InventoryPercent[inv];
321 else
322 amt = diff;
323
324 PlayerUpdateHealth(pp, amt);
325
326 pp->InventoryPercent[inv] -= diff;
327 if (pp->InventoryPercent[inv] < 0)
328 {
329 pp->InventoryPercent[inv] = 0;
330 pp->InventoryAmount[inv]--;
331 }
332
333 AutoPickInventory(pp);
334
335 //percent
336 PlayerUpdateInventory(pp, pp->InventoryNum);
337
338 if(pp == Player+myconnectindex)
339 {
340 if (amt >= 30)
341 PlayerSound(DIGI_GETMEDKIT,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
342 else
343 PlayerSound(DIGI_AHH,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
344 }
345 }
346
347 //////////////////////////////////////////////////////////////////////
348 //
349 // CHEMICAL WARFARE CANISTERS
350 //
351 //////////////////////////////////////////////////////////////////////
352 VOID
UseInventoryChemBomb(PLAYERp pp)353 UseInventoryChemBomb(PLAYERp pp)
354 {
355 USERp u = User[pp->PlayerSprite];
356 short diff;
357 short inv = INVENTORY_CHEMBOMB;
358
359 if (!pp->InventoryAmount[inv])
360 return;
361
362 PlayerInitChemBomb(pp); // Throw a chemical bomb out there
363
364 pp->InventoryPercent[inv] = 0;
365 if (--pp->InventoryAmount[inv] < 0)
366 pp->InventoryAmount[inv] = 0;
367
368 AutoPickInventory(pp);
369
370 PlayerUpdateInventory(pp, pp->InventoryNum);
371 }
372
373 //////////////////////////////////////////////////////////////////////
374 //
375 // FLASH BOMBS
376 //
377 //////////////////////////////////////////////////////////////////////
378 VOID
UseInventoryFlashBomb(PLAYERp pp)379 UseInventoryFlashBomb(PLAYERp pp)
380 {
381 USERp u = User[pp->PlayerSprite];
382 short diff;
383 short inv = INVENTORY_FLASHBOMB;
384
385 if (!pp->InventoryAmount[inv])
386 return;
387
388 PlayerInitFlashBomb(pp);
389
390 pp->InventoryPercent[inv] = 0;
391 if (--pp->InventoryAmount[inv] < 0)
392 pp->InventoryAmount[inv] = 0;
393
394 AutoPickInventory(pp);
395
396 PlayerUpdateInventory(pp, pp->InventoryNum);
397 }
398
399 //////////////////////////////////////////////////////////////////////
400 //
401 // CALTROPS
402 //
403 //////////////////////////////////////////////////////////////////////
404 VOID
UseInventoryCaltrops(PLAYERp pp)405 UseInventoryCaltrops(PLAYERp pp)
406 {
407 USERp u = User[pp->PlayerSprite];
408 short diff;
409 short inv = INVENTORY_CALTROPS;
410
411 if (!pp->InventoryAmount[inv])
412 return;
413
414 PlayerInitCaltrops(pp);
415
416 pp->InventoryPercent[inv] = 0;
417 if (--pp->InventoryAmount[inv] < 0)
418 pp->InventoryAmount[inv] = 0;
419
420 AutoPickInventory(pp);
421
422 PlayerUpdateInventory(pp, pp->InventoryNum);
423 }
424
425 //////////////////////////////////////////////////////////////////////
426 //
427 // REPAIR KIT
428 //
429 //////////////////////////////////////////////////////////////////////
430
431 VOID
UseInventoryRepairKit(PLAYERp pp)432 UseInventoryRepairKit(PLAYERp pp)
433 {
434 SPRITEp sp = pp->SpriteP;
435 short inv = INVENTORY_REPAIR_KIT;
436
437 //PlaySound(DIGI_TOOLBOX, &pp->posx, &pp->posy, &pp->posz, v3df_none);
438 if(pp == Player + myconnectindex)
439 {
440 if(STD_RANDOM_RANGE(1000) > 500)
441 PlayerSound(DIGI_NOREPAIRMAN,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
442 else
443 PlayerSound(DIGI_NOREPAIRMAN2,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
444 }
445
446 pp->InventoryPercent[inv] = 0;
447 pp->InventoryAmount[inv] = 0;
448
449 AutoPickInventory(pp);
450
451 //percent
452 PlayerUpdateInventory(pp, pp->InventoryNum);
453 }
454
455 //////////////////////////////////////////////////////////////////////
456 //
457 // CLOAK
458 //
459 //////////////////////////////////////////////////////////////////////
460
461 VOID
UseInventoryCloak(PLAYERp pp)462 UseInventoryCloak(PLAYERp pp)
463 {
464 SPRITEp sp = pp->SpriteP;
465
466 if (pp->InventoryActive[pp->InventoryNum])
467 {
468 // StopInventoryCloak(pp, pp->InventoryNum);
469 return;
470 }
471
472 pp->InventoryActive[pp->InventoryNum] = TRUE;
473
474 AutoPickInventory(pp);
475
476 // on/off
477 PlayerUpdateInventory(pp, pp->InventoryNum);
478
479 SET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT);
480 sp->shade = 100;
481
482 PlaySound(DIGI_GASPOP, &pp->posx, &pp->posy, &pp->posz, v3df_none);
483 //if(RANDOM_RANGE(1000) > 950)
484 if(pp == Player+myconnectindex)
485 PlayerSound(DIGI_IAMSHADOW,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
486 }
487
488 VOID
StopInventoryCloak(PLAYERp pp,short InventoryNum)489 StopInventoryCloak(PLAYERp pp, short InventoryNum)
490 {
491 SPRITEp sp = pp->SpriteP;
492
493 pp->InventoryActive[InventoryNum] = FALSE;
494
495 if (pp->InventoryPercent[InventoryNum] <= 0)
496 {
497 pp->InventoryPercent[InventoryNum] = 0;
498 if (--pp->InventoryAmount[InventoryNum] < 0)
499 pp->InventoryAmount[InventoryNum] = 0;
500 }
501
502 // on/off
503 PlayerUpdateInventory(pp, InventoryNum);
504
505 RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT);
506 sp->shade = 0;
507
508 PlaySound(DIGI_GASPOP, &pp->posx, &pp->posy, &pp->posz, v3df_none);
509 }
510
511 //////////////////////////////////////////////////////////////////////
512 //
513 // ENVIRONMENT SUIT
514 //
515 //////////////////////////////////////////////////////////////////////
516 #if 0
517 VOID
518 UseInventoryEnvironSuit(PLAYERp pp)
519 {
520 SPRITEp sp = pp->SpriteP;
521 short inv = INVENTORY_ENVIRON_SUIT;
522
523 // only activate if you have one
524 if (pp->InventoryAmount[inv])
525 {
526 pp->InventoryActive[inv] = TRUE;
527 // on/off
528 PlayerUpdateInventory(pp, inv);
529 }
530 }
531
532 VOID
533 StopInventoryEnvironSuit(PLAYERp pp, short InventoryNum)
534 {
535 SPRITEp sp = pp->SpriteP;
536 short inv = INVENTORY_ENVIRON_SUIT;
537
538 pp->InventoryActive[InventoryNum] = FALSE;
539
540 if (pp->InventoryPercent[InventoryNum] <= 0)
541 {
542 pp->InventoryPercent[InventoryNum] = 0;
543 if (--pp->InventoryAmount[InventoryNum] < 0)
544 pp->InventoryAmount[InventoryNum] = 0;
545 }
546
547 // on/off
548 PlayerUpdateInventory(pp, InventoryNum);
549
550 PlaySound(DIGI_SWCLOAKUNCLOAK, &pp->posx, &pp->posy, &pp->posz, v3df_none);
551 }
552 #endif
553
554 //////////////////////////////////////////////////////////////////////
555 //
556 // NIGHT VISION
557 //
558 //////////////////////////////////////////////////////////////////////
559
560 static char sectorfloorpals[MAXSECTORS], sectorceilingpals[MAXSECTORS], wallpals[MAXWALLS];
561
562 #if 0
563 VOID
564 DoPlayerNightVisionPalette(PLAYERp pp)
565 {
566 extern char DefaultPalette[];
567 short i;
568
569 if (pp->InventoryActive[INVENTORY_NIGHT_VISION] && (pp - Player == screenpeek))
570 {
571 if (NightVision)
572 return; // Already using night vision, don't
573 // bother.
574 visibility = 0;
575 for (i = 0; i < numsectors; i++)
576 {
577 sectorfloorpals[i] = sector[i].floorpal;
578 sectorceilingpals[i] = sector[i].ceilingpal;
579 sector[i].floorpal = PALETTE_GREEN_LIGHTING;
580 sector[i].ceilingpal = PALETTE_GREEN_LIGHTING;
581 }
582 for (i = 0; i < numwalls; i++)
583 {
584 wallpals[i] = wall[i].pal;
585 wall[i].pal = PALETTE_GREEN_LIGHTING;
586 }
587
588
589 NightVision = TRUE;
590 COVERsetbrightness(4, (char *) &palette_data[0][0]);
591 }
592 else
593 {
594 visibility = NormalVisibility;
595 for (i = 0; i < numsectors; i++)
596 {
597 sector[i].floorpal = sectorfloorpals[i];
598 sector[i].ceilingpal = sectorceilingpals[i];
599 }
600 for (i = 0; i < numwalls; i++)
601 {
602 wall[i].pal = wallpals[i];
603 }
604 DoPlayerDivePalette(pp); // Check again to see if its a water palette
605 NightVision = FALSE;
606 COVERsetbrightness(gs.Brightness, (char *) &palette_data[0][0]);
607 }
608 }
609 #endif
610
611 VOID
DoPlayerNightVisionPalette(PLAYERp pp)612 DoPlayerNightVisionPalette(PLAYERp pp)
613 {
614 extern char DefaultPalette[];
615
616 if (pp != Player + screenpeek) return;
617
618 if (pp->InventoryActive[INVENTORY_NIGHT_VISION])
619 {
620 // if (pp->NightVision && pp->StartColor == 148)
621 // return;
622 SetFadeAmt(pp,-1005,148); // Night vision green tint
623 pp->NightVision = TRUE;
624 } else
625 {
626 // Put it all back to normal
627 if(pp->StartColor == 148)
628 {
629 memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
630 memcpy(palookup[PALETTE_DEFAULT], DefaultPalette, 256 * 32);
631 pp->FadeAmt = 0;
632 #if USE_POLYMOST && USE_OPENGL
633 if (getrendermode() >= 3)
634 {
635 setpalettefade(0,0,0,0);
636 }
637 else
638 #endif
639 {
640 COVERsetbrightness(gs.Brightness, &palette_data[0][0]);
641 }
642 }
643 pp->NightVision = FALSE;
644 }
645 }
646
647 VOID
UseInventoryNightVision(PLAYERp pp)648 UseInventoryNightVision(PLAYERp pp)
649 {
650 SPRITEp sp = pp->SpriteP;
651 #define NIGHT_INVENTORY_TIME 30
652
653 if (pp->InventoryActive[pp->InventoryNum])
654 {
655 StopInventoryNightVision(pp, pp->InventoryNum);
656 return;
657 }
658
659 pp->InventoryActive[pp->InventoryNum] = TRUE;
660
661 // on/off
662 PlayerUpdateInventory(pp, pp->InventoryNum);
663
664 DoPlayerNightVisionPalette(pp);
665 PlaySound(DIGI_NIGHTON, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow);
666 }
667
668 VOID
StopInventoryNightVision(PLAYERp pp,short InventoryNum)669 StopInventoryNightVision(PLAYERp pp, short InventoryNum)
670 {
671 SPRITEp sp = pp->SpriteP;
672
673 pp->InventoryActive[InventoryNum] = FALSE;
674
675 if (pp->InventoryPercent[InventoryNum] <= 0)
676 {
677 pp->InventoryPercent[InventoryNum] = 0;
678 if (--pp->InventoryAmount[InventoryNum] < 0)
679 pp->InventoryAmount[InventoryNum] = 0;
680 }
681
682 AutoPickInventory(pp);
683
684 // on/off
685 PlayerUpdateInventory(pp, pp->InventoryNum);
686
687 DoPlayerNightVisionPalette(pp);
688 DoPlayerDivePalette(pp);
689 PlaySound(DIGI_NIGHTOFF, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow);
690 }
691
692 //////////////////////////////////////////////////////////////////////
693 //
694 // INVENTORY KEYS
695 //
696 //////////////////////////////////////////////////////////////////////
697
InventoryKeys(PLAYERp pp)698 VOID InventoryKeys(PLAYERp pp)
699 {
700 short inv_hotkey;
701
702 // scroll SPELLs left
703 if (TEST_SYNC_KEY(pp, SK_INV_LEFT))
704 {
705 if (FLAG_KEY_PRESSED(pp, SK_INV_LEFT))
706 {
707 FLAG_KEY_RELEASE(pp, SK_INV_LEFT);
708 SpawnInventoryBar(pp);
709 PlayerUpdateInventory(pp, pp->InventoryNum - 1);
710 PutStringInfo(pp, InventoryData[pp->InventoryNum].Name);
711 InventoryBarUpdatePosition(pp);
712 InvBorderRefresh(pp);
713 }
714 }
715 else
716 {
717 FLAG_KEY_RESET(pp, SK_INV_LEFT);
718 }
719
720 // scroll SPELLs right
721 if (TEST_SYNC_KEY(pp, SK_INV_RIGHT))
722 {
723 if (FLAG_KEY_PRESSED(pp, SK_INV_RIGHT))
724 {
725 FLAG_KEY_RELEASE(pp, SK_INV_RIGHT);
726 SpawnInventoryBar(pp);
727 PlayerUpdateInventory(pp, pp->InventoryNum + 1);
728 PutStringInfo(pp, InventoryData[pp->InventoryNum].Name);
729 InventoryBarUpdatePosition(pp);
730 InvBorderRefresh(pp);
731 }
732 }
733 else
734 {
735 FLAG_KEY_RESET(pp, SK_INV_RIGHT);
736 }
737
738 if (TEST_SYNC_KEY(pp, SK_INV_USE))
739 {
740 if (FLAG_KEY_PRESSED(pp, SK_INV_USE))
741 {
742 FLAG_KEY_RELEASE(pp, SK_INV_USE);
743
744 if (InventoryData[pp->InventoryNum].Init)
745 {
746 if (pp->InventoryAmount[pp->InventoryNum])
747 {
748 InventoryUse(pp);
749 }
750 else
751 {
752 sprintf(ds,"No %s",InventoryData[pp->InventoryNum].Name);
753 PutStringInfo(pp,ds); // DONT have message
754 }
755 }
756 }
757 }
758 else
759 {
760 FLAG_KEY_RESET(pp, SK_INV_USE);
761 }
762
763 // get hotkey number out of input bits
764 inv_hotkey = TEST(pp->input.bits, SK_INV_HOTKEY_MASK) >> SK_INV_HOTKEY_BIT0;
765
766 if (inv_hotkey)
767 {
768 if (FLAG_KEY_PRESSED(pp, SK_INV_HOTKEY_BIT0))
769 {
770 FLAG_KEY_RELEASE(pp, SK_INV_HOTKEY_BIT0);
771
772 inv_hotkey -= 1;
773
774 ////DSPRINTF(ds,"inv_hotkey %d",inv_hotkey);
775 //MONO_PRINT(ds);
776
777 // switches you to this inventory item
778 //PlayerUpdateInventory(pp, inv_hotkey);
779 pp->InventoryNum = inv_hotkey;
780
781 if (InventoryData[pp->InventoryNum].Init && !TEST(pp->Flags, PF_CLIMBING))
782 {
783 if (pp->InventoryAmount[pp->InventoryNum])
784 {
785 InventoryUse(pp);
786 }
787 #if 0
788 else
789 {
790 sprintf(ds,"No %s",InventoryData[pp->InventoryNum].Name);
791 PutStringInfo(pp,ds); // DONT have message
792 }
793 #endif
794 }
795
796 //PlayerUpdateInventory(pp, pp->InventoryNum);
797 }
798 }
799 else
800 {
801 FLAG_KEY_RESET(pp, SK_INV_HOTKEY_BIT0);
802 }
803 }
804
InvBorderRefresh(PLAYERp pp)805 VOID InvBorderRefresh(PLAYERp pp)
806 {
807 int x,y;
808
809 if (pp != Player + myconnectindex)
810 return;
811
812 x = InventoryBarXpos[gs.BorderNum];
813 y = InventoryBarYpos[gs.BorderNum];
814
815 SetRedrawScreen(pp);
816 //BorderRefreshClip(pp, x-5, y-5, x + (MAX_INVENTORY * INVENTORY_ICON_WIDTH), y + 24);
817 }
818
InventoryTimer(PLAYERp pp)819 VOID InventoryTimer(PLAYERp pp)
820 {
821 // called every time through loop
822 short inv = 0;
823 INVENTORY_DATAp id;
824
825 // if bar is up
826 if (pp->InventoryBarTics)
827 {
828 InventoryBarUpdatePosition(pp);
829
830 pp->InventoryBarTics -= synctics;
831 // if bar time has elapsed
832 if (pp->InventoryBarTics <= 0)
833 {
834 // get rid of the bar
835 KillInventoryBar(pp);
836 // don't update bar anymore
837 pp->InventoryBarTics = 0;
838
839 InvBorderRefresh(pp);
840 //BorderRefresh(pp);
841 }
842 }
843
844 for (id = InventoryData; id->Name; id++, inv++)
845 {
846 // if timed and active
847 if (TEST(id->Flags, INVF_TIMED) && pp->InventoryActive[inv])
848 {
849 // dec tics
850 pp->InventoryTics[inv] -= synctics;
851 if (pp->InventoryTics[inv] <= 0)
852 {
853 // take off a percentage
854 pp->InventoryPercent[inv] -= id->DecPerSec;
855 if (pp->InventoryPercent[inv] <= 0)
856 {
857 // ALL USED UP
858 pp->InventoryPercent[inv] = 0;
859 InventoryStop(pp, inv);
860 pp->InventoryActive[inv] = FALSE;
861 }
862 else
863 {
864 // reset 1 sec tic clock
865 pp->InventoryTics[inv] = SEC(1);
866 }
867
868 //PlayerUpdateInventoryPercent(pp);
869 PlayerUpdateInventory(pp, pp->InventoryNum);
870 }
871 }
872 else
873 // the idea behind this is that the USE function will get called
874 // every time the player is in an AUTO_USE situation.
875 // This code will decrement the timer and set the Item to InActive
876 // EVERY SINGLE TIME. Relies on the USE function getting called!
877 if (TEST(id->Flags, INVF_AUTO_USE) && pp->InventoryActive[inv])
878 {
879 pp->InventoryTics[inv] -= synctics;
880 if (pp->InventoryTics[inv] <= 0)
881 {
882 // take off a percentage
883 pp->InventoryPercent[inv] -= id->DecPerSec;
884 if (pp->InventoryPercent[inv] <= 0)
885 {
886 // ALL USED UP
887 pp->InventoryPercent[inv] = 0;
888 // should get rid if Amount - stop it for good
889 InventoryStop(pp, inv);
890 }
891 else
892 {
893 // reset 1 sec tic clock
894 pp->InventoryTics[inv] = SEC(1);
895 // set to InActive EVERY TIME THROUGH THE LOOP!
896 pp->InventoryActive[inv] = FALSE;
897 }
898
899 //PlayerUpdateInventoryPercent(pp);
900 PlayerUpdateInventory(pp, pp->InventoryNum);
901 }
902 }
903 }
904 }
905
906 //////////////////////////////////////////////////////////////////////
907 //
908 // INVENTORY BAR
909 //
910 //////////////////////////////////////////////////////////////////////
911
SpawnInventoryBar(PLAYERp pp)912 VOID SpawnInventoryBar(PLAYERp pp)
913 {
914 short inv = 0;
915 INVENTORY_DATAp id;
916 PANEL_SPRITEp psp;
917
918
919 // its already up
920 if (pp->InventoryBarTics)
921 {
922 pp->InventoryBarTics = SEC(2);
923 return;
924 }
925
926 pp->InventorySelectionBox = SpawnIcon(pp, ps_PanelSelectionBox);
927
928 for (id = InventoryData; id->Name; id++, inv++)
929 {
930 psp = SpawnInventoryIcon(pp, inv);
931
932 if (!pp->InventoryAmount[inv])
933 {
934 //SET(psp->flags, PANF_TRANSLUCENT);
935 //SET(psp->flags, PANF_TRANS_FLIP);
936 psp->shade = 100; //Darken it
937 }
938 }
939
940 pp->InventoryBarTics = SEC(2);
941 }
942
KillInventoryBar(PLAYERp pp)943 VOID KillInventoryBar(PLAYERp pp)
944 {
945 KillAllPanelInv(pp);
946 KillPlayerIcon(pp, &pp->InventorySelectionBox);
947 }
948
949 // In case the BorderNum changes - move the postions
InventoryBarUpdatePosition(PLAYERp pp)950 VOID InventoryBarUpdatePosition(PLAYERp pp)
951 {
952 short inv = 0;
953 short x,y;
954 INVENTORY_DATAp id;
955
956 x = InventoryBarXpos[gs.BorderNum] + (pp->InventoryNum * INVENTORY_ICON_WIDTH);
957 y = InventoryBarYpos[gs.BorderNum];
958
959 pp->InventorySelectionBox->x = x - 5;
960 pp->InventorySelectionBox->y = y - 5;
961
962 for (id = InventoryData; id->Name; id++, inv++)
963 {
964 x = InventoryBarXpos[gs.BorderNum] + (inv * INVENTORY_ICON_WIDTH);
965 y = InventoryBarYpos[gs.BorderNum];
966
967 pp->InventorySprite[inv]->x = x;
968 pp->InventorySprite[inv]->y = y;
969 }
970
971 }
972
InventoryUse(PLAYERp pp)973 VOID InventoryUse(PLAYERp pp)
974 {
975 INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
976
977 if (id->Init)
978 (*id->Init)(pp);
979 }
980
InventoryStop(PLAYERp pp,short InventoryNum)981 VOID InventoryStop(PLAYERp pp, short InventoryNum)
982 {
983 INVENTORY_DATAp id = &InventoryData[InventoryNum];
984
985 if (id->Stop)
986 (*id->Stop)(pp, InventoryNum);
987 }
988
989 /////////////////////////////////////////////////////////////////
990 //
991 // Inventory Console Area
992 //
993 /////////////////////////////////////////////////////////////////
994
995 #define INVENTORY_BOX_X 231
996 #define INVENTORY_BOX_Y (176-8)
997 #define INVENTORY_BOX_ERASE 2403
998
999 short InventoryBoxX;
1000 short InventoryBoxY;
1001 short InventoryXoff;
1002 short InventoryYoff;
1003 VOID (*InventoryDisplayString)(PLAYERp, short, short, short, const char *);
1004
1005 #define INVENTORY_PIC_XOFF 1
1006 #define INVENTORY_PIC_YOFF 1
1007
1008 #define INVENTORY_PERCENT_XOFF 19
1009 #define INVENTORY_PERCENT_YOFF 13
1010
1011 #define INVENTORY_STATE_XOFF 19
1012 #define INVENTORY_STATE_YOFF 1
1013
1014 VOID
PlayerUpdateInventory(PLAYERp pp,short InventoryNum)1015 PlayerUpdateInventory(PLAYERp pp, short InventoryNum)
1016 {
1017 USERp u = User[pp->PlayerSprite];
1018 short w,h;
1019 PANEL_SPRITEp psp;
1020
1021 // Check for items that need to go translucent from use
1022 if (pp->InventoryBarTics)
1023 {
1024 short inv = 0;
1025 INVENTORY_DATAp id;
1026
1027 // Go translucent if used
1028 for (id = InventoryData; id->Name; id++, inv++)
1029 {
1030 psp = pp->InventorySprite[inv];
1031 if (!pp->InventoryAmount[inv])
1032 {
1033 //SET(psp->flags, PANF_TRANSLUCENT);
1034 //SET(psp->flags, PANF_TRANS_FLIP);
1035 psp->shade = 100; // Darken it
1036 }
1037 else
1038 {
1039 //RESET(psp->flags, PANF_TRANSLUCENT);
1040 //RESET(psp->flags, PANF_TRANS_FLIP);
1041 psp->shade = 0;
1042 }
1043 }
1044 }
1045
1046 pp->InventoryNum = InventoryNum;
1047
1048 if (pp->InventoryNum < 0)
1049 pp->InventoryNum = MAX_INVENTORY-1;
1050
1051 if (pp->InventoryNum >= MAX_INVENTORY)
1052 pp->InventoryNum = 0;
1053
1054 if (pp - Player != screenpeek)
1055 return;
1056
1057 if (gs.BorderNum == BORDER_MINI_BAR)
1058 {
1059 InventoryBoxX = MINI_BAR_INVENTORY_BOX_X;
1060 InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y;
1061
1062 InventoryXoff = 1;
1063 InventoryYoff = 1;
1064
1065 InventoryDisplayString = DisplayMiniBarSmString;
1066 }
1067 else
1068 {
1069 if (gs.BorderNum < BORDER_BAR)
1070 return;
1071
1072 InventoryBoxX = INVENTORY_BOX_X;
1073 InventoryBoxY = INVENTORY_BOX_Y;
1074
1075 InventoryXoff = 0;
1076 InventoryYoff = 0;
1077
1078 InventoryDisplayString = DisplaySmString;
1079
1080 // erase old info
1081 psp = pSpawnFullScreenSprite(pp, INVENTORY_BOX_ERASE, PRI_MID, INVENTORY_BOX_X, INVENTORY_BOX_Y);
1082 SET(psp->flags, PANF_SCALE_BOTTOM);
1083
1084 // put pic
1085 if (pp->InventoryAmount[pp->InventoryNum])
1086 PlayerUpdateInventoryPic(pp);
1087 }
1088
1089 if (pp->InventoryAmount[pp->InventoryNum])
1090 {
1091 // Auto/On/Off
1092 PlayerUpdateInventoryState(pp);
1093 // Percent count/Item count
1094 PlayerUpdateInventoryPercent(pp);
1095 }
1096 }
1097
1098 VOID
PlayerUpdateInventoryPercent(PLAYERp pp)1099 PlayerUpdateInventoryPercent(PLAYERp pp)
1100 {
1101 USERp u = User[pp->PlayerSprite];
1102 short x,y;
1103 INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
1104
1105 x = InventoryBoxX + INVENTORY_PERCENT_XOFF + InventoryXoff;
1106 y = InventoryBoxY + INVENTORY_PERCENT_YOFF + InventoryYoff;
1107
1108 if (TEST(id->Flags, INVF_COUNT))
1109 {
1110 sprintf(ds,"%d", pp->InventoryAmount[pp->InventoryNum]);
1111 InventoryDisplayString(pp, x, y, 0, ds);
1112 }
1113 else
1114 {
1115 sprintf(ds,"%d%c", pp->InventoryPercent[pp->InventoryNum],'%');
1116 InventoryDisplayString(pp, x, y, 0, ds);
1117 }
1118 }
1119
1120 VOID
PlayerUpdateInventoryPic(PLAYERp pp)1121 PlayerUpdateInventoryPic(PLAYERp pp)
1122 {
1123 USERp u = User[pp->PlayerSprite];
1124 PANEL_SPRITEp psp;
1125 short pic;
1126 short x,y;
1127 INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
1128
1129 x = InventoryBoxX + INVENTORY_PIC_XOFF + InventoryXoff;
1130 y = InventoryBoxY + INVENTORY_PIC_YOFF + InventoryYoff;
1131
1132 pic = id->State->picndx;
1133
1134 psp = pSpawnFullScreenSprite(pp, pic, PRI_FRONT_MAX, x, y);
1135 SET(psp->flags, PANF_SCALE_BOTTOM);
1136
1137 psp->scale = id->Scale;
1138 }
1139
1140 VOID
PlayerUpdateInventoryState(PLAYERp pp)1141 PlayerUpdateInventoryState(PLAYERp pp)
1142 {
1143 USERp u = User[pp->PlayerSprite];
1144 short x,y;
1145 INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
1146
1147 x = InventoryBoxX + INVENTORY_STATE_XOFF + InventoryXoff;
1148 y = InventoryBoxY + INVENTORY_STATE_YOFF + InventoryYoff;
1149
1150 if (TEST(id->Flags, INVF_AUTO_USE))
1151 {
1152 sprintf(ds,"%s", "AUTO");
1153 InventoryDisplayString(pp, x, y, 0, ds);
1154 }
1155 else
1156 if (TEST(id->Flags, INVF_TIMED))
1157 {
1158 sprintf(ds,"%s", pp->InventoryActive[pp->InventoryNum] ? "ON" : "OFF");
1159 InventoryDisplayString(pp, x, y, 0, ds);
1160 }
1161 }
1162