summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/wolf3d/wl_act1.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_act1.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/wl_act1.c859
1 files changed, 859 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_act1.c b/apps/plugins/sdl/progs/wolf3d/wl_act1.c
new file mode 100644
index 0000000000..e9553c97c5
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/wl_act1.c
@@ -0,0 +1,859 @@
1// WL_ACT1.C
2
3#include "wl_def.h"
4#pragma hdrstop
5
6/*
7=============================================================================
8
9 STATICS
10
11=============================================================================
12*/
13
14
15statobj_t statobjlist[MAXSTATS];
16statobj_t *laststatobj;
17
18
19struct
20{
21 short picnum;
22 wl_stat_t type;
23 uint32_t specialFlags; // they are ORed to the statobj_t flags
24} statinfo[] =
25{
26 {SPR_STAT_0}, // puddle spr1v
27 {SPR_STAT_1,block}, // Green Barrel "
28 {SPR_STAT_2,block}, // Table/chairs "
29 {SPR_STAT_3,block,FL_FULLBRIGHT}, // Floor lamp "
30 {SPR_STAT_4,none,FL_FULLBRIGHT}, // Chandelier "
31 {SPR_STAT_5,block}, // Hanged man "
32 {SPR_STAT_6,bo_alpo}, // Bad food "
33 {SPR_STAT_7,block}, // Red pillar "
34 //
35 // NEW PAGE
36 //
37 {SPR_STAT_8,block}, // Tree spr2v
38 {SPR_STAT_9}, // Skeleton flat "
39 {SPR_STAT_10,block}, // Sink " (SOD:gibs)
40 {SPR_STAT_11,block}, // Potted plant "
41 {SPR_STAT_12,block}, // Urn "
42 {SPR_STAT_13,block}, // Bare table "
43 {SPR_STAT_14,none,FL_FULLBRIGHT}, // Ceiling light "
44 #ifndef SPEAR
45 {SPR_STAT_15}, // Kitchen stuff "
46 #else
47 {SPR_STAT_15,block}, // Gibs!
48 #endif
49 //
50 // NEW PAGE
51 //
52 {SPR_STAT_16,block}, // suit of armor spr3v
53 {SPR_STAT_17,block}, // Hanging cage "
54 {SPR_STAT_18,block}, // SkeletoninCage "
55 {SPR_STAT_19}, // Skeleton relax "
56 {SPR_STAT_20,bo_key1}, // Key 1 "
57 {SPR_STAT_21,bo_key2}, // Key 2 "
58 {SPR_STAT_22,block}, // stuff (SOD:gibs)
59 {SPR_STAT_23}, // stuff
60 //
61 // NEW PAGE
62 //
63 {SPR_STAT_24,bo_food}, // Good food spr4v
64 {SPR_STAT_25,bo_firstaid}, // First aid "
65 {SPR_STAT_26,bo_clip}, // Clip "
66 {SPR_STAT_27,bo_machinegun}, // Machine gun "
67 {SPR_STAT_28,bo_chaingun}, // Gatling gun "
68 {SPR_STAT_29,bo_cross}, // Cross "
69 {SPR_STAT_30,bo_chalice}, // Chalice "
70 {SPR_STAT_31,bo_bible}, // Bible "
71 //
72 // NEW PAGE
73 //
74 {SPR_STAT_32,bo_crown}, // crown spr5v
75 {SPR_STAT_33,bo_fullheal,FL_FULLBRIGHT},// one up "
76 {SPR_STAT_34,bo_gibs}, // gibs "
77 {SPR_STAT_35,block}, // barrel "
78 {SPR_STAT_36,block}, // well "
79 {SPR_STAT_37,block}, // Empty well "
80 {SPR_STAT_38,bo_gibs}, // Gibs 2 "
81 {SPR_STAT_39,block}, // flag "
82 //
83 // NEW PAGE
84 //
85 #ifndef SPEAR
86 {SPR_STAT_40,block}, // Call Apogee spr7v
87 #else
88 {SPR_STAT_40}, // Red light
89 #endif
90 //
91 // NEW PAGE
92 //
93 {SPR_STAT_41}, // junk "
94 {SPR_STAT_42}, // junk "
95 {SPR_STAT_43}, // junk "
96 #ifndef SPEAR
97 {SPR_STAT_44}, // pots "
98 #else
99 {SPR_STAT_44,block}, // Gibs!
100 #endif
101 {SPR_STAT_45,block}, // stove " (SOD:gibs)
102 {SPR_STAT_46,block}, // spears " (SOD:gibs)
103 {SPR_STAT_47}, // vines "
104 //
105 // NEW PAGE
106 //
107 #ifdef SPEAR
108 {SPR_STAT_48,block}, // marble pillar
109 {SPR_STAT_49,bo_25clip}, // bonus 25 clip
110 {SPR_STAT_50,block}, // truck
111 {SPR_STAT_51,bo_spear}, // SPEAR OF DESTINY!
112 #endif
113
114 {SPR_STAT_26,bo_clip2}, // Clip "
115#ifdef USE_DIR3DSPR
116 // These are just two examples showing the new way of using dir 3d sprites.
117 // You can find the allowed values in the objflag_t enum in wl_def.h.
118 {SPR_STAT_47,none,FL_DIR_VERT_MID},
119 {SPR_STAT_47,block,FL_DIR_HORIZ_MID},
120#endif
121 {-1} // terminator
122};
123
124/*
125===============
126=
127= InitStaticList
128=
129===============
130*/
131
132void InitStaticList (void)
133{
134 laststatobj = &statobjlist[0];
135}
136
137
138
139/*
140===============
141=
142= SpawnStatic
143=
144===============
145*/
146
147void SpawnStatic (int tilex, int tiley, int type)
148{
149 laststatobj->shapenum = statinfo[type].picnum;
150 laststatobj->tilex = tilex;
151 laststatobj->tiley = tiley;
152 laststatobj->visspot = &spotvis[tilex][tiley];
153
154 switch (statinfo[type].type)
155 {
156 case block:
157 actorat[tilex][tiley] = (objtype *) 64; // consider it a blocking tile
158 case none:
159 laststatobj->flags = 0;
160 break;
161
162 case bo_cross:
163 case bo_chalice:
164 case bo_bible:
165 case bo_crown:
166 case bo_fullheal:
167 if (!loadedgame)
168 gamestate.treasuretotal++;
169
170 case bo_firstaid:
171 case bo_key1:
172 case bo_key2:
173 case bo_key3:
174 case bo_key4:
175 case bo_clip:
176 case bo_25clip:
177 case bo_machinegun:
178 case bo_chaingun:
179 case bo_food:
180 case bo_alpo:
181 case bo_gibs:
182 case bo_spear:
183 laststatobj->flags = FL_BONUS;
184 laststatobj->itemnumber = statinfo[type].type;
185 break;
186 }
187
188 laststatobj->flags |= statinfo[type].specialFlags;
189
190 laststatobj++;
191
192 if (laststatobj == &statobjlist[MAXSTATS])
193 Quit ("Too many static objects!\n");
194}
195
196
197/*
198===============
199=
200= PlaceItemType
201=
202= Called during game play to drop actors' items. It finds the proper
203= item number based on the item type (bo_???). If there are no free item
204= spots, nothing is done.
205=
206===============
207*/
208
209void PlaceItemType (int itemtype, int tilex, int tiley)
210{
211 int type;
212 statobj_t *spot;
213
214 //
215 // find the item number
216 //
217 for (type=0; ; type++)
218 {
219 if (statinfo[type].picnum == -1) // end of list
220 Quit ("PlaceItemType: couldn't find type!");
221 if (statinfo[type].type == itemtype)
222 break;
223 }
224
225 //
226 // find a spot in statobjlist to put it in
227 //
228 for (spot=&statobjlist[0]; ; spot++)
229 {
230 if (spot==laststatobj)
231 {
232 if (spot == &statobjlist[MAXSTATS])
233 return; // no free spots
234 laststatobj++; // space at end
235 break;
236 }
237
238 if (spot->shapenum == -1) // -1 is a free spot
239 break;
240 }
241 //
242 // place it
243 //
244 spot->shapenum = statinfo[type].picnum;
245 spot->tilex = tilex;
246 spot->tiley = tiley;
247 spot->visspot = &spotvis[tilex][tiley];
248 spot->flags = FL_BONUS | statinfo[type].specialFlags;
249 spot->itemnumber = statinfo[type].type;
250}
251
252
253
254/*
255=============================================================================
256
257 DOORS
258
259doorobjlist[] holds most of the information for the doors
260
261doorposition[] holds the amount the door is open, ranging from 0 to 0xffff
262 this is directly accessed by AsmRefresh during rendering
263
264The number of doors is limited to 64 because a spot in tilemap holds the
265 door number in the low 6 bits, with the high bit meaning a door center
266 and bit 6 meaning a door side tile
267
268Open doors conect two areas, so sounds will travel between them and sight
269 will be checked when the player is in a connected area.
270
271Areaconnect is incremented/decremented by each door. If >0 they connect
272
273Every time a door opens or closes the areabyplayer matrix gets recalculated.
274 An area is true if it connects with the player's current spor.
275
276=============================================================================
277*/
278
279#define DOORWIDTH 0x7800
280#define OPENTICS 300
281
282doorobj_t doorobjlist[MAXDOORS],*lastdoorobj;
283short doornum;
284
285word doorposition[MAXDOORS]; // leading edge of door 0=closed
286 // 0xffff = fully open
287
288byte areaconnect[NUMAREAS][NUMAREAS];
289
290boolean areabyplayer[NUMAREAS];
291
292
293/*
294==============
295=
296= ConnectAreas
297=
298= Scans outward from playerarea, marking all connected areas
299=
300==============
301*/
302
303void RecursiveConnect (int areanumber)
304{
305 int i;
306
307 for (i=0;i<NUMAREAS;i++)
308 {
309 if (areaconnect[areanumber][i] && !areabyplayer[i])
310 {
311 areabyplayer[i] = true;
312 RecursiveConnect (i);
313 }
314 }
315}
316
317
318void ConnectAreas (void)
319{
320 memset (areabyplayer,0,sizeof(areabyplayer));
321 areabyplayer[player->areanumber] = true;
322 RecursiveConnect (player->areanumber);
323}
324
325
326void InitAreas (void)
327{
328 memset (areabyplayer,0,sizeof(areabyplayer));
329 if (player->areanumber < NUMAREAS)
330 areabyplayer[player->areanumber] = true;
331}
332
333
334
335/*
336===============
337=
338= InitDoorList
339=
340===============
341*/
342
343void InitDoorList (void)
344{
345 memset (areabyplayer,0,sizeof(areabyplayer));
346 memset (areaconnect,0,sizeof(areaconnect));
347
348 lastdoorobj = &doorobjlist[0];
349 doornum = 0;
350}
351
352
353/*
354===============
355=
356= SpawnDoor
357=
358===============
359*/
360
361void SpawnDoor (int tilex, int tiley, boolean vertical, int lock)
362{
363 word *map;
364
365 if (doornum==MAXDOORS)
366 Quit ("64+ doors on level!");
367
368 doorposition[doornum] = 0; // doors start out fully closed
369 lastdoorobj->tilex = tilex;
370 lastdoorobj->tiley = tiley;
371 lastdoorobj->vertical = vertical;
372 lastdoorobj->lock = lock;
373 lastdoorobj->action = dr_closed;
374
375 actorat[tilex][tiley] = (objtype *)(uintptr_t)(doornum | 0x80); // consider it a solid wall
376
377 //
378 // make the door tile a special tile, and mark the adjacent tiles
379 // for door sides
380 //
381 tilemap[tilex][tiley] = doornum | 0x80;
382 map = mapsegs[0] + (tiley<<mapshift) +tilex;
383 if (vertical)
384 {
385 *map = *(map-1); // set area number
386 tilemap[tilex][tiley-1] |= 0x40;
387 tilemap[tilex][tiley+1] |= 0x40;
388 }
389 else
390 {
391 *map = *(map-mapwidth); // set area number
392 tilemap[tilex-1][tiley] |= 0x40;
393 tilemap[tilex+1][tiley] |= 0x40;
394 }
395
396 doornum++;
397 lastdoorobj++;
398}
399
400//===========================================================================
401
402/*
403=====================
404=
405= OpenDoor
406=
407=====================
408*/
409
410void OpenDoor (int door)
411{
412 if (doorobjlist[door].action == dr_open)
413 doorobjlist[door].ticcount = 0; // reset open time
414 else
415 doorobjlist[door].action = dr_opening; // start it opening
416}
417
418
419/*
420=====================
421=
422= CloseDoor
423=
424=====================
425*/
426
427void CloseDoor (int door)
428{
429 int tilex,tiley,area;
430 objtype *check;
431
432 //
433 // don't close on anything solid
434 //
435 tilex = doorobjlist[door].tilex;
436 tiley = doorobjlist[door].tiley;
437
438 if (actorat[tilex][tiley])
439 return;
440
441 if (player->tilex == tilex && player->tiley == tiley)
442 return;
443
444 if (doorobjlist[door].vertical)
445 {
446 if ( player->tiley == tiley )
447 {
448 if ( ((player->x+MINDIST) >>TILESHIFT) == tilex )
449 return;
450 if ( ((player->x-MINDIST) >>TILESHIFT) == tilex )
451 return;
452 }
453 check = actorat[tilex-1][tiley];
454 if (ISPOINTER(check) && ((check->x+MINDIST) >> TILESHIFT) == tilex )
455 return;
456 check = actorat[tilex+1][tiley];
457 if (ISPOINTER(check) && ((check->x-MINDIST) >> TILESHIFT) == tilex )
458 return;
459 }
460 else if (!doorobjlist[door].vertical)
461 {
462 if (player->tilex == tilex)
463 {
464 if ( ((player->y+MINDIST) >>TILESHIFT) == tiley )
465 return;
466 if ( ((player->y-MINDIST) >>TILESHIFT) == tiley )
467 return;
468 }
469 check = actorat[tilex][tiley-1];
470 if (ISPOINTER(check) && ((check->y+MINDIST) >> TILESHIFT) == tiley )
471 return;
472 check = actorat[tilex][tiley+1];
473 if (ISPOINTER(check) && ((check->y-MINDIST) >> TILESHIFT) == tiley )
474 return;
475 }
476
477
478 //
479 // play door sound if in a connected area
480 //
481 area = *(mapsegs[0] + (doorobjlist[door].tiley<<mapshift)
482 +doorobjlist[door].tilex)-AREATILE;
483 if (areabyplayer[area])
484 {
485 PlaySoundLocTile(CLOSEDOORSND,doorobjlist[door].tilex,doorobjlist[door].tiley); // JAB
486 }
487
488 doorobjlist[door].action = dr_closing;
489 //
490 // make the door space solid
491 //
492 actorat[tilex][tiley] = (objtype *)(uintptr_t)(door | 0x80);
493}
494
495
496
497/*
498=====================
499=
500= OperateDoor
501=
502= The player wants to change the door's direction
503=
504=====================
505*/
506
507void OperateDoor (int door)
508{
509 int lock;
510
511 lock = doorobjlist[door].lock;
512 if (lock >= dr_lock1 && lock <= dr_lock4)
513 {
514 if ( ! (gamestate.keys & (1 << (lock-dr_lock1) ) ) )
515 {
516 SD_PlaySound (NOWAYSND); // locked
517 return;
518 }
519 }
520
521 switch (doorobjlist[door].action)
522 {
523 case dr_closed:
524 case dr_closing:
525 OpenDoor (door);
526 break;
527 case dr_open:
528 case dr_opening:
529 CloseDoor (door);
530 break;
531 }
532}
533
534
535//===========================================================================
536
537/*
538===============
539=
540= DoorOpen
541=
542= Close the door after three seconds
543=
544===============
545*/
546
547void DoorOpen (int door)
548{
549 if ( (doorobjlist[door].ticcount += (short) tics) >= OPENTICS)
550 CloseDoor (door);
551}
552
553
554
555/*
556===============
557=
558= DoorOpening
559=
560===============
561*/
562
563void DoorOpening (int door)
564{
565 unsigned area1,area2;
566 word *map;
567 int32_t position;
568
569 position = doorposition[door];
570 if (!position)
571 {
572 //
573 // door is just starting to open, so connect the areas
574 //
575 map = mapsegs[0] + (doorobjlist[door].tiley<<mapshift)
576 +doorobjlist[door].tilex;
577
578 if (doorobjlist[door].vertical)
579 {
580 area1 = *(map+1);
581 area2 = *(map-1);
582 }
583 else
584 {
585 area1 = *(map-mapwidth);
586 area2 = *(map+mapwidth);
587 }
588 area1 -= AREATILE;
589 area2 -= AREATILE;
590
591 if (area1 < NUMAREAS && area2 < NUMAREAS)
592 {
593 areaconnect[area1][area2]++;
594 areaconnect[area2][area1]++;
595
596 if (player->areanumber < NUMAREAS)
597 ConnectAreas ();
598
599 if (areabyplayer[area1])
600 PlaySoundLocTile(OPENDOORSND,doorobjlist[door].tilex,doorobjlist[door].tiley); // JAB
601 }
602 }
603
604 //
605 // slide the door by an adaptive amount
606 //
607 position += tics<<10;
608 if (position >= 0xffff)
609 {
610 //
611 // door is all the way open
612 //
613 position = 0xffff;
614 doorobjlist[door].ticcount = 0;
615 doorobjlist[door].action = dr_open;
616 actorat[doorobjlist[door].tilex][doorobjlist[door].tiley] = 0;
617 }
618
619 doorposition[door] = (word) position;
620}
621
622
623/*
624===============
625=
626= DoorClosing
627=
628===============
629*/
630
631void DoorClosing (int door)
632{
633 unsigned area1,area2;
634 word *map;
635 int32_t position;
636 int tilex,tiley;
637
638 tilex = doorobjlist[door].tilex;
639 tiley = doorobjlist[door].tiley;
640
641 if ( ((int)(uintptr_t)actorat[tilex][tiley] != (door | 0x80))
642 || (player->tilex == tilex && player->tiley == tiley) )
643 { // something got inside the door
644 OpenDoor (door);
645 return;
646 };
647
648 position = doorposition[door];
649
650 //
651 // slide the door by an adaptive amount
652 //
653 position -= tics<<10;
654 if (position <= 0)
655 {
656 //
657 // door is closed all the way, so disconnect the areas
658 //
659 position = 0;
660
661 doorobjlist[door].action = dr_closed;
662
663 map = mapsegs[0] + (doorobjlist[door].tiley<<mapshift) + doorobjlist[door].tilex;
664
665 if (doorobjlist[door].vertical)
666 {
667 area1 = *(map+1);
668 area2 = *(map-1);
669 }
670 else
671 {
672 area1 = *(map-mapwidth);
673 area2 = *(map+mapwidth);
674 }
675 area1 -= AREATILE;
676 area2 -= AREATILE;
677
678 if (area1 < NUMAREAS && area2 < NUMAREAS)
679 {
680 areaconnect[area1][area2]--;
681 areaconnect[area2][area1]--;
682
683 if (player->areanumber < NUMAREAS)
684 ConnectAreas ();
685 }
686 }
687
688 doorposition[door] = (word) position;
689}
690
691
692
693
694/*
695=====================
696=
697= MoveDoors
698=
699= Called from PlayLoop
700=
701=====================
702*/
703
704void MoveDoors (void)
705{
706 int door;
707
708 if (gamestate.victoryflag) // don't move door during victory sequence
709 return;
710
711 for (door = 0; door < doornum; door++)
712 {
713 switch (doorobjlist[door].action)
714 {
715 case dr_open:
716 DoorOpen (door);
717 break;
718
719 case dr_opening:
720 DoorOpening(door);
721 break;
722
723 case dr_closing:
724 DoorClosing(door);
725 break;
726 }
727 }
728}
729
730
731/*
732=============================================================================
733
734 PUSHABLE WALLS
735
736=============================================================================
737*/
738
739word pwallstate;
740word pwallpos; // amount a pushable wall has been moved (0-63)
741word pwallx,pwally;
742byte pwalldir,pwalltile;
743int dirs[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
744
745/*
746===============
747=
748= PushWall
749=
750===============
751*/
752
753void PushWall (int checkx, int checky, int dir)
754{
755 int oldtile, dx, dy;
756
757 if (pwallstate)
758 return;
759
760 oldtile = tilemap[checkx][checky];
761 if (!oldtile)
762 return;
763
764 dx = dirs[dir][0];
765 dy = dirs[dir][1];
766
767 if (actorat[checkx+dx][checky+dy])
768 {
769 SD_PlaySound (NOWAYSND);
770 return;
771 }
772 actorat[checkx+dx][checky+dy] = (objtype *)(uintptr_t) (tilemap[checkx+dx][checky+dy] = oldtile);
773
774 gamestate.secretcount++;
775 pwallx = checkx;
776 pwally = checky;
777 pwalldir = dir;
778 pwallstate = 1;
779 pwallpos = 0;
780 pwalltile = tilemap[pwallx][pwally];
781 tilemap[pwallx][pwally] = 64;
782 tilemap[pwallx+dx][pwally+dy] = 64;
783 *(mapsegs[1]+(pwally<<mapshift)+pwallx) = 0; // remove P tile info
784 *(mapsegs[0]+(pwally<<mapshift)+pwallx) = *(mapsegs[0]+(player->tiley<<mapshift)+player->tilex); // set correct floorcode (BrotherTank's fix)
785
786 SD_PlaySound (PUSHWALLSND);
787}
788
789
790
791/*
792=================
793=
794= MovePWalls
795=
796=================
797*/
798
799void MovePWalls (void)
800{
801 int oldblock,oldtile;
802
803 if (!pwallstate)
804 return;
805
806 oldblock = pwallstate/128;
807
808 pwallstate += (word)tics;
809
810 if (pwallstate/128 != oldblock)
811 {
812 // block crossed into a new block
813 oldtile = pwalltile;
814
815 //
816 // the tile can now be walked into
817 //
818 tilemap[pwallx][pwally] = 0;
819 actorat[pwallx][pwally] = 0;
820 *(mapsegs[0]+(pwally<<mapshift)+pwallx) = player->areanumber+AREATILE;
821
822 int dx=dirs[pwalldir][0], dy=dirs[pwalldir][1];
823 //
824 // see if it should be pushed farther
825 //
826 if (pwallstate>=256) // only move two tiles fix
827 {
828 //
829 // the block has been pushed two tiles
830 //
831 pwallstate = 0;
832 tilemap[pwallx+dx][pwally+dy] = oldtile;
833 return;
834 }
835 else
836 {
837 int xl,yl,xh,yh;
838 xl = (player->x-PLAYERSIZE) >> TILESHIFT;
839 yl = (player->y-PLAYERSIZE) >> TILESHIFT;
840 xh = (player->x+PLAYERSIZE) >> TILESHIFT;
841 yh = (player->y+PLAYERSIZE) >> TILESHIFT;
842
843 pwallx += dx;
844 pwally += dy;
845
846 if (actorat[pwallx+dx][pwally+dy]
847 || xl<=pwallx+dx && pwallx+dx<=xh && yl<=pwally+dy && pwally+dy<=yh)
848 {
849 pwallstate = 0;
850 tilemap[pwallx][pwally] = oldtile;
851 return;
852 }
853 actorat[pwallx+dx][pwally+dy] = (objtype *)(uintptr_t) (tilemap[pwallx+dx][pwally+dy] = oldtile);
854 tilemap[pwallx+dx][pwally+dy] = 64;
855 }
856 }
857
858 pwallpos = (pwallstate/2)&63;
859}