1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program 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.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #include "rt_def.h"
21 #include "rt_sound.h"
22 #include "rt_door.h"
23 #include "rt_actor.h"
24 #include "rt_stat.h"
25 #include "_rt_door.h"
26 #include "z_zone.h"
27 #include "w_wad.h"
28 #include "rt_ted.h"
29 #include "rt_draw.h"
30 #include "rt_main.h"
31 #include "rt_playr.h"
32 #include "rt_util.h"
33 #include "rt_menu.h"
34 #include "rt_ted.h"
35 #include "rt_msg.h"
36 #include "rt_game.h"
37 #include "rt_vid.h"
38 #include "rt_net.h"
39 #include "isr.h"
40 #include "develop.h"
41 #include "rt_rand.h"
42 #include "engine.h"
43 #include <stdlib.h>
44 #include <string.h>
45 //MED
46 #include "memcheck.h"
47
48 /*=============================================================================
49
50 DOORS
51
52 doorobjlist[] holds most of the information for the doors
53
54 Open doors conect two areas, so sounds will travel between them and sight
55 will be checked when the player is in a connected area.
56
57 Areaconnect is incremented/decremented by each door. If >0 they connect
58
59 Every time a door opens or closes the areabyplayer matrix gets recalculated.
60 An area is true if it connects with the player's current spor.
61
62 =============================================================================
63 */
64
65
66 // Global Variables
67
68
69 #define ELEVATORMUSICTIME 560
70
71 elevator_t ELEVATOR[MAXELEVATORS];
72 int _numelevators;
73 animmaskedwallobj_t* FIRSTANIMMASKEDWALL,*LASTANIMMASKEDWALL;
74 maskedwallobj_t* FIRSTMASKEDWALL,*LASTMASKEDWALL;
75 byte touchindices[MAPSIZE][MAPSIZE],lasttouch;
76 touchplatetype *touchplate[MAXTOUCHPLATES],*lastaction[MAXTOUCHPLATES];
77
78 byte numactions[MAXTOUCHPLATES];
79 int totalactions;
80
81 byte TRIGGER[MAXTOUCHPLATES];
82 doorobj_t *doorobjlist[MAXDOORS];
83 int doornum;
84 maskedwallobj_t *maskobjlist[MAXMASKED];
85 int maskednum;
86
87 pwallobj_t *pwallobjlist[MAXPWALLS];
88 int pwallnum;
89
90 byte areaconnect[NUMAREAS][NUMAREAS];
91
92 boolean areabyplayer[NUMAREAS];
93
94
95 // Local Variables
96
97 static void (*touchactions[NUMTOUCHPLATEACTIONS])(int) =
98 {ActivatePushWall,
99 ActivateMoveWall,
100 LinkedOpenDoor,
101 LinkedCloseDoor,
102 EnableObject,
103 DisableObject,
104 ActivateLight,
105 DeactivateLight};
106
107 #if ((DEVELOPMENT == 1))
108 #if ((LOADSAVETEST == 1))
109 static char*touchstrings[NUMTOUCHPLATEACTIONS] =
110 {"ActivatePushWall",
111 "ActivateMoveWall",
112 "LinkedOpenDoor",
113 "LinkedCloseDoor",
114 "EnableObject",
115 "DisableObject",
116 "ActivateLight",
117 "DeactivateLight"
118 };
119 #endif
120 #endif
121 #if ((DEVELOPMENT == 1))
122 #if ((ELEVATORTEST == 1))
123
124 static char*elevstring[NUMELEVATORACTIONS] =
125 {"ready at source",
126 "ready at destination",
127 "moving to source",
128 "moving to destination",
129 "doorclosing"
130 };
131 #endif
132 #endif
133
134 void UtilizeDoor (int door,void (*action)(int));
135 void UseDoor (int door);
136 void Teleport(elevator_t*eptr,int destination);
137 void ConnectPushWall (int pwall);
138 void SetupPushWall (int pwall);
139 void WallMoving (int pwall);
140 int SetNextAction(elevator_t*eptr,int action);
141
142 /*
143 ===============
144 =
145 = MakeMaskedWallActive
146 =
147 ===============
148 */
149
MakeMaskedWallActive(maskedwallobj_t * tmwall)150 void MakeMaskedWallActive(maskedwallobj_t* tmwall)
151 {if (!FIRSTMASKEDWALL)
152 FIRSTMASKEDWALL = tmwall;
153 else
154 {tmwall->prev = LASTMASKEDWALL;
155 LASTMASKEDWALL->next = tmwall;
156 }
157 LASTMASKEDWALL = tmwall;
158 }
159
160 /*
161 ===============
162 =
163 = MakeMaskedWallInactive
164 =
165 ===============
166 */
167
168
MakeMaskedWallInactive(maskedwallobj_t * tmwall)169 void MakeMaskedWallInactive(maskedwallobj_t* tmwall)
170 {
171 if (tmwall == LASTMASKEDWALL)
172 LASTMASKEDWALL = tmwall->prev;
173 else
174 tmwall->next->prev = tmwall->prev;
175
176 if (tmwall == FIRSTMASKEDWALL)
177 FIRSTMASKEDWALL = tmwall->next;
178 else
179 tmwall->prev->next = tmwall->next;
180
181 tmwall->prev = NULL;
182 tmwall->next = NULL;
183
184 }
185
186
187 /*
188 ===============
189 =
190 = ActivateAnimMaskedWall
191 =
192 ===============
193 */
194
ActivateAnimMaskedWall(animmaskedwallobj_t * amwall)195 void ActivateAnimMaskedWall(animmaskedwallobj_t* amwall)
196 {
197 if (!FIRSTANIMMASKEDWALL)
198 FIRSTANIMMASKEDWALL = amwall;
199 else
200 {
201 amwall->prev = LASTANIMMASKEDWALL;
202 LASTANIMMASKEDWALL->next = amwall;
203 }
204 LASTANIMMASKEDWALL = amwall;
205 }
206
207 /*
208 ===============
209 =
210 = DeactivateAnimMaskedWall
211 =
212 ===============
213 */
214
215
DeactivateAnimMaskedWall(animmaskedwallobj_t * amwall)216 void DeactivateAnimMaskedWall(animmaskedwallobj_t* amwall)
217 {
218 if (amwall == LASTANIMMASKEDWALL)
219 LASTANIMMASKEDWALL = amwall->prev;
220 else
221 amwall->next->prev = amwall->prev;
222
223 if (amwall == FIRSTANIMMASKEDWALL)
224 FIRSTANIMMASKEDWALL = amwall->next;
225 else
226 amwall->prev->next = amwall->next;
227
228 amwall->prev = NULL;
229 amwall->next = NULL;
230
231 }
232
233
PlatformHeight(int tilex,int tiley)234 int PlatformHeight(int tilex,int tiley)
235 {
236 int platform;
237
238 if (!IsPlatform(tilex,tiley))
239 return nominalheight;
240
241 platform = MAPSPOT(tilex,tiley,2);
242
243 switch(platform)
244 {
245 case 1:
246 return -10;
247 case 4:
248 return nominalheight;
249 case 5:
250 case 6:
251 return nominalheight - 64;
252 case 7:
253 return nominalheight;
254 case 8:
255 case 9:
256 return -10;
257 }
258
259 return -1000;
260 }
261
SpawnAnimatedMaskedWall(int num)262 void SpawnAnimatedMaskedWall ( int num )
263 {
264 animmaskedwallobj_t * temp;
265
266 temp = (animmaskedwallobj_t *)Z_LevelMalloc(sizeof(animmaskedwallobj_t),PU_LEVELSTRUCT,NULL);
267 if (!temp)
268 Error("SpawnAnimatedMaskedWall: Failed on allocation of animated masked wall");
269 temp->num=num;
270 temp->count=AMW_NUMFRAMES;
271 temp->ticcount=AMW_TICCOUNT;
272 temp->next=NULL;
273 temp->prev=NULL;
274 ActivateAnimMaskedWall(temp);
275 }
276
KillAnimatedMaskedWall(animmaskedwallobj_t * temp)277 void KillAnimatedMaskedWall ( animmaskedwallobj_t * temp )
278 {
279 DeactivateAnimMaskedWall(temp);
280 Z_Free(temp);
281 }
282
283
DoAnimatedMaskedWalls(void)284 void DoAnimatedMaskedWalls ( void )
285 {
286 boolean done;
287 animmaskedwallobj_t * temp;
288
289 for(temp=FIRSTANIMMASKEDWALL;temp;)
290 {
291 done=false;
292 temp->ticcount-=tics;
293 while (temp->ticcount<0)
294 {
295 temp->ticcount+=AMW_TICCOUNT;
296 temp->count--;
297 maskobjlist[temp->num]->bottomtexture++;
298 if (temp->count==0)
299 {
300 done=true;
301 break;
302 }
303 }
304 if (done==true)
305 {
306 animmaskedwallobj_t * temp2;
307
308 temp2=temp->next;
309 KillAnimatedMaskedWall(temp);
310 temp=temp2;
311 }
312 else
313 temp=temp->next;
314 }
315 }
316
317
GetIndexForAction(void (* action)(int))318 int GetIndexForAction(void (*action)(int))
319 {int i;
320
321 for(i=0;i<NUMTOUCHPLATEACTIONS;i++)
322 if (action == touchactions[i])
323 return i;
324
325 Error("Touchplate Action Not Matched");
326 return -1;
327 }
328
329
SaveTouchPlates(byte ** buffer,int * size)330 void SaveTouchPlates(byte ** buffer,int *size)
331 {int i,k;
332 byte * tptr;
333 touchplatetype *temp;
334 saved_touch_type dummy;
335
336 *size = sizeof(TRIGGER);
337 *size += sizeof(numactions);
338 *size += sizeof(saved_touch_type)*totalactions;
339
340 *buffer = (byte *)SafeMalloc(*size);
341 tptr = *buffer;
342 memcpy(tptr,&TRIGGER[0],sizeof(TRIGGER));
343 tptr+=sizeof(TRIGGER);
344
345 memcpy(tptr,&numactions[0],sizeof(numactions));
346 tptr+=sizeof(numactions);
347
348 #if ((DEVELOPMENT == 1))
349 #if (LOADSAVETEST == 1)
350 Debug("\n\nSAVE INFO\n");
351 Debug("---------");
352
353 Debug("\n\nTOUCHINDICES\n");
354 Debug("------------\n\n");
355 for(i=0;i<MAPSIZE;i++)
356 for(j=0;j< MAPSIZE;j++)
357 if (touchindices[i][j])
358 Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
359
360 Debug("\n\nTRIGGER: ");
361 for(i=0;i<(sizeof(TRIGGER)/sizeof(TRIGGER[0]));i++)
362 if (TRIGGER[i])
363 Debug("%1d",TRIGGER[i]);
364 Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
365 Debug("-------------------------\n\n");
366 for(i=0;i<(sizeof(numactions)/sizeof(numactions[0]));i++)
367 if (numactions[i])
368 Debug("\n %2d: %2d",i,numactions[i]);
369 #endif
370 #endif
371
372 for(i=0;i<lasttouch;i++)
373 {
374 #if ((DEVELOPMENT == 1))
375 #if (LOADSAVETEST == 1)
376 Debug("\n\nTOUCHPLATE[%2d]\n",i);
377 Debug("--------------\n\n");
378 #endif
379 #endif
380
381 for(k=0,temp=touchplate[i];temp;k++,temp = temp->nextaction)
382 {
383 dummy.tictime = temp->tictime;
384 dummy.ticcount = temp->ticcount;
385 dummy.triggered = temp->triggered;
386 dummy.done = temp->done;
387 dummy.complete = temp->complete;
388
389 if (temp->action)
390 dummy.actionindex = GetIndexForAction(temp->action);
391 else
392 dummy.actionindex = -1;
393
394 if (temp->swapaction)
395 dummy.swapactionindex = GetIndexForAction(temp->swapaction);
396 else
397 dummy.swapactionindex = -1;
398 if ((dummy.actionindex > 5) || (dummy.swapactionindex > 5)) // means whichobj holds pointer to actor
399 {
400 statobj_t *tstat;
401
402 tstat = (statobj_t*)(temp->whichobj);
403 dummy.whichobj = (tstat->whichstat|FL_TSTAT);
404 }
405
406 else if ((dummy.actionindex > 3) || (dummy.swapactionindex > 3))
407
408 {
409 objtype *tactor;
410
411 tactor = (objtype*)(temp->whichobj);
412 dummy.whichobj = (tactor->whichactor|FL_TACT);
413 }
414
415 else
416 dummy.whichobj = temp->whichobj;
417
418 #if ((DEVELOPMENT == 1))
419 #if (LOADSAVETEST == 1)
420 Debug("action node %d: tictime: %d, ticcount: %d ",k,dummy.tictime,dummy.ticcount);
421 if (dummy.actionindex == -1)
422 Debug("action: -1,");
423 else
424 Debug("action: %13s,",touchstrings[dummy.actionindex]);
425
426 if (dummy.swapactionindex == -1)
427 Debug("swapaction: -1,");
428 else
429 Debug("swapaction: %13s,",touchstrings[dummy.swapactionindex]);
430
431 if (dummy.whichobj & FL_TACT)
432 Debug("whichobj (actor): %4x\n",(dummy.whichobj & ~FL_TACT));
433 else
434 Debug("whichobj (nonactor): %4x\n",dummy.whichobj);
435 #endif
436 #endif
437
438
439 memcpy(tptr,&dummy,sizeof(saved_touch_type));
440 tptr+=sizeof(saved_touch_type);
441 }
442 }
443 }
444
GetStatForIndex(int index)445 statobj_t* GetStatForIndex(int index)
446 {statobj_t *temp;
447
448 for(temp = FIRSTSTAT;temp;temp=temp->statnext)
449 if (temp->whichstat == index)
450 return temp;
451
452 SoftError("\nstat not found in GetStatForIndex");
453 return NULL;
454
455 }
456
457
LoadTouchPlates(byte * buffer,int size)458 void LoadTouchPlates(byte * buffer, int size)
459 {touchplatetype *temp;
460 int i,savedactions,loadedactions,index=0;
461 saved_touch_type dummy;
462
463 savedactions = (size-sizeof(TRIGGER)-sizeof(numactions))/sizeof(saved_touch_type);
464 memset(touchplate,0,sizeof(touchplate));
465 memset(lastaction,0,sizeof(lastaction));
466 memset(numactions,0,sizeof(numactions));
467 totalactions = 0;
468
469 memcpy(&TRIGGER[0],buffer,sizeof(TRIGGER));
470 buffer += sizeof(TRIGGER);
471
472 memcpy(&numactions[0],buffer,sizeof(numactions));
473 buffer += sizeof(numactions);
474
475 for(loadedactions=0,index=0,i=0;i<savedactions;i++)
476 {memcpy(&dummy,buffer,sizeof(saved_touch_type));
477 temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
478 if (!temp)
479 Error("LoadTouchplates: Failed on allocation of touchplates %ld of %ld",i,savedactions);
480 memset(temp,0,sizeof(*temp));
481
482 temp->tictime = dummy.tictime;
483 temp->ticcount = dummy.ticcount;
484 temp->triggered = dummy.triggered;
485 temp->done = dummy.done;
486 temp->complete = dummy.complete;
487
488 if (dummy.whichobj & FL_TACT)
489 temp->whichobj = (int)(objlist[dummy.whichobj & ~FL_TACT]);
490
491 else if (dummy.whichobj & FL_TSTAT)
492 temp->whichobj = (int)(GetStatForIndex(dummy.whichobj & ~FL_TSTAT));
493 else
494 temp->whichobj = dummy.whichobj;
495 if (dummy.actionindex != -1)
496 temp->action = touchactions[dummy.actionindex];
497 else
498 temp->action = NULL;
499
500 if (dummy.swapactionindex != -1)
501 temp->swapaction = touchactions[dummy.swapactionindex];
502 else
503 temp->swapaction = NULL;
504
505 buffer+=sizeof(saved_touch_type);
506
507 while (!numactions[index])
508 index ++;
509
510 AddTouchplateAction(temp,index);
511
512 /*if (touchplate[index])
513 lastaction[index]->nextaction = temp;
514 else
515 touchplate[index] = temp;
516 lastaction[index] = temp;*/
517
518 totalactions ++;
519
520 loadedactions++;
521 if (loadedactions == numactions[index]) // found end of a touchplate's actions, goto next touch.
522 {loadedactions = 0;
523 index++;
524 }
525 }
526
527
528 #if ((DEVELOPMENT == 1))
529 #if (LOADSAVETEST == 1)
530 Debug("\n\nLOAD INFO\n");
531 Debug("---------");
532
533 Debug("\n\nTOUCHINDICES\n");
534 Debug("------------\n\n");
535 for(i=0;i<MAPSIZE;i++)
536 for(j=0;j< MAPSIZE;j++)
537 if (touchindices[i][j])
538 Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
539
540 Debug("\n\nTRIGGER: ");
541 for(i=0;i<(sizeof(TRIGGER)/sizeof(TRIGGER[0]));i++)
542 if (TRIGGER[i])
543 Debug("%1d",TRIGGER[i]);
544 Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
545 Debug("-------------------------\n\n");
546 for(i=0;i<(sizeof(numactions)/sizeof(numactions[0]));i++)
547 if (numactions[i])
548 Debug("\n %2d: %2d",i,numactions[i]);
549
550 for(i=0;i<lasttouch;i++)
551 {
552 Debug("\n\nTOUCHPLATE[%2d]\n",i);
553 Debug("--------------\n\n");
554
555 for(k=0,temp=touchplate[i];temp;k++,temp = temp->nextaction)
556 {
557 Debug("action node %d: tictime: %d, ticcount: %d ",k,temp->tictime,temp->ticcount);
558 if (!temp->action)
559 Debug("action: NULL,");
560 else
561 Debug("action: %13s,",touchstrings[GetIndexForAction(temp->action)]);
562
563 if (!temp->swapaction)
564 Debug("swapaction: NULL,");
565 else
566 Debug("swapaction: %13s,",touchstrings[GetIndexForAction(temp->swapaction)]);
567
568 Debug("whichobj: %4x\n",(int)temp->whichobj);
569 }
570 }
571 #endif
572 #endif
573
574 SafeFree(objlist);
575
576 }
577
578
579
580
AddTouchplateAction(touchplatetype * tplate,int index)581 void AddTouchplateAction(touchplatetype *tplate,int index)
582 {
583 if (touchplate[index])
584 {tplate->prevaction = lastaction[index];
585 lastaction[index]->nextaction = tplate;
586 }
587 else
588 touchplate[index] = tplate;
589 lastaction[index] = tplate;
590
591 }
592
593
594
595
RemoveTouchplateAction(touchplatetype * tplate,int index)596 void RemoveTouchplateAction(touchplatetype *tplate,int index)
597 {
598 if (tplate == lastaction[index]) // remove from master list
599 lastaction[index] = tplate->prevaction;
600 else
601 tplate->nextaction->prevaction = tplate->prevaction;
602
603 if (tplate == touchplate[index])
604 touchplate[index] = tplate->nextaction;
605 else
606 tplate->prevaction->nextaction = tplate->nextaction;
607
608 Z_Free(tplate);
609 numactions[index]--;
610 totalactions--;
611
612 }
613
614
615
Link_To_Touchplate(word touchlocx,word touchlocy,void (* maction)(int),void (* swapaction)(int),int wobj,int delaytime)616 void Link_To_Touchplate(word touchlocx, word touchlocy, void (*maction)(int), void (*swapaction)(int), int wobj, int delaytime)
617 {touchplatetype *temp;
618 int index;
619
620 index = touchindices[touchlocx][touchlocy]-1;
621
622 temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
623 if (!temp)
624 Error("Link_To_Touchplate: Failed on allocation of touchplate\n");
625 memset(temp,0,sizeof(*temp));
626 temp->action = maction;
627 temp->swapaction = swapaction;
628 temp->whichobj = wobj;
629 temp->tictime = temp->ticcount = delaytime;
630
631 AddTouchplateAction(temp,index);
632 /*if(touchplate[index])
633 lastaction[index]->nextaction=temp;
634 else
635 touchplate[index] = temp;
636 lastaction[index] = temp;*/
637 numactions[index]++;
638 totalactions++;
639 }
640
641
642
ClockLink(void (* saction)(int),void (* eaction)(int),int wobj,int whichclock)643 void ClockLink (void (*saction)(int), void (*eaction)(int), int wobj,int whichclock)
644 {touchplatetype*temp;
645
646
647 // adding two actions per clock
648 temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
649 if (!temp)
650 Error("ClockLink: Failed on allocation of clock");
651 memset(temp,0,sizeof(*temp));
652 temp->action = saction;
653 temp->swapaction = eaction;
654 temp->whichobj = wobj;
655 temp->clocktype = 1;
656
657 AddTouchplateAction(temp,whichclock);
658 /* if(touchplate[whichclock])
659 lastaction[whichclock]->nextaction = temp;
660 else
661 touchplate[whichclock] = temp;
662 lastaction[whichclock]=temp;*/
663
664 numactions[whichclock]++;
665 totalactions ++;
666 }
667
668
DisplayMessageForAction(touchplatetype * temp,boolean * wallmessage,boolean * doormessage,boolean * columnmessage)669 void DisplayMessageForAction(touchplatetype *temp, boolean *wallmessage,
670 boolean *doormessage, boolean*columnmessage)
671 {
672
673 if ((temp->action == ActivatePushWall) ||
674 (temp->action == ActivateMoveWall)
675 )
676 {
677 if (*wallmessage == false)
678 {
679 if (temp->clocktype)
680 AddMessage("Time-delay wall moves.",MSG_GAME);
681 else
682 AddMessage("A wall moves.",MSG_GAME);
683 *wallmessage = true;
684 }
685 }
686
687 else if (temp->action == LinkedCloseDoor)
688 {
689 if (*doormessage == false)
690 {
691 if (temp->clocktype)
692 AddMessage("Time-delay door closes.",MSG_GAME);
693 else
694 AddMessage("A door closes.",MSG_GAME);
695 *doormessage = true;
696 }
697 }
698
699 else if (temp->action == LinkedOpenDoor)
700 {
701 if (*doormessage == false)
702 {
703 if (temp->clocktype)
704 AddMessage("Time-delay door opens.",MSG_GAME);
705 else
706 AddMessage("A door opens.",MSG_GAME);
707 *doormessage = true;
708 }
709 }
710
711 else if (temp->action == EnableObject)
712 {
713 objtype *tempactor = (objtype*)(temp->whichobj);
714
715 if (M_ISACTOR(tempactor) && (tempactor->obclass == pillarobj))
716 {
717 if (*columnmessage == false)
718 {
719 if (temp->clocktype)
720 AddMessage("Time-delay column moves.",MSG_GAME);
721 else
722 AddMessage("A column moves.",MSG_GAME);
723 *columnmessage = true;
724 }
725 }
726 }
727 }
728
TriggerStuff(void)729 void TriggerStuff(void)
730 {
731 touchplatetype *temp;
732 int i,touchcomplete,j;
733 int playeron;
734 void (*tempact)(int);
735 boolean wallmessage,doormessage,columnmessage;
736
737 for(i=0;i<lasttouch;i++)
738 {
739 playeron = false;
740 for( j = 0; j < numplayers; j++ )
741 {
742 if ( i == touchindices[ PLAYER[ j ]->tilex ][ PLAYER[ j ]->tiley ] - 1 )
743 {
744 playeron = true;
745 break;
746 }
747 }
748
749
750 if (!TRIGGER[i])
751 continue;
752
753 else if (touchplate[i]->complete)
754 {
755 if (!playeron)
756 TRIGGER[i] = 0;
757 continue;
758 }
759
760 if (touchplate[i]->done)
761 {
762 if (!playeron)
763 {
764 for(temp = touchplate[i];temp;temp = temp->nextaction)
765 temp->triggered=false;
766 TRIGGER[i] = 0;
767 touchplate[i]->done = false;
768 }
769 }
770
771 else
772 {
773 wallmessage = false;
774 doormessage = false;
775 columnmessage = false;
776
777 for(temp = touchplate[i];temp;temp = temp->nextaction)
778 {
779 if (temp->action && (!temp->triggered))
780 {
781 if (!temp->ticcount)
782 {
783 temp->action(temp->whichobj);
784 if (temp->action == ActivateMoveWall)
785 {
786 int tilex,tiley;
787
788 tilex = pwallobjlist[temp->whichobj]->tilex;
789 tiley = pwallobjlist[temp->whichobj]->tiley;
790 tilemap[tilex][tiley] = 0;
791
792 }
793 if (gamestate.difficulty == gd_baby)
794 {
795 DisplayMessageForAction(temp,&wallmessage,&doormessage,&columnmessage);
796 }
797
798 tempact = temp->action;
799 temp->action = temp->swapaction;
800 temp->swapaction = tempact;
801 temp->ticcount = temp->tictime;
802 temp->triggered = true;
803 }
804
805 else
806 temp->ticcount --;
807 }
808 }
809 //done:
810
811 // check to see if any actions will ever be triggered by this
812 // touchplate again; if not, null touchplate out; else,
813 // check status of other actions
814
815 touchcomplete = 1;
816 for(temp = touchplate[i];temp;temp = temp->nextaction)
817 {
818 if (temp->action)
819 {
820 touchcomplete = 0;
821 break;
822 }
823 }
824
825 if (touchcomplete)
826 touchplate[i]->complete = 1; // this touchplate is out of commission
827 else
828 {
829 touchplate[i]->done = true;
830 for(temp = touchplate[i];temp;temp = temp->nextaction)
831 {
832 if (temp->action && (!temp->triggered))
833 {
834 touchplate[i]->done = false;
835 break;
836 }
837 }
838 }
839 }
840 }
841 }
842
843
844 //==================== Tile stuff ====================================
845
CheckTile(int x,int y)846 boolean CheckTile(int x, int y)
847 {
848
849 if ((x < 2) || (x > (MAPSIZE-1)) || (y < 2) || (y > (MAPSIZE - 1)))
850 return false;
851
852 if (actorat[x][y])
853 {objtype *check = (objtype*)(actorat[x][y]);
854 if (insetupgame)
855 return false;
856 if (!(M_ISACTOR(check) && (check->obclass == playerobj)))
857 return false;
858 }
859 if (DiskAt(x,y))
860 return false;
861 if (sprites[x][y])
862 return false;
863 if ((tilemap[x][y]) && (IsPlatform(x,y)==false))
864 return false;
865 if ((AREANUMBER(x,y)<=0) || (AREANUMBER(x,y)>NUMAREAS))
866 return false;
867 if (IsWindow(x,y))
868 return false;
869 return true;
870 }
871
872
873 #define CountTile(x,y) \
874 { \
875 if (oldarea == AREANUMBER(x,y))\
876 {if (CheckTile(x,y)) \
877 numemptytiles ++; \
878 \
879 areanumbercount++; \
880 if (areanumbercount == numareatiles[oldarea])\
881 return numemptytiles; \
882 } \
883 \
884 } \
885
886
Number_of_Empty_Tiles_In_Area_Around(int x,int y)887 int Number_of_Empty_Tiles_In_Area_Around(int x, int y)
888 {int roverx,rovery,areanumbercount=0,
889 numemptytiles=0,oldarea,i,limit,j;
890
891 oldarea = AREANUMBER(x,y);
892
893 for (i=1;;i++)
894 {roverx = x-i;
895 rovery = y-i;
896
897 CountTile(roverx,rovery);
898 limit = i<<1;
899
900 for(j=0;j<limit;j++)
901 {roverx++;
902 CountTile(roverx,rovery);
903 }
904
905 for(j=0;j<limit;j++)
906 {rovery++;
907 CountTile(roverx,rovery);
908 }
909
910 for(j=0;j<limit;j++)
911 {roverx--;
912 CountTile(roverx,rovery);
913 }
914
915 for(j=0;j<limit-1;j++)
916 {rovery--;
917 CountTile(roverx,rovery);
918 }
919 }
920 }
921
922
923
924 #define CheckSet(x,y) \
925 {if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y))) \
926 {*stilex = x; \
927 *stiley = y; \
928 return; \
929 } \
930 } \
931
932
933
FindEmptyTile(int * stilex,int * stiley)934 void FindEmptyTile(int *stilex, int *stiley)
935 {
936 int i,j,x,y,oldarea,roverx,rovery,limit;
937
938 oldarea = AREANUMBER(*stilex,*stiley);
939
940 x = *stilex;
941 y = *stiley;
942
943 if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y)))
944 return;
945
946 for (i=1;;i++)
947 {roverx = x-i;
948 rovery = y-i;
949
950 CheckSet(roverx,rovery);
951 limit = i<<1;
952
953 for(j=0;j<limit;j++)
954 {roverx++;
955 CheckSet(roverx,rovery);
956 }
957
958 for(j=0;j<limit;j++)
959 {rovery++;
960 CheckSet(roverx,rovery);
961 }
962
963 for(j=0;j<limit;j++)
964 {roverx--;
965 CheckSet(roverx,rovery);
966 }
967
968 for(j=0;j<limit-1;j++)
969 {rovery--;
970 CheckSet(roverx,rovery);
971 }
972 }
973 }
974
975 //================================================================
976
977
978
979
RecursiveConnect(int areanumber)980 void RecursiveConnect (int areanumber)
981 {
982 int i;
983
984 for (i=0;i<NUMAREAS;i++)
985 {
986 if (areaconnect[areanumber][i] && !areabyplayer[i])
987 {
988 areabyplayer[i] = true;
989 RecursiveConnect (i);
990 }
991 }
992 }
993
994
995 /*
996 ==============
997 =
998 = ConnectAreas
999 =
1000 = Scans outward from playerarea, marking all connected areas
1001 =
1002 ==============
1003 */
1004
ConnectAreas(void)1005 void ConnectAreas (void)
1006 {objtype*temp;
1007 statobj_t*tstat;
1008 int i;
1009 #define MASTER_DISK(ob) ((ob->obclass == diskobj) && (ob->flags & FL_MASTER))
1010
1011 memset (areabyplayer,0,sizeof(areabyplayer));
1012 for (i=0;i<numplayers;i++)
1013 {
1014 areabyplayer[PLAYER[i]->areanumber] = true;
1015 RecursiveConnect (PLAYER[i]->areanumber);
1016 }
1017 for(temp=FIRSTACTOR;temp;temp=temp->next)
1018 {
1019 if (MASTER_DISK(temp))
1020 continue;
1021 if (!areabyplayer[temp->areanumber])
1022 continue;
1023 if (!(temp->flags & FL_ABP))
1024 {temp->flags |= FL_ABP;
1025 MakeActive(temp);
1026 }
1027 }
1028
1029 for(tstat=FIRSTSTAT;tstat;tstat=tstat->statnext)
1030 {if (areabyplayer[tstat->areanumber])
1031 {if (!(tstat->flags & FL_ABP))
1032 {tstat->flags |= FL_ABP;
1033 MakeStatActive(tstat);
1034 }
1035 }
1036 else if (tstat->flags & FL_ABP)
1037 {MakeStatInactive(tstat);
1038 tstat->flags &= ~FL_ABP;
1039 }
1040 }
1041
1042 for(i=0;i<maskednum;i++)
1043 {if (areabyplayer[maskobjlist[i]->areanumber])
1044 {if (!(maskobjlist[i]->flags & MW_ABP))
1045 {maskobjlist[i]->flags |= MW_ABP;
1046 MakeMaskedWallActive(maskobjlist[i]);
1047 }
1048 }
1049 else if (maskobjlist[i]->flags & MW_ABP)
1050 {MakeMaskedWallInactive(maskobjlist[i]);
1051 maskobjlist[i]->flags &= ~MW_ABP;
1052 }
1053 }
1054 }
1055
1056
InitAreas(void)1057 void InitAreas (void)
1058 {
1059 memset (areabyplayer,0,sizeof(areabyplayer));
1060 memset (areaconnect,0,sizeof(areaconnect));
1061 }
1062
1063
1064 /*
1065 ===============
1066 =
1067 = InitDoorList
1068 =
1069 ===============
1070 */
1071
InitDoorList(void)1072 void InitDoorList (void)
1073 {
1074 doornum=0;
1075 pwallnum=0;
1076 maskednum=0;
1077 lasttouch = 0;
1078 numclocks=0;
1079
1080 memset(touchindices,0,sizeof(touchindices));
1081 memset(touchplate,0,sizeof(touchplate));
1082 memset(lastaction,0,sizeof(lastaction));
1083 memset(numactions,0,sizeof(numactions));
1084 totalactions = 0;
1085 memset(TRIGGER,0,sizeof(TRIGGER));
1086 memset(Clocks,0,sizeof(Clocks));
1087 FIRSTMASKEDWALL=NULL;
1088 LASTMASKEDWALL=NULL;
1089 FIRSTANIMMASKEDWALL=NULL;
1090 LASTANIMMASKEDWALL=NULL;
1091 }
1092
1093 /*
1094 ===============
1095 =
1096 = IsWall
1097 =
1098 ===============
1099 */
1100
IsWall(int tilex,int tiley)1101 int IsWall (int tilex, int tiley)
1102 {
1103 int map;
1104
1105 map=MAPSPOT(tilex,tiley,0);
1106
1107 if ((map>=1) && (map<=89))
1108 return 1;
1109
1110 else if ((map>=106) && (map<=107))
1111 return 1;
1112
1113 else if ((map>=224) && (map<=233))
1114 return 1;
1115
1116 else if ((map>=242) && (map<=244))
1117 return 1;
1118
1119 return 0;
1120 }
1121
1122
1123
1124 /*
1125 ===============
1126 =
1127 = InitElevators
1128 =
1129 ===============
1130 */
1131
InitElevators(void)1132 void InitElevators(void)
1133 {_numelevators = 0;
1134 memset(ELEVATOR,0,sizeof(ELEVATOR));
1135
1136 }
1137
1138
1139
1140 /*
1141 ===============
1142 =
1143 = IsDoor
1144 =
1145 ===============
1146 */
1147
IsDoor(int tilex,int tiley)1148 int IsDoor (int tilex, int tiley)
1149 {
1150 int map;
1151
1152 map=MAPSPOT(tilex,tiley,0);
1153
1154 if ((map>=33) && (map<=35))
1155 return 1;
1156
1157 if ((map>=90) && (map<=104))
1158 return 1;
1159
1160 if ((map>=154) && (map<=156))
1161 return 1;
1162
1163 if (M_ISDOOR(tilex,tiley))
1164 return 1;
1165
1166 return 0;
1167 }
1168
1169
1170 /*
1171 ===============
1172 =
1173 = SpawnDoor
1174 =
1175 ===============
1176 */
1177
SpawnDoor(int tilex,int tiley,int lock,int texture)1178 void SpawnDoor (int tilex, int tiley, int lock, int texture)
1179 {
1180 int i;
1181 doorobj_t * lastdoorobj;
1182 int up,dn,lt,rt;
1183 int abovewallstart;
1184 int swallstart;
1185 int basetexture;
1186
1187 abovewallstart=W_GetNumForName("ABVWSTRT")+1;
1188 swallstart=W_GetNumForName("SIDESTRT")+1;
1189
1190 doorobjlist[doornum]=(doorobj_t*)Z_LevelMalloc(sizeof(doorobj_t),PU_LEVELSTRUCT,NULL);
1191 if (!doorobjlist[doornum])
1192 Error("SpawnDoor: Failed on allocation of door %ld ",doornum);
1193 memset(doorobjlist[doornum],0,sizeof(doorobj_t));
1194 lastdoorobj=doorobjlist[doornum];
1195
1196 if (
1197 ( MAPSPOT(tilex,tiley,1) >= 29 ) &&
1198 ( MAPSPOT(tilex,tiley,1) <= 32 )
1199 )
1200 {
1201 lock = MAPSPOT(tilex,tiley,1) - 28;
1202 }
1203
1204 lastdoorobj->position = 0;
1205 lastdoorobj->tilex = tilex;
1206 lastdoorobj->tiley = tiley;
1207 lastdoorobj->lock = lock;
1208 lastdoorobj->action = dr_closed;
1209 lastdoorobj->which = DOOR;
1210 lastdoorobj->flags = 0;
1211 lastdoorobj->eindex = -1;
1212
1213 //
1214 // make the door space solid
1215 //
1216
1217 if (loadedgame==false)
1218 actorat[tilex][tiley] = lastdoorobj;
1219
1220 if (IsDoor(tilex,tiley-1)) up=2;
1221 else if (IsWall(tilex,tiley-1)) up=1;
1222 else up=0;
1223
1224 if (IsDoor(tilex,tiley+1)) dn=2;
1225 else if (IsWall(tilex,tiley+1)) dn=1;
1226 else dn=0;
1227
1228 if (IsDoor(tilex-1,tiley)) lt=2;
1229 else if (IsWall(tilex-1,tiley)) lt=1;
1230 else lt=0;
1231
1232 if (IsDoor(tilex+1,tiley)) rt=2;
1233 else if (IsWall(tilex+1,tiley)) rt=1;
1234 else rt=0;
1235
1236 if ((up==1) && (dn==1))
1237 lastdoorobj->vertical = true;
1238 else if ((lt==1) && (rt==1))
1239 lastdoorobj->vertical = false;
1240 else if ((up>0) && (dn>0))
1241 lastdoorobj->vertical = true;
1242 else if ((lt>0) && (rt>0))
1243 lastdoorobj->vertical = false;
1244 else if (up>0)
1245 lastdoorobj->vertical = true;
1246 else if (dn>0)
1247 lastdoorobj->vertical = true;
1248 else if (lt>0)
1249 lastdoorobj->vertical = false;
1250 else if (rt>0)
1251 lastdoorobj->vertical = false;
1252
1253 switch (texture)
1254 {
1255
1256 case 0:
1257 case 8:
1258 basetexture = W_GetNumForName("RAMDOOR1\0");
1259 break;
1260
1261 case 1:
1262 case 9:
1263 basetexture = W_GetNumForName("DOOR2\0");
1264 break;
1265
1266
1267 case 2:
1268 case 3:
1269 case 13:
1270 basetexture = W_GetNumForName("TRIDOOR1\0");
1271 break;
1272
1273 case 10:
1274 case 11:
1275 case 14:
1276 basetexture = W_GetNumForName("SDOOR4\0");
1277 break;
1278
1279
1280
1281 case 12:
1282 basetexture = W_GetNumForName("EDOOR\0");
1283 break;
1284 case 15:
1285 basetexture = W_GetNumForName("SNDOOR\0");
1286 break;
1287 case 16:
1288 basetexture = W_GetNumForName("SNADOOR\0");
1289 break;
1290 case 17:
1291 basetexture = W_GetNumForName("SNKDOOR\0");
1292 break;
1293
1294 case 18:
1295 basetexture = W_GetNumForName("TNDOOR\0");
1296 break;
1297 case 19:
1298 basetexture = W_GetNumForName("TNADOOR\0");
1299 break;
1300 case 20:
1301 basetexture = W_GetNumForName("TNKDOOR\0");
1302 break;
1303 default:
1304 Error("Illegal door value encountered\n");
1305 break;
1306 }
1307 lastdoorobj->basetexture = basetexture;
1308 lastdoorobj->texture = lastdoorobj->basetexture;
1309
1310 SD_PreCacheSoundGroup(SD_OPENDOORSND,SD_CLOSEDOORSND);
1311
1312 //
1313 // make the door tile a special tile, and mark the adjacent tiles
1314 // for door sides
1315 //
1316 tilemap[tilex][tiley] = doornum | 0x8000;
1317
1318 switch (texture)
1319 {
1320 case 0:
1321 case 1:
1322 case 2:
1323 case 3:
1324 case 8:
1325 case 9:
1326 case 10:
1327 case 11:
1328 case 12:
1329 case 13:
1330 case 14:
1331 lastdoorobj->sidepic = W_GetNumForName("SIDE8");
1332 lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
1333 break;
1334
1335 case 15:
1336 case 16:
1337 case 17:
1338 if (isSHAREWARE) {
1339 lastdoorobj->sidepic = W_GetNumForName("SIDE8");
1340 } else {
1341 lastdoorobj->sidepic = W_GetNumForName("SIDE16");
1342 }
1343 lastdoorobj->alttexture = W_GetNumForName("ABOVEW16");
1344 break;
1345
1346 case 18:
1347 case 19:
1348 case 20:
1349 if (isSHAREWARE) {
1350 lastdoorobj->sidepic = W_GetNumForName("SIDE8");
1351 lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
1352
1353 } else {
1354 lastdoorobj->sidepic = W_GetNumForName("SIDE17");
1355 lastdoorobj->alttexture = W_GetNumForName("ABOVEW17");
1356
1357 }
1358
1359 break;
1360 default:
1361 Error("Illegal door value encountered\n");
1362 break;
1363 }
1364
1365
1366
1367 if ((lock>0) && (lock<5))
1368 lastdoorobj->sidepic = W_GetNumForName("lock1")+lock-1;
1369
1370 PreCacheLump(lastdoorobj->sidepic,PU_CACHEWALLS);
1371 PreCacheLump(lastdoorobj->alttexture,PU_CACHEWALLS);
1372
1373 if (lastdoorobj->vertical==true)
1374 {
1375 if (up==1)
1376 tilemap[tilex][tiley-1] |= 0x4000;
1377 else if (up==2)
1378 lastdoorobj->flags|=DF_MULTI;
1379 if (dn==1)
1380 tilemap[tilex][tiley+1] |= 0x4000;
1381 else if (dn==2)
1382 lastdoorobj->flags|=DF_MULTI;
1383 }
1384 else
1385 {
1386 if (lt==1)
1387 tilemap[tilex-1][tiley] |= 0x4000;
1388 else if (lt==2)
1389 lastdoorobj->flags|=DF_MULTI;
1390 if (rt==1)
1391 tilemap[tilex+1][tiley] |= 0x4000;
1392 else if (rt==2)
1393 lastdoorobj->flags|=DF_MULTI;
1394 }
1395
1396 for (i=0;i<9;i++)
1397 PreCacheLump(lastdoorobj->texture+i,PU_CACHEWALLS);
1398 doornum++;
1399 lastdoorobj++;
1400 if (doornum==MAXDOORS)
1401 Error ("Too many doors on level!");
1402
1403 }
1404
1405 /*
1406 ===============
1407 =
1408 = MakeWideDoorVisible
1409 =
1410 ===============
1411 */
MakeWideDoorVisible(int doornum)1412 void MakeWideDoorVisible ( int doornum )
1413 {
1414 int dx,dy;
1415 doorobj_t * dr2;
1416 doorobj_t * dr;
1417 int tx,ty;
1418
1419 dr=doorobjlist[doornum];
1420
1421 dx=0;dy=0;
1422 if (dr->vertical==true)
1423 dy=1;
1424 else
1425 dx=1;
1426 spotvis[dr->tilex][dr->tiley]=1;
1427 tx=dr->tilex+dx;
1428 ty=dr->tiley+dy;
1429 while (M_ISDOOR(tx,ty))
1430 {
1431 int num;
1432
1433 num=tilemap[tx][ty]&0x3ff;
1434 dr2=doorobjlist[num];
1435 if (!(dr2->flags&DF_MULTI))
1436 break;
1437 spotvis[tx][ty]=1;
1438
1439 tx+=dx;
1440 ty+=dy;
1441 }
1442 tx=dr->tilex-dx;
1443 ty=dr->tiley-dy;
1444 while (M_ISDOOR(tx,ty))
1445 {
1446 int num;
1447
1448 num=tilemap[tx][ty]&0x3ff;
1449 dr2=doorobjlist[num];
1450 if (!(dr2->flags&DF_MULTI))
1451 break;
1452 spotvis[tx][ty]=1;
1453
1454 tx-=dx;
1455 ty-=dy;
1456 }
1457 }
1458
1459 /*
1460 =====================
1461 =
1462 = LockLinkedDoor
1463 =
1464 =====================
1465 */
1466
LockLinkedDoor(int door)1467 void LockLinkedDoor (int door)
1468 {
1469 doorobj_t*dptr;
1470
1471 dptr = doorobjlist[door];
1472 if (!dptr->lock)
1473 dptr->lock=5;
1474 }
1475
1476 /*
1477 =====================
1478 =
1479 = IsDoorLinked
1480 =
1481 =====================
1482 */
1483
IsDoorLinked(int door)1484 boolean IsDoorLinked (int door)
1485 {
1486 doorobj_t*dptr;
1487
1488 dptr = doorobjlist[door];
1489 if (dptr->lock==5)
1490 return true;
1491 return false;
1492 }
1493
1494
1495 /*
1496 ===============
1497 =
1498 = FixDoorAreaNumbers
1499 =
1500 ===============
1501 */
FixDoorAreaNumbers(void)1502 void FixDoorAreaNumbers ( void )
1503 {
1504 int i;
1505 int up,dn,lt,rt;
1506 int tilex,tiley;
1507
1508 for (i=0;i<doornum;i++)
1509 {
1510 tilex=doorobjlist[i]->tilex;
1511 tiley=doorobjlist[i]->tiley;
1512 up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
1513 dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
1514 lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
1515 rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
1516
1517 up = ((up>0) && (up<=NUMAREAS));
1518 dn = ((dn>0) && (dn<=NUMAREAS));
1519 lt = ((lt>0) && (lt<=NUMAREAS));
1520 rt = ((rt>0) && (rt<=NUMAREAS));
1521
1522
1523 if (doorobjlist[i]->vertical==true)
1524 {
1525 if (rt)
1526 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
1527 else if (lt)
1528 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
1529 else
1530 Error("FixDoors: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
1531 }
1532 else
1533 {
1534 if (dn)
1535 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
1536 else if (up)
1537 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
1538 else
1539 Error("FixDoors: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
1540 }
1541 if (IsDoorLinked(i))
1542 UtilizeDoor(i,LockLinkedDoor);
1543 }
1544 }
1545
1546
1547 //===========================================================================
1548
1549 /*
1550 =====================
1551 =
1552 = OpenDoor
1553 =
1554 =====================
1555 */
1556
OpenDoor(int door)1557 void OpenDoor (int door)
1558 {
1559 if (doorobjlist[door]->action == dr_open)
1560 doorobjlist[door]->ticcount = 0; // reset open time
1561 else
1562 {
1563 doorobjlist[door]->action = dr_opening; // start it opening
1564 }
1565 }
1566
1567 /*
1568 =====================
1569 =
1570 = DoorUnBlocked
1571 =
1572 =====================
1573 */
1574
DoorUnBlocked(int door)1575 boolean DoorUnBlocked (int door)
1576 {
1577 int tilex,tiley;
1578 objtype *check;
1579 doorobj_t*dptr;
1580
1581 dptr = doorobjlist[door];
1582
1583 //
1584 // don't close on anything solid
1585 //
1586
1587 tilex = dptr->tilex;
1588 tiley = dptr->tiley;
1589 check = (objtype*)actorat[tilex][tiley];
1590
1591 if (check && (check->which == ACTOR))
1592 return false;
1593
1594 if (dptr->vertical==true)
1595 {
1596 check = (objtype*)actorat[tilex-1][tiley];
1597 if (check && (check->which==ACTOR) && ((check->x+MINDIST) >> TILESHIFT) == tilex )
1598 return false;
1599 check = (objtype*)actorat[tilex+1][tiley];
1600 if (check && (check->which==ACTOR) && ((check->x-MINDIST) >> TILESHIFT) == tilex )
1601 return false;
1602 }
1603 else if (dptr->vertical==false)
1604 {
1605 check = (objtype*)actorat[tilex][tiley-1];
1606 if (check && (check->which==ACTOR) && ((check->y+MINDIST) >> TILESHIFT) == tiley )
1607 return false;
1608 check = (objtype*)actorat[tilex][tiley+1];
1609 if (check && (check->which==ACTOR) && ((check->y-MINDIST) >> TILESHIFT) == tiley )
1610 return false;
1611 }
1612 return true;
1613 }
1614
1615
1616 /*
1617 =====================
1618 =
1619 = DoorReadyToClose
1620 =
1621 = Alter the door's state
1622 =
1623 =====================
1624 */
1625
DoorReadyToClose(int door)1626 boolean DoorReadyToClose(int door)
1627 {
1628 doorobj_t*dptr;
1629 int dx,dy;
1630 doorobj_t * dr2;
1631 int tx,ty;
1632
1633
1634 dptr = doorobjlist[door];
1635
1636 if (dptr->action==dr_closed)
1637 return true;
1638
1639 if (DoorUnBlocked(door)==false)
1640 return false;
1641
1642 dx=0;dy=0;
1643 if (dptr->vertical==true)
1644 dy=1;
1645 else
1646 dx=1;
1647 tx=dptr->tilex+dx;
1648 ty=dptr->tiley+dy;
1649 while (M_ISDOOR(tx,ty))
1650 {
1651 int num;
1652
1653 num=tilemap[tx][ty]&0x3ff;
1654 dr2=doorobjlist[num];
1655 if (!(dr2->flags&DF_MULTI))
1656 break;
1657 if (DoorUnBlocked(num)==false)
1658 return false;
1659 tx+=dx;
1660 ty+=dy;
1661 }
1662 tx=dptr->tilex-dx;
1663 ty=dptr->tiley-dy;
1664 while (M_ISDOOR(tx,ty))
1665 {
1666 int num;
1667
1668 num=tilemap[tx][ty]&0x3ff;
1669 dr2=doorobjlist[num];
1670 if (!(dr2->flags&DF_MULTI))
1671 break;
1672 if (DoorUnBlocked(num)==false)
1673 return false;
1674 tx-=dx;
1675 ty-=dy;
1676 }
1677 return true;
1678 }
1679
1680
1681 /*
1682 =====================
1683 =
1684 = CloseDoor
1685 =
1686 =====================
1687 */
1688
CloseDoor(int door)1689 void CloseDoor (int door)
1690 {
1691 int tilex,tiley,area;
1692 doorobj_t*dptr;
1693
1694 dptr = doorobjlist[door];
1695 if (dptr->action == dr_closed)
1696 return;
1697 tilex = dptr->tilex;
1698 tiley = dptr->tiley;
1699
1700 //
1701 // play door sound
1702 //
1703 area = MAPSPOT(tilex,tiley,0)-AREATILE;
1704 if (areabyplayer[area])
1705 {
1706 dptr->soundhandle=SD_PlaySoundRTP ( SD_CLOSEDOORSND, dptr->tilex<<16, dptr->tiley<<16 );
1707 }
1708
1709 dptr->action = dr_closing;
1710 //
1711 // make the door space solid
1712 //
1713 actorat[tilex][tiley] = dptr;
1714 }
1715
1716
1717
1718 /*
1719 =====================
1720 =
1721 = OperateDoor
1722 =
1723 = The player wants to change the door's direction
1724 =
1725 =====================
1726 */
1727
OperateDoor(int keys,int door,boolean localplayer)1728 void OperateDoor (int keys, int door, boolean localplayer )
1729 {
1730 int lock;
1731 doorobj_t*dptr;
1732
1733 dptr = doorobjlist[door];
1734 if ( ( dptr->flags & DF_ELEVLOCKED ) ||
1735 ( MISCVARS->GASON && ( MAPSPOT( dptr->tilex,
1736 dptr->tiley, 1 ) == GASVALUE ) ) )
1737 {
1738 if ( localplayer )
1739 {
1740 // locked
1741 SD_Play ( SD_NOITEMSND );
1742 }
1743 return;
1744 }
1745
1746 lock = dptr->lock;
1747 if ( lock && !( keys & ( 1 << ( lock - 1 ) ) ) )
1748 {
1749 if ( localplayer )
1750 {
1751 // locked
1752 switch (lock)
1753 {
1754 case 1:
1755 AddMessage("You need the \\EGOLD key",MSG_DOOR);
1756 break;
1757
1758 case 2:
1759 AddMessage("You need the \\FSILVER key",MSG_DOOR);
1760 break;
1761
1762 case 3:
1763 AddMessage("You need the \\8IRON key",MSG_DOOR);
1764 break;
1765
1766 case 4:
1767 AddMessage("You need the \\AOSCURO key",MSG_DOOR);
1768 break;
1769
1770 default:
1771 AddMessage("This door appears to be locked",MSG_DOOR);
1772 break;
1773 }
1774
1775 SD_Play( SD_NOITEMSND );
1776 }
1777 return;
1778 }
1779 UseDoor(door);
1780 }
1781
1782 /*
1783 =====================
1784 =
1785 = LinkedOpenDoor
1786 =
1787 =====================
1788 */
1789
LinkedOpenDoor(int door)1790 void LinkedOpenDoor (int door)
1791 {
1792 UtilizeDoor(door,OpenDoor);
1793 }
1794
1795 /*
1796 =====================
1797 =
1798 = LinkedCloseDoor
1799 =
1800 =====================
1801 */
1802
LinkedCloseDoor(int door)1803 void LinkedCloseDoor (int door)
1804 {
1805 if (DoorReadyToClose(door)==true)
1806 UtilizeDoor(door,CloseDoor);
1807 }
1808
1809 /*
1810 =====================
1811 =
1812 = UtilizeDoor
1813 =
1814 = Alter the door's state
1815 =
1816 =====================
1817 */
1818
UtilizeDoor(int door,void (* action)(int))1819 void UtilizeDoor (int door,void (*action)(int))
1820 {
1821 doorobj_t*dptr;
1822 int dx,dy;
1823 doorobj_t * dr2;
1824 int tx,ty;
1825
1826 dptr = doorobjlist[door];
1827
1828 action(door);
1829
1830 dx=0;dy=0;
1831 if (dptr->vertical==true)
1832 dy=1;
1833 else
1834 dx=1;
1835 tx=dptr->tilex+dx;
1836 ty=dptr->tiley+dy;
1837 while (M_ISDOOR(tx,ty))
1838 {
1839 int num;
1840
1841 num=tilemap[tx][ty]&0x3ff;
1842 dr2=doorobjlist[num];
1843 if (!(dr2->flags&DF_MULTI))
1844 break;
1845 action(num);
1846 tx+=dx;
1847 ty+=dy;
1848 }
1849 tx=dptr->tilex-dx;
1850 ty=dptr->tiley-dy;
1851 while (M_ISDOOR(tx,ty))
1852 {
1853 int num;
1854
1855 num=tilemap[tx][ty]&0x3ff;
1856 dr2=doorobjlist[num];
1857 if (!(dr2->flags&DF_MULTI))
1858 break;
1859 action(num);
1860 tx-=dx;
1861 ty-=dy;
1862 }
1863 }
1864
1865 /*
1866 =====================
1867 =
1868 = UseDoor
1869 =
1870 = Alter the door's state
1871 =
1872 =====================
1873 */
1874
UseDoor(int door)1875 void UseDoor (int door)
1876 {
1877 switch (doorobjlist[door]->action)
1878 {
1879 case dr_closing:
1880 SD_StopSound(doorobjlist[door]->soundhandle);
1881 case dr_closed:
1882 UtilizeDoor(door,OpenDoor);
1883 break;
1884 case dr_opening:
1885 SD_StopSound(doorobjlist[door]->soundhandle);
1886 case dr_open:
1887 if (DoorReadyToClose(door)==true)
1888 UtilizeDoor(door,CloseDoor);
1889 break;
1890 }
1891 }
1892
1893 //===========================================================================
1894
1895 /*
1896 ===============
1897 =
1898 = DoorOpen
1899 =
1900 = Close the door after three seconds
1901 =
1902 ===============
1903 */
1904
DoorOpen(int door)1905 void DoorOpen (int door)
1906 {doorobj_t* dptr;
1907
1908 dptr = doorobjlist[door];
1909 dptr->ticcount += 1;
1910 if ((dptr->ticcount >= OPENTICS) &&
1911 (!(dptr->flags & DF_TIMED)) &&
1912 (DoorReadyToClose(door)==true))
1913 UtilizeDoor(door,CloseDoor);
1914 }
1915
1916
1917
1918 /*
1919 ===============
1920 =
1921 = DoorOpening
1922 =
1923 ===============
1924 */
1925
DoorOpening(int door)1926 void DoorOpening (int door)
1927 {
1928 int area1,area2;
1929 word *map;
1930 long position;
1931 int tilex,tiley;
1932
1933 position = doorobjlist[door]->position;
1934 tilex = doorobjlist[door]->tilex;
1935 tiley = doorobjlist[door]->tiley;
1936 if (!position)
1937 {
1938 //
1939 // door is just starting to open, so connect the areas
1940 //
1941 map = &MAPSPOT(tilex,tiley,0);
1942
1943 if (doorobjlist[door]->vertical==true)
1944 {
1945 area1 = *(map+1);
1946 area2 = *(map-1);
1947 }
1948 else
1949 {
1950 area1 = *(map-mapwidth);
1951 area2 = *(map+mapwidth);
1952 }
1953 area1 -= AREATILE;
1954 area2 -= AREATILE;
1955 areaconnect[area1][area2]++;
1956 areaconnect[area2][area1]++;
1957 if ((insetupgame==false) && (loadedgame==false))
1958 ConnectAreas ();
1959 if (areabyplayer[area1])
1960 {
1961 doorobjlist[door]->soundhandle=SD_PlaySoundRTP ( SD_OPENDOORSND, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
1962 }
1963 }
1964
1965 //
1966 // slide the door by an adaptive amount
1967 //
1968 position += 1<<12;
1969 if (position >= 0xffff)
1970 {
1971 //
1972 // door is all the way open
1973 //
1974 position = 0xffff;
1975 doorobjlist[door]->ticcount = 0;
1976 doorobjlist[door]->action = dr_open;
1977 if (doorobjlist[door] == actorat[tilex][tiley])
1978 actorat[tilex][tiley] = 0;
1979 }
1980
1981 doorobjlist[door]->position = position;
1982 doorobjlist[door]->texture=doorobjlist[door]->basetexture+((position+1)>>13);
1983 }
1984
1985
1986 /*
1987 ===============
1988 =
1989 = DoorClosing
1990 =
1991 ===============
1992 */
1993
DoorClosing(int door)1994 void DoorClosing (int door)
1995 {
1996 int area1,area2;
1997 word *map;
1998 long position;
1999 int tilex,tiley;
2000 doorobj_t *dptr;
2001
2002 dptr = doorobjlist[door];
2003
2004 tilex = dptr->tilex;
2005 tiley = dptr->tiley;
2006
2007 position = dptr->position;
2008
2009 //
2010 // slide the door by an adaptive amount
2011 //
2012 position -= 1<<12;
2013 if (position < (0xffff >> 1))
2014 ResolveDoorSpace(tilex,tiley);
2015
2016
2017 if (position <= 0)
2018 {
2019 //
2020 // door is closed all the way, so disconnect the areas
2021 //
2022 position = 0;
2023
2024 dptr->action = dr_closed;
2025
2026
2027
2028 map = &MAPSPOT(tilex,tiley,0);
2029
2030 if (areabyplayer[(*map-AREATILE)])
2031 {
2032 dptr->soundhandle=SD_PlaySoundRTP ( SD_DOORHITSND, dptr->tilex<<16, dptr->tiley<<16 );
2033 }
2034
2035 if (dptr->vertical==true)
2036 {
2037 area1 = *(map+1);
2038 area2 = *(map-1);
2039 }
2040 else
2041 {
2042 area1 = *(map-mapwidth);
2043 area2 = *(map+mapwidth);
2044 }
2045 area1 -= AREATILE;
2046 area2 -= AREATILE;
2047 areaconnect[area1][area2]--;
2048 areaconnect[area2][area1]--;
2049
2050 ConnectAreas ();
2051 }
2052
2053 dptr->position = position;
2054 dptr->texture=dptr->basetexture+((position+1)>>13);
2055 }
2056
2057 /*
2058 ===============
2059 =
2060 = IsMaskedWall
2061 =
2062 ===============
2063 */
2064
IsMaskedWall(int tilex,int tiley)2065 int IsMaskedWall (int tilex, int tiley)
2066 {
2067 int map;
2068
2069 if (IsPlatform(tilex,tiley))
2070 return 1;
2071
2072 map=MAPSPOT(tilex,tiley,0);
2073
2074 if ((map>=157) && (map<=160))
2075 return 1;
2076
2077 if ((map>=162) && (map<=179))
2078 return 1;
2079
2080 if (M_ISMWALL(tilex,tiley))
2081 return 1;
2082
2083 return 0;
2084 }
2085
2086 /*
2087 ===============
2088 =
2089 = SpawnMaskedWall
2090 =
2091 ===============
2092 */
2093
2094
SpawnMaskedWall(int tilex,int tiley,int which,int flags)2095 void SpawnMaskedWall (int tilex, int tiley, int which, int flags)
2096 {word *map;
2097 int area1, area2;
2098 int up,dn,lt,rt;
2099 int himask;
2100 boolean sidepic;
2101 int side, middle, above, bottom;
2102 maskedwallobj_t * lastmaskobj;
2103 boolean metal;
2104 int maskedstart;
2105 int abovemaskedwallstart;
2106 int swallstart;
2107
2108 himask=W_GetNumForName("HMSKSTRT")+1;
2109 maskedstart=W_GetNumForName("MASKSTRT");
2110 abovemaskedwallstart=W_GetNumForName("ABVMSTRT");
2111 swallstart=W_GetNumForName("SIDESTRT");
2112
2113 maskobjlist[maskednum]=(maskedwallobj_t*)Z_LevelMalloc(sizeof(maskedwallobj_t),PU_LEVELSTRUCT,NULL);
2114 memset(maskobjlist[maskednum],0,sizeof(maskedwallobj_t));
2115 lastmaskobj=maskobjlist[maskednum];
2116
2117 sidepic=true;
2118
2119 lastmaskobj->tilex = tilex;
2120 lastmaskobj->tiley = tiley;
2121 lastmaskobj->which = MWALL;
2122 up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
2123 dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
2124 lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
2125 rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
2126
2127 if (IsMaskedWall(tilex,tiley-1)) up=2;
2128 else if (IsWall(tilex,tiley-1)) up=1;
2129 else up=0;
2130
2131 if (IsMaskedWall(tilex,tiley+1)) dn=2;
2132 else if (IsWall(tilex,tiley+1)) dn=1;
2133 else dn=0;
2134
2135 if (IsMaskedWall(tilex-1,tiley)) lt=2;
2136 else if (IsWall(tilex-1,tiley)) lt=1;
2137 else lt=0;
2138
2139 if (IsMaskedWall(tilex+1,tiley)) rt=2;
2140 else if (IsWall(tilex+1,tiley)) rt=1;
2141 else rt=0;
2142
2143 if ((up==1) && (dn==1))
2144 lastmaskobj->vertical = true;
2145 else if ((lt==1) && (rt==1))
2146 lastmaskobj->vertical = false;
2147 else if ((up>0) && (dn>0))
2148 lastmaskobj->vertical = true;
2149 else if ((lt>0) && (rt>0))
2150 lastmaskobj->vertical = false;
2151 else if (up>0)
2152 lastmaskobj->vertical = true;
2153 else if (dn>0)
2154 lastmaskobj->vertical = true;
2155 else if (lt>0)
2156 lastmaskobj->vertical = false;
2157 else if (rt>0)
2158 lastmaskobj->vertical = false;
2159
2160 tilemap[tilex][tiley] = maskednum | 0xc000;
2161 map = &MAPSPOT(tilex,tiley,0);
2162
2163 if (lastmaskobj->vertical==true)
2164 {
2165 area1 = *(map+1);
2166 area2 = *(map-1);
2167 area1 -= AREATILE;
2168 area2 -= AREATILE;
2169 if (lt==0 && rt==0)
2170 {
2171 areaconnect[area1][area2]++;
2172 areaconnect[area2][area1]++;
2173 }
2174 }
2175 else
2176 {
2177 area1 = *(map-mapwidth);
2178 area2 = *(map+mapwidth);
2179 area1 -= AREATILE;
2180 area2 -= AREATILE;
2181 if (up==0 && dn==0)
2182 {
2183 areaconnect[area1][area2]++;
2184 areaconnect[area2][area1]++;
2185 }
2186 }
2187 lastmaskobj->flags=flags;
2188
2189 if (IsPlatform(tilex,tiley))
2190 {
2191 if (MAPSPOT(tilex,tiley,0)==21)
2192 {
2193 metal=true;
2194 actorat[tilex][tiley]=0;
2195 }
2196 else
2197 metal=false;
2198 }
2199
2200
2201
2202 switch (which)
2203 {
2204 case mw_peephole:
2205
2206 //#if (SHAREWARE == 1)
2207 side = W_GetNumForName("SIDE21");
2208 middle = W_GetNumForName("ABOVEM4A") ;
2209 above = W_GetNumForName("ABOVEM4") ;
2210 /*
2211 #else
2212 side = W_GetNumForName("SIDE16");
2213 middle = W_GetNumForName("ABOVEM3A") ;
2214 above = W_GetNumForName("ABOVEM2A") ;
2215
2216 #endif
2217 */
2218 bottom = W_GetNumForName("PEEPMASK");
2219 break;
2220
2221
2222 case mw_dogwall:
2223
2224 side = W_GetNumForName("SIDE21");
2225 above = W_GetNumForName("ABOVEM4") ;
2226
2227 if (isSHAREWARE) {
2228 middle = W_GetNumForName("ABOVEM4A") ;
2229 } else {
2230 middle = W_GetNumForName("ABOVEM9") ;
2231 }
2232
2233 bottom = W_GetNumForName("DOGMASK");
2234 break;
2235
2236 case mw_multi1:
2237
2238 /*
2239 #if (SHAREWARE == 1)
2240 side = W_GetNumForName("SIDE21");
2241 middle = W_GetNumForName("ABOVEM4A") ;
2242 above = W_GetNumForName("ABOVEM4") ;
2243
2244 #else
2245 */
2246 //side = W_GetNumForName("SIDE23") ;
2247 side = W_GetNumForName("SIDE21") ;
2248 middle = W_GetNumForName("ABOVEM5A") ;
2249 above = W_GetNumForName("ABOVEM5") ;
2250
2251 // #endif
2252
2253 bottom = W_GetNumForName("MULTI1");
2254 break;
2255
2256 case mw_multi2:
2257 /*
2258 #if (SHAREWARE == 1)
2259 side = W_GetNumForName("SIDE21");
2260 middle = W_GetNumForName("ABOVEM4A");
2261 above = W_GetNumForName("ABOVEM4") ;
2262
2263 #else
2264 */
2265 //side = W_GetNumForName("SIDE23") ;
2266 side = W_GetNumForName("SIDE21") ;
2267 middle = W_GetNumForName("ABOVEM5B");
2268 above = W_GetNumForName("ABOVEM5") ;
2269
2270
2271 //#endif
2272
2273 bottom = W_GetNumForName("MULTI2");
2274 break;
2275
2276 case mw_multi3:
2277
2278 /*
2279 #if (SHAREWARE == 1)
2280 side = W_GetNumForName("SIDE21");
2281 middle = W_GetNumForName("ABOVEM4A") ;
2282 above = W_GetNumForName("ABOVEM4") ;
2283
2284 #else
2285 */
2286 //side = W_GetNumForName("SIDE23") ;
2287 side = W_GetNumForName("SIDE21") ;
2288 middle = W_GetNumForName("ABOVEM5C") ;
2289 above = W_GetNumForName("ABOVEM5") ;
2290
2291
2292 //#endif
2293
2294 bottom = W_GetNumForName("MULTI3");
2295 break;
2296
2297 case mw_singlepane:
2298
2299 // #if (SHAREWARE == 1)
2300 side = W_GetNumForName("SIDE21");
2301
2302 // #else
2303 // side = W_GetNumForName("SIDE22") ;
2304 // #endif
2305
2306 middle = W_GetNumForName("ABOVEM4A") ;
2307 above = W_GetNumForName("ABOVEM4") ;
2308 bottom = W_GetNumForName("MASKED4");
2309 break;
2310
2311 case mw_normal1:
2312 side = W_GetNumForName("SIDE21");
2313
2314
2315 // #if (SHAREWARE == 1)
2316 middle = W_GetNumForName("ABOVEM4A") ;
2317 above = W_GetNumForName("ABOVEM4") ;
2318
2319 //#else
2320 // middle = W_GetNumForName("ABOVEM1A") ;
2321 // above = W_GetNumForName("ABOVEM1") ;
2322
2323
2324 //#endif
2325
2326 bottom = W_GetNumForName("MASKED1");
2327 break;
2328
2329 case mw_normal2:
2330 side = W_GetNumForName("SIDE21");
2331
2332 //#if (SHAREWARE == 1)
2333 middle = W_GetNumForName("ABOVEM4A") ;
2334 above = W_GetNumForName("ABOVEM4") ;
2335
2336 //#else
2337 // middle = W_GetNumForName("ABOVEM2A") ;
2338 // above = W_GetNumForName("ABOVEM2") ;
2339
2340 //#endif
2341
2342 bottom = W_GetNumForName("MASKED2");
2343 break;
2344
2345 case mw_normal3:
2346 side = W_GetNumForName("SIDE21");
2347
2348 //#if (SHAREWARE == 1)
2349 middle = W_GetNumForName("ABOVEM4A") ;
2350 above = W_GetNumForName("ABOVEM4") ;
2351
2352 //#else
2353 // middle = W_GetNumForName("ABOVEM3A") ;
2354 // above = W_GetNumForName("ABOVEM3") ;
2355
2356 //#endif
2357
2358 bottom = W_GetNumForName("MASKED3");
2359 break;
2360
2361 case mw_exitarch:
2362
2363 side = W_GetNumForName("SIDE21");
2364
2365 //#if (SHAREWARE == 1)
2366 middle = W_GetNumForName("ABOVEM4A") ;
2367 above = W_GetNumForName("ABOVEM4") ;
2368
2369 //#else
2370 // middle = W_GetNumForName("ABOVEM6A") ;
2371 // above = W_GetNumForName("ABOVEM6") ;
2372
2373 //#endif
2374
2375 bottom = W_GetNumForName("EXITARCH");
2376 break;
2377
2378 case mw_secretexitarch:
2379
2380 side = W_GetNumForName("SIDE21");
2381
2382 //#if (SHAREWARE == 1)
2383 middle = W_GetNumForName("ABOVEM4A") ;
2384 above = W_GetNumForName("ABOVEM4") ;
2385
2386 //#else
2387 // middle = W_GetNumForName("ABOVEM8A") ;
2388 // above = W_GetNumForName("ABOVEM8") ;
2389
2390 //#endif
2391
2392 bottom = W_GetNumForName("EXITARCA");
2393 break;
2394
2395 case mw_railing:
2396 sidepic = false;
2397 middle = -1;
2398 above = -1;
2399 bottom = W_GetNumForName("RAILING");
2400 break;
2401
2402 case mw_hiswitchon:
2403 sidepic = false;
2404 middle = himask+1;
2405 above = himask+3;
2406 bottom = himask;
2407 break;
2408
2409 case mw_hiswitchoff:
2410 sidepic = false;
2411 middle = himask+1;
2412 above = himask+2;
2413 bottom = himask;
2414 break;
2415
2416 case mw_entrygate:
2417 side = W_GetNumForName("SIDE21");
2418
2419 //#if (SHAREWARE == 1)
2420 //side = W_GetNumForName("SIDE21");
2421 middle = W_GetNumForName("ABOVEM4A") ;
2422 above = W_GetNumForName("ABOVEM4") ;
2423
2424 //#else
2425 //side = W_GetNumForName("SIDE20") ;
2426 // middle = W_GetNumForName("ABOVEM7A") ;
2427 // above = W_GetNumForName("ABOVEM7") ;
2428
2429
2430 //#endif
2431
2432 bottom = W_GetNumForName("ENTRARCH");
2433 break;
2434
2435 case mw_platform1:
2436 sidepic = false;
2437 bottom = -1;
2438 middle = -1;
2439 above = himask+10;
2440 if (metal==true)
2441 {
2442 bottom = -1;
2443 middle = -1;
2444 above = himask+15;
2445 }
2446 break;
2447 case mw_platform2:
2448 sidepic = false;
2449 bottom = himask+8;
2450 middle = -1;
2451 above = -1;
2452 if (metal==true)
2453 {
2454 bottom = himask+14;
2455 middle = -1;
2456 above = -1;
2457 }
2458 else
2459 lastmaskobj->flags|=MW_BOTTOMFLIPPING;
2460 break;
2461 case mw_platform3:
2462 sidepic = false;
2463 bottom = himask+8;
2464 middle = -1;
2465 above = himask+10;
2466 if (metal==true)
2467 {
2468 bottom = himask+14;
2469 middle = -1;
2470 above = himask+15;
2471 }
2472 else
2473 lastmaskobj->flags|=MW_BOTTOMFLIPPING;
2474 break;
2475 case mw_platform4:
2476 sidepic = false;
2477 bottom = himask+12;
2478 middle = himask+7;
2479 above = himask+7;
2480 if (metal==true)
2481 {
2482 bottom = -1;
2483 middle = himask+15;
2484 above = himask+15;
2485 }
2486 break;
2487 case mw_platform5:
2488 sidepic = false;
2489 bottom = himask+12;
2490 middle = himask+7;
2491 above = himask+5;
2492 if (metal==true)
2493 {
2494 bottom = -1;
2495 middle = himask+15;
2496 above = -1;
2497 }
2498 else
2499 lastmaskobj->flags|=MW_TOPFLIPPING;
2500 break;
2501 case mw_platform6:
2502 sidepic = false;
2503 bottom = himask+4;
2504 middle = himask+7;
2505 above = himask+5;
2506 if (metal==true)
2507 {
2508 bottom = himask+14;
2509 middle = himask+15;
2510 above = -1;
2511 }
2512 else
2513 lastmaskobj->flags|=MW_TOPFLIPPING;
2514 break;
2515 case mw_platform7:
2516 sidepic = false;
2517 bottom = himask+4;
2518 middle = himask+7;
2519 above = himask+5;
2520 if ((up==1) || (dn==1))
2521 lastmaskobj->vertical=true;
2522 else if ((lt==1) || (rt==1))
2523 lastmaskobj->vertical=false;
2524 else
2525 Error("Perpendicular platform used with no wall near it\n");
2526 if (metal==true)
2527 {
2528 bottom = himask+14;
2529 middle = himask+15;
2530 above = -1;
2531 }
2532 else
2533 lastmaskobj->flags|=MW_TOPFLIPPING;
2534 break;
2535 }
2536
2537 switch (which)
2538 {
2539 case mw_multi1:
2540 case mw_multi2:
2541 case mw_multi3:
2542 case mw_singlepane:
2543 case mw_normal1:
2544 case mw_normal2:
2545 case mw_normal3:
2546 if (!(flags & MW_SHOOTABLE))
2547 bottom+=9;
2548 break;
2549 }
2550 lastmaskobj->midtexture=middle;
2551 lastmaskobj->toptexture=above;
2552 lastmaskobj->bottomtexture=bottom;
2553
2554 if (sidepic == true)
2555 {
2556 lastmaskobj->sidepic=side;
2557 if (lastmaskobj->vertical==true)
2558 {
2559 if (up==1)
2560 tilemap[tilex][tiley-1] |= 0x4000;
2561 if (dn==1)
2562 tilemap[tilex][tiley+1] |= 0x4000;
2563 }
2564 else
2565 {
2566 if (lt==1)
2567 tilemap[tilex-1][tiley] |= 0x4000;
2568 if (rt==1)
2569 tilemap[tilex+1][tiley] |= 0x4000;
2570 }
2571 }
2572
2573 // Cache in the broken version
2574
2575 if (lastmaskobj->flags & MW_SHOOTABLE)
2576 {
2577 int i;
2578
2579 for (i=1;i<AMW_NUMFRAMES;i++)
2580 {
2581 PreCacheLump(lastmaskobj->bottomtexture+i,PU_CACHEWALLS);
2582 }
2583 SD_PreCacheSound(SD_GLASSBREAKSND);
2584 }
2585 if (sidepic==true)
2586 {
2587 PreCacheLump(lastmaskobj->sidepic,PU_CACHEWALLS);
2588 }
2589 if (lastmaskobj->bottomtexture>=0)
2590 PreCacheLump(lastmaskobj->bottomtexture,PU_CACHEWALLS);
2591 if (lastmaskobj->toptexture>=0)
2592 PreCacheLump(lastmaskobj->toptexture,PU_CACHEWALLS);
2593 if (lastmaskobj->midtexture>=0)
2594 PreCacheLump(lastmaskobj->midtexture,PU_CACHEWALLS);
2595 maskednum++;
2596 lastmaskobj++;
2597 if (maskednum==MAXMASKED)
2598 Error ("Too many masked walls\n");
2599 }
2600
2601 /*
2602 ===============
2603 =
2604 = FixMaskedWallAreaNumbers
2605 =
2606 ===============
2607 */
FixMaskedWallAreaNumbers(void)2608 void FixMaskedWallAreaNumbers ( void )
2609 {
2610 int i;
2611 int up,dn,lt,rt;
2612 int tilex,tiley;
2613
2614 for (i=0;i<maskednum;i++)
2615 {
2616 int tile;
2617 tilex=maskobjlist[i]->tilex;
2618 tiley=maskobjlist[i]->tiley;
2619 tile=MAPSPOT(tilex,tiley,0)-AREATILE;
2620 if ((tile<=NUMAREAS) && (tile>0))
2621 {
2622 maskobjlist[i]->areanumber = tile;
2623 continue;
2624 }
2625 up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
2626 dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
2627 lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
2628 rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
2629
2630
2631
2632 up = ((up>0) && (up<=NUMAREAS));
2633 dn = ((dn>0) && (dn<=NUMAREAS));
2634 lt = ((lt>0) && (lt<=NUMAREAS));
2635 rt = ((rt>0) && (rt<=NUMAREAS));
2636
2637 if (maskobjlist[i]->vertical==true)
2638 {
2639 if (rt)
2640 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
2641 else if (lt)
2642 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
2643 else if (up)
2644 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
2645 else if (dn)
2646 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
2647 else
2648 Error("FixMaskedWalls: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
2649 }
2650 else
2651 {
2652 if (dn)
2653 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
2654 else if (up)
2655 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
2656 else if (rt)
2657 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
2658 else if (lt)
2659 MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
2660 else
2661 Error("FixMaskedWalls: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
2662 }
2663 maskobjlist[i]->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
2664 if ((maskobjlist[i]->areanumber <0) || (maskobjlist[i]->areanumber > NUMAREAS))
2665 Error("Bad masked wall areanumber of %d",maskobjlist[i]->areanumber);
2666 }
2667 }
2668
2669
2670 /*
2671 ===============
2672 =
2673 = CheckMaskedWall
2674 =
2675 ===============
2676 */
2677
CheckMaskedWall(maskedwallobj_t * mw)2678 int CheckMaskedWall( maskedwallobj_t * mw )
2679 {
2680 int result;
2681
2682 result=0;
2683 if (mw->flags & MW_SHOOTABLE)
2684 {
2685 if (mw->flags & MW_BLOCKINGCHANGES)
2686 {
2687 mw->flags&=~MW_BLOCKINGCHANGES;
2688 mw->flags&=~MW_BLOCKING;
2689 mw->flags|=MW_BOTTOMPASSABLE;
2690 }
2691 mw->flags&=~MW_SHOOTABLE;
2692 // mw->bottomtexture++;
2693 result=1;
2694 }
2695 return result;
2696 }
2697
2698
2699 /*
2700 ===============
2701 =
2702 = UpdateMaskedWall
2703 =
2704 ===============
2705 */
2706
UpdateMaskedWall(int num)2707 int UpdateMaskedWall (int num)
2708 {
2709 maskedwallobj_t * mw;
2710 int result;
2711
2712
2713 mw=maskobjlist[num];
2714 result=CheckMaskedWall(mw);
2715 if (result==1)
2716 {
2717 SpawnAnimatedMaskedWall(num);
2718 if (loadedgame==false)
2719 SD_PlaySoundRTP(SD_GLASSBREAKSND,mw->tilex<<16,mw->tiley<<16);
2720 if (mw->flags&MW_MULTI)
2721 {
2722 int i;
2723 int dx,dy;
2724 int r;
2725 maskedwallobj_t * mw2;
2726
2727 dx=0;dy=0;
2728 if (mw->vertical==true)
2729 dy=1;
2730 else
2731 dx=1;
2732 i=1;
2733 while (M_ISMWALL(mw->tilex+(dx*i),mw->tiley+(dy*i)))
2734 {
2735 int num;
2736
2737 num=tilemap[mw->tilex+(dx*i)][mw->tiley+(dy*i)]&0x3ff;
2738 mw2=maskobjlist[num];
2739 if (!(mw2->flags&MW_MULTI))
2740 break;
2741 r=CheckMaskedWall(mw2);
2742 if (r==1)
2743 {
2744 SpawnAnimatedMaskedWall(num);
2745 if (loadedgame==false)
2746 SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
2747 }
2748 i++;
2749 }
2750 i=1;
2751 while (M_ISMWALL(mw->tilex-(dx*i),mw->tiley-(dy*i)))
2752 {
2753 int num;
2754
2755 num=tilemap[mw->tilex-(dx*i)][mw->tiley-(dy*i)]&0x3ff;
2756 mw2=maskobjlist[num];
2757 if (!(mw2->flags&MW_MULTI))
2758 break;
2759 r=CheckMaskedWall(mw2);
2760 if (r==1)
2761 {
2762 SpawnAnimatedMaskedWall(num);
2763 if (loadedgame==false)
2764 SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
2765 }
2766 i++;
2767 }
2768 }
2769 }
2770 return result;
2771 }
2772
2773
2774
2775 /*
2776 ============================
2777 =
2778 = ExecuteElevatorStopActions
2779 =
2780 ============================
2781 */
2782
2783
ExecuteElevatorStopActions(elevator_t * eptr,int teleport_location,int desttilex,int desttiley)2784 void ExecuteElevatorStopActions(elevator_t *eptr, int teleport_location,
2785 int desttilex,int desttiley)
2786 {
2787 eptr->state = ev_doorclosing;
2788 eptr->doorclosing = eptr->doortoopen;
2789 doorobjlist[eptr->doortoopen]->flags &= ~DF_ELEVLOCKED;
2790 OpenDoor(eptr->doortoopen);
2791 SD_PlaySoundRTP(SD_ELEVATORENDSND,desttilex,desttiley);
2792 Teleport(eptr,teleport_location);
2793 eptr->ticcount = OPENTICS;
2794 eptr->doortoopen = -1;
2795 if (MISCVARS->elevatormusicon == true)
2796 {
2797 MU_StartSong(song_level);
2798 MU_RestoreSongPosition();
2799 MISCVARS->elevatormusicon = false;
2800
2801 }
2802 }
2803
2804
PlayerInElevator(elevator_t * eptr)2805 boolean PlayerInElevator(elevator_t *eptr)
2806 {
2807 if (eptr->state == ev_mts)
2808 {
2809 if ((eptr->dx == player->tilex) && (eptr->dy == player->tiley))
2810 return true;
2811 }
2812 else if (eptr->state == ev_mtd)
2813 {
2814 if ((eptr->sx == player->tilex) && (eptr->sy == player->tiley))
2815 return true;
2816 }
2817
2818 return false;
2819
2820 }
2821
2822 #define SHOULD_START_ELEVATOR_MUSIC(eptr) \
2823 ((demoplayback == false) && (demorecord == false) && \
2824 (MusicStarted() == true) && \
2825 (!BATTLEMODE) && \
2826 (!(player->flags & FL_GODMODE)) &&\
2827 (GameRandomNumber("elevator music",0) < 25) && \
2828 (PlayerInElevator(eptr)) \
2829 ) \
2830
2831
2832 /*
2833 ==========================
2834 =
2835 = SetElevatorOperationTime
2836 =
2837 ==========================
2838 */
2839
2840
SetElevatorOperationTime(elevator_t * eptr)2841 void SetElevatorOperationTime(elevator_t*eptr)
2842 {
2843 if (SHOULD_START_ELEVATOR_MUSIC(eptr))
2844 {
2845 MU_StoreSongPosition();
2846 MU_StartSong(song_elevator);
2847 MISCVARS->elevatormusicon = true;
2848 eptr->ticcount = ELEVATORMUSICTIME;
2849 }
2850
2851 else if (AREANUMBER(eptr->sx,eptr->sy) == AREANUMBER(eptr->dx,eptr->dy))
2852 eptr->ticcount = 70;
2853 else
2854 eptr->ticcount = 170;
2855
2856 }
2857
2858
2859 /*
2860 =====================
2861 =
2862 = CheckElevatorStart
2863 =
2864 =====================
2865 */
2866
CheckElevatorStart(elevator_t * eptr)2867 void CheckElevatorStart (elevator_t*eptr)
2868 {
2869 doorobj_t *dptr = doorobjlist[eptr->doorclosing];
2870
2871 if (dptr->action == dr_closed)
2872 {
2873
2874 if (eptr->nextaction!=-1)
2875 {
2876 eptr->state = eptr->nextaction;
2877 eptr->nextaction = -1;
2878 switch (eptr->state)
2879 {
2880 case ev_mtd:
2881 eptr->doortoopen = eptr->door2;
2882 SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->sx<<16,eptr->sy<<16);
2883 //eptr->doorclosing = eptr->door1;
2884
2885 SetElevatorOperationTime(eptr);
2886 break;
2887
2888 case ev_mts:
2889 eptr->doortoopen = eptr->door1;
2890
2891 SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->dx<<16,eptr->dy<<16);
2892
2893 SetElevatorOperationTime(eptr);
2894 break;
2895 }
2896 }
2897
2898 else if (eptr->doorclosing == eptr->door1)
2899 eptr->state = ev_ras;
2900
2901
2902 else if (eptr->doorclosing == eptr->door2)
2903 eptr->state = ev_rad;
2904
2905
2906 eptr->doorclosing = -1;
2907 }
2908 }
2909
2910
2911 /*
2912 =====================
2913 =
2914 = ProcessElevators
2915 =
2916 = Called from PlayLoop
2917 =
2918 =====================
2919 */
2920
ProcessElevators(void)2921 void ProcessElevators (void)
2922 {
2923 int ectr;
2924 elevator_t *eptr;
2925
2926 for (ectr = 0 ; ectr < _numelevators ; ectr++)
2927 {
2928 eptr = &ELEVATOR[ectr];
2929 if (eptr->ticcount)
2930 eptr->ticcount --;
2931 else
2932 {
2933 switch (eptr->state)
2934 {
2935 /*
2936 case ev_ras:
2937 break;
2938
2939 case ev_rad:
2940 break;
2941 */
2942 case ev_mts:
2943 ExecuteElevatorStopActions(eptr,0,(eptr->sx << 16),(eptr->sy << 16));
2944 break;
2945
2946 case ev_mtd:
2947 ExecuteElevatorStopActions(eptr,1,(eptr->dx << 16),(eptr->dy << 16));
2948 break;
2949
2950 case ev_doorclosing:
2951 CheckElevatorStart(eptr);
2952 break;
2953 }
2954 }
2955 }
2956 }
2957
2958
2959
Teleport(elevator_t * eptr,int destination)2960 void Teleport(elevator_t*eptr,int destination)
2961 {statobj_t*tstat;
2962 objtype*temp;
2963 int startx,starty,destx,desty;
2964
2965 if (destination) // move to dest
2966 {startx = eptr->sx;
2967 starty = eptr->sy;
2968 destx = eptr->dx;
2969 desty = eptr->dy;
2970 tilemap[eptr->esx][eptr->esy] = (elevatorstart + 5) | 0x2000;
2971
2972 }
2973 else
2974 {startx = eptr->dx;
2975 starty = eptr->dy;
2976 destx = eptr->sx;
2977 desty = eptr->sy;
2978 tilemap[eptr->edx][eptr->edy] = (elevatorstart + 5) | 0x2000;
2979 }
2980
2981 for(tstat=firstactivestat;tstat;tstat=tstat->nextactive)
2982 {if ((tstat->tilex == startx) && (tstat->tiley == starty))
2983 {
2984 tstat->x += ((destx - tstat->tilex) << TILESHIFT);
2985 tstat->y += ((desty - tstat->tiley) << TILESHIFT);
2986 tstat->tilex = tstat->x >> TILESHIFT;
2987 tstat->tiley = tstat->y >> TILESHIFT;
2988 tstat->visspot = &spotvis[tstat->tilex][tstat->tiley];
2989 if (sprites[startx][starty] == tstat)
2990 {sprites[startx][starty] = NULL;
2991 sprites[destx][desty] = tstat;
2992
2993 }
2994
2995 }
2996 }
2997
2998 for(temp=firstactive;temp;temp=temp->nextactive)
2999 {if ((temp->tilex == startx) && (temp->tiley == starty))
3000 {temp->x += ((destx - temp->tilex) << TILESHIFT);
3001 temp->y += ((desty - temp->tiley) << TILESHIFT);
3002 temp->tilex = temp->x >> TILESHIFT;
3003 temp->tiley = temp->y >> TILESHIFT;
3004 if (temp->obclass!=inertobj)
3005 {
3006 RemoveFromArea (temp);
3007 temp->areanumber = AREANUMBER(temp->tilex,temp->tiley);
3008 MakeLastInArea (temp);
3009 }
3010 if (temp == player)
3011 SHAKETICS = 10;
3012 }
3013 }
3014
3015
3016
3017 }
3018
3019
3020
OperateElevatorDoor(int dnum)3021 void OperateElevatorDoor(int dnum)
3022 {
3023 elevator_t*eptr;
3024 doorobj_t *dptr,*door1,*door2;
3025
3026 dptr = doorobjlist[dnum];
3027 eptr = &ELEVATOR[dptr->eindex];
3028 door1 = doorobjlist[eptr->door1];
3029 door2 = doorobjlist[eptr->door2];
3030
3031 switch(eptr->state)
3032 {/*
3033 case ev_mtd: // if already on the way to request,
3034 // ignore; else, put request in
3035 if (dnum == eptr->door1)
3036 {eptr->nextaction = ev_mts;
3037 //eptr->doortoopen = eptr->door1;
3038 #if (DEVELOPMENT == 1)
3039 #if (ELEVATORTEST == 1)
3040 Debug("\nplayer at source requesting elev %d mtd",dptr->eindex);
3041 #endif
3042 #endif
3043 }
3044 break;
3045
3046 case ev_mts:
3047 if (dnum == eptr->door2)
3048 {eptr->nextaction = ev_mtd;
3049 //eptr->doortoopen = eptr->door2;
3050 #if (DEVELOPMENT == 1)
3051 #if (ELEVATORTEST == 1)
3052 Debug("\nplayer at dest requesting elev %d mts",dptr->eindex);
3053 #endif
3054 #endif
3055 }
3056 break;
3057 */
3058 case ev_rad: // if ready at other place,
3059 if ((dnum == eptr->door1) && (eptr->nextaction != ev_mts)) // process request, lock doors,
3060
3061 {
3062 #if (DEVELOPMENT == 1)
3063 #if (ELEVATORTEST == 1)
3064 Debug("\nplayer at source requesting elev %d rad",dptr->eindex);
3065 #endif
3066 #endif
3067 // start moving to current loc;
3068 SetNextAction(eptr,0); // if already there, do nothing
3069
3070 }
3071 break;
3072
3073 case ev_ras:
3074 if ((dnum == eptr->door2) && (eptr->nextaction != ev_mtd))
3075 {
3076 #if (DEVELOPMENT == 1)
3077 #if (ELEVATORTEST == 1)
3078 Debug("\nplayer at dest requesting elev %d ras",dptr->eindex);
3079 #endif
3080 #endif
3081 SetNextAction(eptr,1);
3082
3083 }
3084 break;
3085
3086 case ev_doorclosing:
3087 if (eptr->doorclosing == dnum) // if opening door at current loc,
3088 // reset elev state to ready
3089 {//if (eptr->door1 == dnum)
3090 // eptr->nextaction = ev_ras;
3091 //else
3092 //eptr->nextaction = ev_rad;
3093 }
3094 else //else prepare for movement
3095 {if ((eptr->door1 == dnum) && (eptr->nextaction != ev_mts))
3096 {
3097 #if ((DEVELOPMENT == 1))
3098 #if ((ELEVATORTEST == 1))
3099 Debug("\nplayer at source requesting elev %d dc",dptr->eindex);
3100 #endif
3101 #endif
3102 SetNextAction(eptr,0);
3103
3104 }
3105 else if ((eptr->door2 == dnum) && (eptr->nextaction != ev_mtd))
3106 {
3107 #if ((DEVELOPMENT == 1))
3108 #if ((ELEVATORTEST == 1))
3109 Debug("\nplayer at dest requesting elev %d dc",dptr->eindex);
3110 #endif
3111 #endif
3112 SetNextAction(eptr,1);
3113
3114 }
3115 }
3116 break;
3117
3118
3119 }
3120
3121 }
3122
3123
SetNextAction(elevator_t * eptr,int action)3124 int SetNextAction(elevator_t*eptr,int action)
3125 {int dn;
3126
3127 if (action)
3128 {if (!DoorReadyToClose(eptr->door1))
3129 return false;
3130
3131 eptr->nextaction = ev_mtd;
3132 dn = eptr->door1;
3133 }
3134 else
3135 {if (!DoorReadyToClose(eptr->door2))
3136 return false;
3137
3138 eptr->nextaction = ev_mts;
3139 dn = eptr->door2;
3140 }
3141 eptr->state = ev_doorclosing;
3142
3143 eptr->doorclosing = dn;
3144 #if (DEVELOPMENT == 1)
3145 #if (ELEVATORTEST == 1)
3146 Debug("\nCloseDoor %d",dn);
3147 #endif
3148 #endif
3149 if (doorobjlist[dn]->action != dr_closed)
3150 CloseDoor(dn);
3151 doorobjlist[dn]->flags |= DF_ELEVLOCKED;
3152
3153 return true;
3154 }
3155
3156
OperateElevatorSwitch(objtype * ob,int elevnum,int checkx,int checky)3157 void OperateElevatorSwitch(objtype*ob,int elevnum,int checkx,int checky)
3158 {elevator_t*eptr;
3159 doorobj_t *door1,*door2;
3160
3161 eptr = &ELEVATOR[elevnum];
3162
3163 if ((eptr->state == ev_mts) ||
3164 (eptr->state == ev_mtd))
3165 {
3166 #if (DEVELOPMENT == 1)
3167 #if (ELEVATORTEST == 1)
3168 Debug("\nobj %d tried to use elevator %d switch while in use",ob->obclass,elevnum);
3169 #endif
3170 #endif
3171 return;
3172 }
3173
3174 door1 = doorobjlist[eptr->door1];
3175 door2 = doorobjlist[eptr->door2];
3176
3177 if ((abs(ob->tilex-door1->tilex)<=1) && //switch at source
3178 (abs(ob->tiley-door1->tiley)<=1))
3179 {if (!SetNextAction(eptr,1)) // set next to dest
3180 return;
3181 #if (DEVELOPMENT == 1)
3182 #if (ELEVATORTEST == 1)
3183 Debug("\nswitch at src %d flipped",elevnum);
3184 #endif
3185 #endif
3186 eptr->ticcount = 0;
3187 }
3188 else //switch at dest
3189 {if (!SetNextAction(eptr,0)) // set next to src
3190 return;
3191 #if (DEVELOPMENT == 1)
3192 #if (ELEVATORTEST == 1)
3193 Debug("\nswitch at dest %d flipped",elevnum);
3194 #endif
3195 #endif
3196 eptr->ticcount = 0;
3197 }
3198
3199 tilemap[checkx][checky] = (elevatorstart + 6) | 0x2000;
3200 SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
3201
3202 }
3203
3204
3205
3206
3207 /*
3208 =====================
3209 =
3210 = MoveDoors
3211 =
3212 = Called from PlayLoop
3213 =
3214 =====================
3215 */
3216
MoveDoors(void)3217 void MoveDoors (void)
3218 {
3219 int door;
3220
3221 for (door = 0 ; door < doornum ; door++)
3222 switch (doorobjlist[door]->action)
3223 {
3224 case dr_open:
3225 DoorOpen (door);
3226 break;
3227
3228 case dr_opening:
3229 DoorOpening(door);
3230 SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
3231 break;
3232
3233 case dr_closing:
3234 DoorClosing(door);
3235 SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
3236 break;
3237 default:
3238 ;
3239 }
3240 }
3241
3242
3243 //===========================================================
3244 //
3245 // PUSHWALLS
3246 //
3247 //===========================================================
3248
3249
3250 /*
3251 ===============
3252 =
3253 = GetAreaNumber
3254 =
3255 ===============
3256 */
GetAreaNumber(int tilex,int tiley,int dir)3257 int GetAreaNumber ( int tilex, int tiley, int dir )
3258 {
3259 int up,dn,lt,rt;
3260
3261 up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
3262 dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
3263 lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
3264 rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
3265 if ((up<=0) || (up>NUMAREAS)) up=0;
3266 if ((dn<=0) || (dn>NUMAREAS)) dn=0;
3267 if ((lt<=0) || (lt>NUMAREAS)) lt=0;
3268 if ((rt<=0) || (rt>NUMAREAS)) rt=0;
3269 switch (dir)
3270 {
3271 case north:
3272 if (up)
3273 return up;
3274 else if (dn)
3275 return dn;
3276 break;
3277 case south:
3278 if (dn)
3279 return dn;
3280 else if (up)
3281 return up;
3282 break;
3283 case east:
3284 if (rt)
3285 return rt;
3286 else if (lt)
3287 return lt;
3288 break;
3289 case west:
3290 if (lt)
3291 return lt;
3292 else if (rt)
3293 return rt;
3294 break;
3295 }
3296 if (up)
3297 return up;
3298 else if (dn)
3299 return dn;
3300 else if (lt)
3301 return lt;
3302 else if (rt)
3303 return rt;
3304 else
3305 Error("Cannot find an area number for tile at x=%ld y=%ld\n",tilex,tiley);
3306 return -1;
3307 }
3308
3309 /*
3310 ===============
3311 =
3312 = SpawnPushWall
3313 =
3314 ===============
3315 */
3316
SpawnPushWall(int tilex,int tiley,int lock,int texture,int dir,int type)3317 void SpawnPushWall (int tilex, int tiley, int lock, int texture, int dir, int type)
3318 {
3319 pwallobj_t * lastpwallobj;
3320
3321 if (pwallnum==MAXPWALLS)
3322 Error ("MAXPWALLS on level!");
3323
3324 pwallobjlist[pwallnum]=(pwallobj_t*)Z_LevelMalloc(sizeof(pwallobj_t),PU_LEVELSTRUCT,NULL);
3325 memset(pwallobjlist[pwallnum],0,sizeof(pwallobj_t));
3326 lastpwallobj=pwallobjlist[pwallnum];
3327
3328 lastpwallobj->x = (tilex<<16)+0x8000;
3329 lastpwallobj->y = (tiley<<16)+0x8000;
3330 lastpwallobj->momentumx=0;
3331 lastpwallobj->momentumy=0;
3332 lastpwallobj->tilex = tilex;
3333 lastpwallobj->tiley = tiley;
3334 lastpwallobj->lock = lock;
3335 lastpwallobj->action = pw_npushed;
3336 lastpwallobj->which = PWALL;
3337 lastpwallobj->dir = dir;
3338 lastpwallobj->num = pwallnum;
3339 actorat[tilex][tiley] = (pwallobj_t*)(lastpwallobj); // consider it a solid wall
3340
3341 if ( (MAPSPOT(tilex,tiley,0)==44) ||
3342 (MAPSPOT(tilex,tiley,0)==233)
3343 )
3344 lastpwallobj->flags=PW_DAMAGE;
3345
3346 lastpwallobj->texture = texture;
3347 if (!texture&0x1000)
3348 PreCacheLump(texture,PU_CACHEWALLS);
3349 lastpwallobj->areanumber = GetAreaNumber(tilex,tiley,lastpwallobj->dir);
3350
3351 MAPSPOT (tilex, tiley, 0)=(word)(lastpwallobj->areanumber+AREATILE);
3352
3353 switch(type)
3354 {
3355 case 0:
3356 case 1:
3357 case 3:
3358 lastpwallobj->speed = 2;
3359 break;
3360 case 2:
3361 case 4:
3362 lastpwallobj->speed = 4;
3363 break;
3364 default:
3365 Error("Illegal PushWall type passed into SpawnPushWall\n");
3366 break;
3367 }
3368 if (type>2)
3369 {
3370 tilemap[tilex][tiley] = 0;
3371 ActivateMoveWall(pwallnum);
3372 }
3373 else
3374 {
3375 tilemap[tilex][tiley] = texture|0x800;
3376 if ((loadedgame==false) && (type==0))
3377 gamestate.secrettotal++;
3378 }
3379
3380 pwallnum++;
3381 lastpwallobj++;
3382
3383 SD_PreCacheSoundGroup(SD_PUSHWALLSND,SD_TURBOWALLSND);
3384 }
3385
3386
3387
3388 /*
3389 =====================
3390 =
3391 = OperatePushWall
3392 =
3393 = The player wants to change the pushwall's direction
3394 =
3395 =====================
3396 */
OperatePushWall(int pwall,int dir,boolean localplayer)3397 void OperatePushWall (int pwall, int dir, boolean localplayer )
3398 {
3399 pwallobj_t * pw;
3400
3401 pw=pwallobjlist[pwall];
3402
3403 if (pw->lock)
3404 {
3405 if ( localplayer )
3406 {
3407 // Can't push
3408 AddMessage("This push wall appears to be locked...",MSG_DOOR);
3409 PlayNoWaySound();
3410 }
3411 return;
3412 }
3413 switch (pw->action)
3414 {
3415 case pw_npushed:
3416 if ((dir!=pw->dir) && (pw->dir!=nodir))
3417 {
3418 // Can't push
3419 if ( localplayer )
3420 {
3421 PlayNoWaySound();
3422 }
3423 return;
3424 }
3425 else if (localplayer && (gamestate.difficulty == gd_baby))
3426 AddMessage("Push Wall Activated.",MSG_GAME);
3427
3428 pw->action=pw_pushing;
3429 pw->dir=dir;
3430 SD_PlaySoundRTP ( SD_TOUCHPLATESND, pw->x, pw->y );
3431 ConnectPushWall(pwall);
3432 SetupPushWall(pwall);
3433 gamestate.secretcount++;
3434 break;
3435 default:
3436 // Can't push
3437 if ( localplayer )
3438 {
3439 PlayNoWaySound();
3440 }
3441 break;
3442 }
3443 }
3444
3445 /*
3446 =====================
3447 =
3448 = ActivateAllPushWalls
3449 =
3450 = A Push wall has beeen activated by a touch plate
3451 =
3452 =====================
3453 */
3454
ActivateAllPushWalls(void)3455 void ActivateAllPushWalls(void)
3456 {
3457 int i;
3458
3459 for(i=0;i<pwallnum;i++)
3460 {
3461 if (pwallobjlist[i]->dir != nodir)
3462 {
3463 ActivatePushWall(i);
3464 }
3465 }
3466 }
3467
3468 /*
3469 =====================
3470 =
3471 = ActivatePushWall
3472 =
3473 = A Push wall has beeen activated by a touch plate
3474 =
3475 =====================
3476 */
3477
ActivatePushWall(int pwall)3478 void ActivatePushWall (int pwall)
3479 {
3480 pwallobj_t * pw;
3481
3482 pw=pwallobjlist[pwall];
3483
3484 switch (pw->action)
3485 {
3486 case pw_npushed:
3487 pw->action=pw_pushing;
3488 ConnectPushWall(pwall);
3489 SetupPushWall(pwall);
3490 gamestate.secretcount++;
3491 break;
3492 default:
3493 // Can't push
3494 SD_Play( SD_BADTOUCHSND );
3495 break;
3496 }
3497 }
3498
3499 /*
3500 =====================
3501 =
3502 = ActivateMoveWall
3503 =
3504 = A Push wall has beeen activated by a touch plate
3505 =
3506 =====================
3507 */
3508
ActivateMoveWall(int pwall)3509 void ActivateMoveWall (int pwall)
3510 {
3511 pwallobj_t * pw;
3512
3513 pw=pwallobjlist[pwall];
3514
3515 switch (pw->action)
3516 {
3517 case pw_npushed:
3518 pw->action=pw_moving;
3519 SetupPushWall(pwall);
3520 break;
3521 default:
3522 SD_Play( SD_BADTOUCHSND );
3523 break;
3524 }
3525 }
3526
3527
3528
3529 /*
3530 ===============
3531 =
3532 = ConnectPushWall
3533 =
3534 ===============
3535 */
3536
ConnectPushWall(int pwall)3537 void ConnectPushWall (int pwall)
3538 {
3539 int checkx;
3540 int checky;
3541 int area1,area2;
3542 int area3,area4;
3543 word *map;
3544 pwallobj_t * pw;
3545
3546 pw=pwallobjlist[pwall];
3547
3548 checkx=pw->tilex;
3549 checky=pw->tiley;
3550 tilemap[checkx][checky] = 0;
3551 map = &MAPSPOT (checkx, checky, 0);
3552
3553 area1 = *(map-mapwidth);
3554 area2 = *(map+mapwidth);
3555 area3 = *(map+1);
3556 area4 = *(map-1);
3557
3558 area1 -= AREATILE;
3559 area2 -= AREATILE;
3560 area3 -= AREATILE;
3561 area4 -= AREATILE;
3562 if (((area1>0) && (area1<NUMAREAS)) &&
3563 ((area2>0) && (area2<NUMAREAS)))
3564 {
3565 areaconnect[area1][area2]++;
3566 areaconnect[area2][area1]++;
3567
3568 if ((insetupgame==false) && (loadedgame==false))
3569 ConnectAreas ();
3570 }
3571 if (((area3>0) && (area3<NUMAREAS)) &&
3572 ((area4>0) && (area4<NUMAREAS)))
3573 {
3574 areaconnect[area3][area4]++;
3575 areaconnect[area4][area3]++;
3576
3577 if ((insetupgame==false) && (loadedgame==false))
3578 ConnectAreas ();
3579 }
3580 }
3581
3582 /*
3583 ===============
3584 =
3585 = SetupPushWall
3586 =
3587 ===============
3588 */
3589
SetupPushWall(int pwall)3590 void SetupPushWall (int pwall)
3591 {
3592 pwallobj_t * pw;
3593 int speed;
3594
3595 pw=pwallobjlist[pwall];
3596 speed=pw->speed<<PUSHWALLSPEED;
3597 switch (pw->dir)
3598 {
3599 case north:
3600 pw->momentumx=0;
3601 pw->momentumy=-speed;
3602 break;
3603
3604 case east:
3605 pw->momentumx=speed;
3606 pw->momentumy=0;
3607 break;
3608
3609 case northeast:
3610 pw->momentumx=speed;
3611 pw->momentumy=-speed;
3612 break;
3613
3614 case southeast:
3615 pw->momentumx=speed;
3616 pw->momentumy=speed;
3617 break;
3618
3619 case south:
3620 pw->momentumx=0;
3621 pw->momentumy=speed;
3622 break;
3623
3624 case west:
3625 pw->momentumx=-speed;
3626 pw->momentumy=0;
3627 break;
3628
3629 case northwest:
3630 pw->momentumx=-speed;
3631 pw->momentumy=-speed;
3632 break;
3633
3634 case southwest:
3635 pw->momentumx=-speed;
3636 pw->momentumy=speed;
3637 break;
3638 }
3639 if (pw->action==pw_pushing)
3640 {
3641 if (loadedgame==false)
3642 pw->soundhandle=SD_PlaySoundRTP ( SD_PUSHWALLSND, pw->x, pw->y );
3643 pw->state=(0x20000L/speed);
3644 }
3645 if (pw->action==pw_moving)
3646 pw->state=(0x10000L/speed);
3647 }
3648
3649
3650 /*
3651 =====================
3652 =
3653 = MovePWalls
3654 =
3655 = Called from PlayLoop
3656 =
3657 =====================
3658 */
3659
MovePWalls(void)3660 void MovePWalls (void)
3661 {
3662 int pwall;
3663
3664 for (pwall = 0 ; pwall < pwallnum ; pwall++)
3665 {
3666 if (pwallobjlist[pwall]->action==pw_pushing)
3667 {
3668 WallPushing (pwall);
3669 SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
3670 }
3671 if (pwallobjlist[pwall]->action==pw_moving)
3672 {
3673 WallMoving (pwall);
3674 SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
3675 }
3676 }
3677 }
3678
3679
ClearActorat(pwallobj_t * pw)3680 void ClearActorat(pwallobj_t*pw)
3681 {int txhigh,txlow,tyhigh,tylow;
3682 int tryx,tryy,x,y;
3683 int pwrad = 0x6fff;
3684
3685
3686 tryx = pw->x;
3687 tryy = pw->y;
3688 txlow = (tryx - pwrad) >> 16;
3689 txhigh = (tryx + pwrad) >> 16;
3690 tylow = (tryy - pwrad) >> 16;
3691 tyhigh = (tryy + pwrad) >> 16;
3692 for(y=tylow;y<=tyhigh;y++)
3693 for(x=txlow;x<=txhigh;x++)
3694 {if (actorat[x][y] == pw)
3695 actorat[x][y] = NULL;
3696 }
3697 }
3698
SetActorat(pwallobj_t * pw)3699 void SetActorat(pwallobj_t*pw)
3700 {int txhigh,txlow,tyhigh,tylow;
3701 int tryx,tryy,x,y;
3702 int pwrad = 0x6fff;
3703
3704 tryx = pw->x;
3705 tryy = pw->y;
3706 txlow = (tryx - pwrad) >> 16;
3707 txhigh = (tryx + pwrad) >> 16;
3708 tylow = (tryy - pwrad) >> 16;
3709 tyhigh = (tryy + pwrad) >> 16;
3710
3711 for(y=tylow;y<=tyhigh;y++)
3712 for(x=txlow;x<=txhigh;x++)
3713 actorat[x][y] = pw;
3714 }
3715
3716 /*
3717 =================
3718 =
3719 = FinishPushWall
3720 =
3721 =================
3722 */
FinishPushWall(pwallobj_t * pw)3723 void FinishPushWall (pwallobj_t * pw)
3724 {
3725 pw->action = pw_pushed;
3726 actorat[pw->tilex][pw->tiley] = (wall_t*)&walls[GetWallIndex(pw->texture)];
3727 tilemap[pw->tilex][pw->tiley] = pw->texture;
3728 }
3729
3730 /*
3731 =================
3732 =
3733 = ResetPushWall
3734 =
3735 =================
3736 */
ResetPushWall(pwallobj_t * pw)3737 void ResetPushWall (pwallobj_t * pw)
3738 {
3739 SetActorat(pw);
3740 tilemap[pw->tilex][pw->tiley] = pw->texture|0x800;
3741 }
3742
3743 /*
3744 =================
3745 =
3746 = WallPushing
3747 =
3748 =================
3749 */
WallPushing(int pwall)3750 void WallPushing (int pwall)
3751 {
3752 int checkx,checky;
3753 int spot;
3754 pwallobj_t * pw;
3755
3756 pw=pwallobjlist[pwall];
3757
3758 ClearActorat(pw);
3759
3760 PushWallMove(pwall);
3761 pw->x+=pw->momentumx;
3762 pw->y+=pw->momentumy;
3763
3764 pw->state--;
3765
3766 checkx=pw->tilex;
3767 checky=pw->tiley;
3768
3769 pw->tilex=pw->x>>16;
3770 pw->tiley=pw->y>>16;
3771
3772 if ((pw->tilex!=checkx) || (pw->tiley!=checky))
3773 {
3774 int x,y;
3775 int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
3776
3777 if ((area<=0) || (area>NUMAREAS))
3778 {
3779 area=pw->areanumber;
3780 MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
3781 }
3782 // block crossed into a new block
3783 //
3784 // the tile can now be walked into
3785 //
3786 mapseen[checkx][checky] = 0;
3787 pw->areanumber = area;
3788 if (pw->momentumx>0)
3789 x=1;
3790 else if (pw->momentumx<0)
3791 x=-1;
3792 else
3793 x=0;
3794 if (pw->momentumy>0)
3795 y=1;
3796 else if (pw->momentumy<0)
3797 y=-1;
3798 else
3799 y=0;
3800 if (tilemap[pw->tilex+x][pw->tiley+y])
3801 {
3802 pw->state=(0x8000L/(pw->speed<<PUSHWALLSPEED));
3803 }
3804 if (actorat[pw->tilex+x][pw->tiley+y])
3805 ResolveDoorSpace(pw->tilex+x,pw->tiley+y);
3806 }
3807
3808
3809 if (pw->state==0)
3810 {
3811 pw->x=(pw->tilex<<16)+0x8000;
3812 pw->y=(pw->tiley<<16)+0x8000;
3813 spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
3814 if ((spot >= 0) && (spot <= 7))
3815 {
3816 pw->action = pw_npushed;
3817 pw->dir = spot;
3818 ResetPushWall (pw);
3819 if (pw->lock)
3820 {
3821 pw->action=pw_pushing;
3822 ConnectPushWall(pwall);
3823 SetupPushWall(pwall);
3824 }
3825 else
3826 {
3827 gamestate.secrettotal++;
3828 }
3829 }
3830 else
3831 {
3832 FinishPushWall (pw);
3833 }
3834 }
3835 else
3836 SetActorat(pw);
3837 }
3838
3839
3840 /*
3841 =================
3842 =
3843 = WallMoving
3844 =
3845 =================
3846 */
WallMoving(int pwall)3847 void WallMoving (int pwall)
3848 {
3849 int checkx,checky;
3850 int spot;
3851 pwallobj_t * pw;
3852
3853 pw=pwallobjlist[pwall];
3854
3855 ClearActorat(pw);
3856
3857 PushWallMove(pwall);
3858 pw->x+=pw->momentumx;
3859 pw->y+=pw->momentumy;
3860
3861 pw->state--;
3862
3863 checkx=pw->tilex;
3864 checky=pw->tiley;
3865
3866 pw->tilex=pw->x>>16;
3867 pw->tiley=pw->y>>16;
3868
3869 if ((pw->tilex!=checkx) || (pw->tiley!=checky))
3870 {
3871 int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
3872
3873 if ((area<=0) || (area>NUMAREAS))
3874 {
3875 area=pw->areanumber;
3876 MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
3877 }
3878 // block crossed into a new block
3879 //
3880 // the tile can now be walked into
3881 //
3882 if (areabyplayer[area])
3883 {
3884 if (pw->speed==2)
3885 pw->soundhandle=SD_PlaySoundRTP ( SD_GOWALLSND, pw->x, pw->y );
3886 else
3887 pw->soundhandle=SD_PlaySoundRTP ( SD_TURBOWALLSND, pw->x, pw->y );
3888 }
3889
3890 if (actorat[pw->tilex][pw->tilex])
3891 ResolveDoorSpace(pw->tilex,pw->tiley);
3892 mapseen[checkx][checky] = 0;
3893 pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
3894 //actorat[pw->tilex][pw->tiley]=pw;
3895 if ( (pw->tilex==0) || (pw->tilex==127) ||
3896 (pw->tiley==0) || (pw->tiley==127) )
3897 {
3898 if (W_CheckNumForName("imfree")>=0)
3899 {
3900 lbm_t *LBM;
3901
3902 LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("imfree"), PU_CACHE, Cvt_lbm_t, 1);
3903 VL_DecompressLBM (LBM,true);
3904 VW_UpdateScreen ();
3905 I_Delay (2000);
3906 }
3907 Error ("PushWall Attempting to escape off the edge of the map\nIt is located at x=%ld y=%ld\nI'm Free!!!!\n",
3908 pw->tilex, pw->tiley);
3909 }
3910 }
3911 if (pw->state==0)
3912 {
3913 pw->x=(pw->tilex<<16)+0x8000;
3914 pw->y=(pw->tiley<<16)+0x8000;
3915 spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
3916 if ((spot >= 0) && (spot <= 7))
3917 {
3918 int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
3919
3920 if ((area<=0) || (area>NUMAREAS))
3921 {
3922 area=pw->areanumber;
3923 MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
3924 }
3925
3926 if (areabyplayer[area] && (abs(spot-pw->dir)==4))
3927 SD_PlaySoundRTP ( SD_PUSHWALLHITSND, pw->x, pw->y );
3928 pw->dir = spot;
3929 }
3930 SetupPushWall(pwall);
3931 }
3932 else
3933 SetActorat(pw);
3934 }
3935
3936
3937
3938 /*
3939 =================
3940 =
3941 = SavePushWalls
3942 =
3943 =================
3944 */
SavePushWalls(byte ** buf,int * sz)3945 void SavePushWalls(byte ** buf, int * sz)
3946 {
3947 int unitsize;
3948 pwallobj_t * pw;
3949 byte * bufptr;
3950 int i;
3951 int size;
3952
3953 if (pwallnum==0)
3954 {
3955 *sz=0;
3956 *buf=SafeMalloc(16);
3957 return;
3958 }
3959 pw=pwallobjlist[0];
3960 unitsize=0;
3961 unitsize+=sizeof(pw->state);
3962 unitsize+=sizeof(pw->x);
3963 unitsize+=sizeof(pw->y);
3964 unitsize+=sizeof(pw->dir);
3965 unitsize+=sizeof(pw->speed);
3966 unitsize+=sizeof(pw->action);
3967
3968 *sz=pwallnum*unitsize;
3969
3970 *buf=SafeMalloc(*sz);
3971 bufptr=*buf;
3972
3973 for (i=0;i<pwallnum;i++)
3974 {
3975 pw=pwallobjlist[i];
3976 size=sizeof(pw->state);
3977 memcpy(bufptr,&(pw->state),size);
3978 bufptr+=size;
3979
3980 size=sizeof(pw->x);
3981 memcpy(bufptr,&(pw->x),size);
3982 bufptr+=size;
3983
3984 size=sizeof(pw->y);
3985 memcpy(bufptr,&(pw->y),size);
3986 bufptr+=size;
3987
3988 size=sizeof(pw->dir);
3989 memcpy(bufptr,&(pw->dir),size);
3990 bufptr+=size;
3991
3992 size=sizeof(pw->speed);
3993 memcpy(bufptr,&(pw->speed),size);
3994 bufptr+=size;
3995
3996 size=sizeof(pw->action);
3997 memcpy(bufptr,&(pw->action),size);
3998 bufptr+=size;
3999 }
4000 }
4001
4002 /*
4003 =================
4004 =
4005 = LoadPushWalls
4006 =
4007 =================
4008 */
LoadPushWalls(byte * bufptr,int sz)4009 void LoadPushWalls(byte * bufptr, int sz)
4010 {
4011 int unitsize;
4012 pwallobj_t * pw;
4013 pwallobj_t new;
4014 int i;
4015 int num;
4016 int size;
4017 int area;
4018
4019 if (sz==0)
4020 return;
4021 SetupPushWalls();
4022 pw=pwallobjlist[0];
4023 unitsize=0;
4024 unitsize+=sizeof(pw->state);
4025 unitsize+=sizeof(pw->x);
4026 unitsize+=sizeof(pw->y);
4027 unitsize+=sizeof(pw->dir);
4028 unitsize+=sizeof(pw->speed);
4029 unitsize+=sizeof(pw->action);
4030
4031 num=sz/unitsize;
4032 if (pwallnum!=num)
4033 Error("Different number of Push Walls when trying to load a game\npwallnum=%ld num=%ld",pwallnum,num);
4034
4035 for (i=0;i<pwallnum;i++)
4036 {
4037 pw=pwallobjlist[i];
4038
4039 size=sizeof(new.state);
4040 memcpy(&(new.state),bufptr,size);
4041 bufptr+=size;
4042
4043 size=sizeof(new.x);
4044 memcpy(&(new.x),bufptr,size);
4045 bufptr+=size;
4046
4047 size=sizeof(new.y);
4048 memcpy(&(new.y),bufptr,size);
4049 bufptr+=size;
4050
4051 size=sizeof(new.dir);
4052 memcpy(&(new.dir),bufptr,size);
4053 bufptr+=size;
4054
4055 size=sizeof(new.speed);
4056 memcpy(&(new.speed),bufptr,size);
4057 bufptr+=size;
4058
4059 size=sizeof(new.action);
4060 memcpy(&(new.action),bufptr,size);
4061 bufptr+=size;
4062
4063 actorat[pw->tilex][pw->tiley] = 0;
4064 mapseen[pw->tilex][pw->tiley] = 0;
4065
4066 new.tilex=new.x>>16;
4067 new.tiley=new.y>>16;
4068
4069 if ((new.tilex!=pw->tilex) || (new.tiley!=pw->tiley))
4070 {
4071 ClearActorat(pw);
4072 tilemap[pw->tilex][pw->tiley] = 0;
4073 if (pw->state!=pw_moving)
4074 {
4075 #if 0
4076 if (pw->dir==nodir)
4077 {
4078 if (tilemap[pw->tilex+1][pw->tiley]==0)
4079 pw->dir=east;
4080 else if (tilemap[pw->tilex-1][pw->tiley]==0)
4081 pw->dir=west;
4082 else if (tilemap[pw->tilex][pw->tiley+1]==0)
4083 pw->dir=south;
4084 else
4085 pw->dir=north;
4086 }
4087 #endif
4088 ConnectPushWall(i);
4089 }
4090 }
4091
4092 // fixup area if needed
4093
4094 area = MAPSPOT(new.tilex,new.tiley,0)-AREATILE;
4095 if ((area<=0) || (area>NUMAREAS))
4096 {
4097 MAPSPOT (new.tilex, new.tiley, 0)=(word)(pw->areanumber+AREATILE);
4098 }
4099
4100 pw->tilex=new.tilex;
4101 pw->tiley=new.tiley;
4102 pw->x=new.x;
4103 pw->y=new.y;
4104 pw->action=new.action;
4105 pw->dir=new.dir;
4106 pw->speed=new.speed;
4107 SetupPushWall(i);
4108 pw->state=new.state;
4109
4110 pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
4111
4112 if (pw->action==pw_pushed)
4113 {
4114 FinishPushWall (pw);
4115 }
4116 else if (pw->action==pw_npushed)
4117 {
4118 ResetPushWall (pw);
4119 }
4120 else
4121 {
4122 SetActorat(pw);
4123 }
4124 }
4125 }
4126
4127
4128
4129
4130
4131 /*
4132 =================
4133 =
4134 = SaveMaskedWalls
4135 =
4136 =================
4137 */
SaveMaskedWalls(byte ** buf,int * size)4138 void SaveMaskedWalls(byte ** buf, int * size)
4139 {
4140 int unitsize;
4141 maskedwallobj_t * mw;
4142 byte * bufptr;
4143 int i;
4144 int sz;
4145
4146 if (maskednum==0)
4147 {
4148 *size=0;
4149 *buf=SafeMalloc(16);
4150 return;
4151 }
4152 mw=maskobjlist[0];
4153 unitsize=0;
4154 unitsize+=sizeof(mw->flags);
4155
4156 *size=maskednum*unitsize;
4157
4158 *buf=SafeMalloc(*size);
4159 bufptr=*buf;
4160
4161 for (i=0;i<maskednum;i++)
4162 {
4163 mw=maskobjlist[i];
4164 sz=sizeof(mw->flags);
4165 memcpy(bufptr,&(mw->flags),sz);
4166 bufptr+=sz;
4167 }
4168 }
4169
4170 /*
4171 =================
4172 =
4173 = LoadMaskedWalls
4174 =
4175 =================
4176 */
LoadMaskedWalls(byte * bufptr,int sz)4177 void LoadMaskedWalls(byte * bufptr, int sz)
4178 {
4179 int unitsize;
4180 maskedwallobj_t * mw;
4181 int i;
4182 int size;
4183 int num;
4184
4185 if (sz==0)
4186 return;
4187
4188 SetupMaskedWalls();
4189 FixMaskedWallAreaNumbers();
4190
4191 mw=maskobjlist[0];
4192 unitsize=0;
4193 unitsize+=sizeof(mw->flags);
4194
4195 num=sz/unitsize;
4196 if (maskednum!=num)
4197 Error("Different number of Masked Walls when trying to load a game\nmaskednum=%ld num=%ld",maskednum,num);
4198
4199 for (i=0;i<maskednum;i++)
4200 {
4201 byte flags;
4202
4203 mw=maskobjlist[i];
4204 size=sizeof(mw->flags);
4205 memcpy(&flags,bufptr,size);
4206 bufptr+=size;
4207 if (flags!=mw->flags)
4208 UpdateMaskedWall(i);
4209 if (mw->flags&MW_SWITCHON)
4210 mw->toptexture--;
4211 }
4212 }
4213
4214
4215 /*
4216 =================
4217 =
4218 = SaveDoors
4219 =
4220 =================
4221 */
4222
SaveDoors(byte ** buf,int * size)4223 void SaveDoors (byte ** buf, int * size)
4224 {
4225 int door;
4226 int doorsave;
4227 byte doorflag;
4228 byte doorlocked;
4229 signed char dooreindex;
4230 short int doortime;
4231 int unitsize;
4232 byte *ptr;
4233
4234 if (doornum==0)
4235 {
4236 *size=0;
4237 *buf=SafeMalloc(16);
4238 return;
4239 }
4240
4241 //
4242 // Size = (int + byte + byte) * numdoors
4243 //
4244
4245 unitsize=0;
4246 unitsize+=sizeof(doorsave);
4247 unitsize+=sizeof(doorflag);
4248 unitsize+=sizeof(doorlocked);
4249 unitsize+=sizeof(doortime);
4250 unitsize+=sizeof(dooreindex);
4251
4252 *size = unitsize*doornum;
4253 *buf = (byte *) SafeMalloc (*size);
4254
4255 ptr = *buf;
4256
4257 for (door = 0; door < doornum ; door++)
4258 {
4259 doorsave = doorobjlist[door]->position & ~3;
4260 doorsave |= doorobjlist[door]->action;
4261 doorflag = doorobjlist[door]->flags;
4262 doorlocked = doorobjlist[door]->lock;
4263 doortime = doorobjlist[door]->ticcount;
4264 dooreindex = doorobjlist[door]->eindex;
4265
4266 memcpy (ptr, &doorsave, sizeof (doorsave));
4267 ptr += sizeof (doorsave);
4268 memcpy (ptr, &doorflag, sizeof (doorflag));
4269 ptr += sizeof (doorflag);
4270 memcpy (ptr, &doorlocked, sizeof (doorlocked));
4271 ptr += sizeof (doorlocked);
4272 memcpy (ptr, &doortime, sizeof (doortime));
4273 ptr += sizeof (doortime);
4274 memcpy (ptr, &dooreindex, sizeof (dooreindex));
4275 ptr += sizeof (dooreindex);
4276 }
4277 }
4278
4279
4280 /*
4281 =================
4282 =
4283 = LoadDoors
4284 =
4285 =================
4286 */
4287
LoadDoors(byte * buf,int size)4288 void LoadDoors (byte * buf, int size)
4289 {
4290 int door;
4291 int doorsave;
4292 byte doorflag;
4293 byte doorlocked;
4294 signed char dooreindex;
4295 short int doortime;
4296 byte *ptr;
4297 int unitsize;
4298 int num;
4299
4300 SetupDoors ();
4301 FixDoorAreaNumbers();
4302 ptr = buf;
4303
4304 unitsize=0;
4305 unitsize+=sizeof(doorsave);
4306 unitsize+=sizeof(doorflag);
4307 unitsize+=sizeof(doorlocked);
4308 unitsize+=sizeof(doortime);
4309 unitsize+=sizeof(dooreindex);
4310
4311 num=size/unitsize;
4312 if (doornum!=num)
4313 Error("Different number of Doors when trying to load a game\ndoornum=%ld num=%ld",doornum,num);
4314
4315 for (door = 0; door < doornum; door++)
4316 {
4317 memcpy (&doorsave, ptr, sizeof (doorsave));
4318 ptr += sizeof (doorsave);
4319 memcpy (&doorflag, ptr, sizeof (doorflag));
4320 ptr += sizeof (doorflag);
4321 memcpy (&doorlocked, ptr, sizeof (doorlocked));
4322 ptr += sizeof (doorlocked);
4323 memcpy (&doortime, ptr, sizeof (doortime));
4324 ptr += sizeof (doortime);
4325 memcpy (&dooreindex, ptr, sizeof (dooreindex));
4326 ptr += sizeof (dooreindex);
4327
4328 doorobjlist[door]->action = doorsave & 3;
4329
4330 // Update Areas
4331
4332 if (doorobjlist[door]->action != dr_closed)
4333 DoorOpening(door);
4334
4335 doorobjlist[door]->action = doorsave & 3;
4336 doorobjlist[door]->position = doorsave;
4337 doorobjlist[door]->flags = doorflag;
4338 doorobjlist[door]->lock = doorlocked;
4339 doorobjlist[door]->ticcount = doortime;
4340 doorobjlist[door]->eindex = dooreindex;
4341
4342 if (doorobjlist[door]->action == dr_open)
4343 doorobjlist[door]->position = 0xFFFF;
4344
4345 else if (doorobjlist[door]->action == dr_closed)
4346 doorobjlist[door]->position = 0;
4347
4348 if (
4349 (doorobjlist[door]->action == dr_closing) ||
4350 (doorobjlist[door]->action == dr_closed)
4351 )
4352 {
4353 actorat[doorobjlist[door]->tilex][doorobjlist[door]->tiley] = doorobjlist[door];
4354 }
4355 doorobjlist[door]->texture = doorobjlist[door]->basetexture +
4356 ((doorobjlist[door]->position+1)>>13);
4357 }
4358 }
4359
4360
4361 /*
4362 =====================
4363 =
4364 = SaveElevators
4365 =
4366 =
4367 =====================
4368 */
4369
SaveElevators(byte ** buffer,int * size)4370 void SaveElevators(byte ** buffer,int *size)
4371 {int i;
4372 byte * tptr;
4373
4374 *size = _numelevators*sizeof(elevator_t);
4375
4376 *buffer = (byte *)SafeMalloc(*size);
4377 tptr = *buffer;
4378
4379 for(i=0;i<_numelevators;i++)
4380 {memcpy(tptr,&ELEVATOR[i],sizeof(elevator_t));
4381 tptr += sizeof(elevator_t);
4382 }
4383 }
4384
4385
4386 /*
4387 =====================
4388 =
4389 = LoadElevators
4390 =
4391 =
4392 =====================
4393 */
4394
LoadElevators(byte * buffer,int size)4395 void LoadElevators(byte * buffer,int size)
4396 {int i;
4397
4398 _numelevators = size/sizeof(elevator_t);
4399
4400
4401 for(i=0;i<_numelevators;i++)
4402 {memcpy(&ELEVATOR[i],buffer,sizeof(elevator_t));
4403 buffer += sizeof(elevator_t);
4404 }
4405 }
4406
4407