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