~ubuntu-branches/ubuntu/karmic/rott/karmic-proposed

« back to all changes in this revision

Viewing changes to rt_door.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabian Greffrath
  • Date: 2008-01-27 20:00:00 UTC
  • mfrom: (1.1.1 upstream) (2.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080127200000-myle9y0099o45sfv
Tags: 1.0+dfsg-2
* debian/patches/01-custom-datapath.dpatch,
  debian/patches/13-improve-makefile.dpatch:
  + Changed DATADIR back to "/usr/share/games/rott/".

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
277
void KillAnimatedMaskedWall ( animmaskedwallobj_t * temp )
 
278
{
 
279
   DeactivateAnimMaskedWall(temp);
 
280
   Z_Free(temp);
 
281
}
 
282
 
 
283
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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 (SHAREWARE == 1)
 
1339
         lastdoorobj->sidepic = W_GetNumForName("SIDE8");
 
1340
 
 
1341
      #else
 
1342
         lastdoorobj->sidepic    = W_GetNumForName("SIDE16");
 
1343
      #endif
 
1344
 
 
1345
         lastdoorobj->alttexture = W_GetNumForName("ABOVEW16");
 
1346
         break;
 
1347
 
 
1348
      case 18:
 
1349
      case 19:
 
1350
      case 20:
 
1351
      #if (SHAREWARE == 1)
 
1352
         lastdoorobj->sidepic = W_GetNumForName("SIDE8");
 
1353
         lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
 
1354
 
 
1355
      #else
 
1356
         lastdoorobj->sidepic    = W_GetNumForName("SIDE17");
 
1357
         lastdoorobj->alttexture = W_GetNumForName("ABOVEW17");
 
1358
 
 
1359
      #endif
 
1360
 
 
1361
         break;
 
1362
      default:
 
1363
         Error("Illegal door value encountered\n");
 
1364
         break;
 
1365
      }
 
1366
 
 
1367
 
 
1368
 
 
1369
   if ((lock>0) && (lock<5))
 
1370
      lastdoorobj->sidepic    = W_GetNumForName("lock1")+lock-1;
 
1371
 
 
1372
   PreCacheLump(lastdoorobj->sidepic,PU_CACHEWALLS);
 
1373
   PreCacheLump(lastdoorobj->alttexture,PU_CACHEWALLS);
 
1374
 
 
1375
        if (lastdoorobj->vertical==true)
 
1376
        {
 
1377
      if (up==1)
 
1378
                   tilemap[tilex][tiley-1] |= 0x4000;
 
1379
      else if (up==2)
 
1380
         lastdoorobj->flags|=DF_MULTI;
 
1381
      if (dn==1)
 
1382
                   tilemap[tilex][tiley+1] |= 0x4000;
 
1383
      else if (dn==2)
 
1384
         lastdoorobj->flags|=DF_MULTI;
 
1385
        }
 
1386
        else
 
1387
        {
 
1388
      if (lt==1)
 
1389
                   tilemap[tilex-1][tiley] |= 0x4000;
 
1390
      else if (lt==2)
 
1391
         lastdoorobj->flags|=DF_MULTI;
 
1392
      if (rt==1)
 
1393
                   tilemap[tilex+1][tiley] |= 0x4000;
 
1394
      else if (rt==2)
 
1395
         lastdoorobj->flags|=DF_MULTI;
 
1396
        }
 
1397
 
 
1398
   for (i=0;i<9;i++)
 
1399
      PreCacheLump(lastdoorobj->texture+i,PU_CACHEWALLS);
 
1400
        doornum++;
 
1401
        lastdoorobj++;
 
1402
        if (doornum==MAXDOORS)
 
1403
                Error ("Too many doors on level!");
 
1404
 
 
1405
}
 
1406
 
 
1407
/*
 
1408
===============
 
1409
=
 
1410
= MakeWideDoorVisible
 
1411
=
 
1412
===============
 
1413
*/
 
1414
void MakeWideDoorVisible ( int doornum )
 
1415
{
 
1416
   int dx,dy;
 
1417
   doorobj_t * dr2;
 
1418
   doorobj_t * dr;
 
1419
   int tx,ty;
 
1420
 
 
1421
   dr=doorobjlist[doornum];
 
1422
 
 
1423
   dx=0;dy=0;
 
1424
   if (dr->vertical==true)
 
1425
      dy=1;
 
1426
   else
 
1427
      dx=1;
 
1428
   spotvis[dr->tilex][dr->tiley]=1;
 
1429
   tx=dr->tilex+dx;
 
1430
   ty=dr->tiley+dy;
 
1431
        while (M_ISDOOR(tx,ty))
 
1432
      {
 
1433
      int num;
 
1434
 
 
1435
      num=tilemap[tx][ty]&0x3ff;
 
1436
      dr2=doorobjlist[num];
 
1437
      if (!(dr2->flags&DF_MULTI))
 
1438
         break;
 
1439
      spotvis[tx][ty]=1;
 
1440
 
 
1441
      tx+=dx;
 
1442
      ty+=dy;
 
1443
      }
 
1444
   tx=dr->tilex-dx;
 
1445
   ty=dr->tiley-dy;
 
1446
        while (M_ISDOOR(tx,ty))
 
1447
      {
 
1448
      int num;
 
1449
 
 
1450
      num=tilemap[tx][ty]&0x3ff;
 
1451
      dr2=doorobjlist[num];
 
1452
      if (!(dr2->flags&DF_MULTI))
 
1453
         break;
 
1454
      spotvis[tx][ty]=1;
 
1455
 
 
1456
      tx-=dx;
 
1457
      ty-=dy;
 
1458
      }
 
1459
}
 
1460
 
 
1461
/*
 
1462
=====================
 
1463
=
 
1464
= LockLinkedDoor
 
1465
=
 
1466
=====================
 
1467
*/
 
1468
 
 
1469
void LockLinkedDoor (int door)
 
1470
{
 
1471
        doorobj_t*dptr;
 
1472
 
 
1473
        dptr = doorobjlist[door];
 
1474
   if (!dptr->lock)
 
1475
      dptr->lock=5;
 
1476
}
 
1477
 
 
1478
/*
 
1479
=====================
 
1480
=
 
1481
= IsDoorLinked
 
1482
=
 
1483
=====================
 
1484
*/
 
1485
 
 
1486
boolean IsDoorLinked (int door)
 
1487
{
 
1488
        doorobj_t*dptr;
 
1489
 
 
1490
        dptr = doorobjlist[door];
 
1491
   if (dptr->lock==5)
 
1492
      return true;
 
1493
   return false;
 
1494
}
 
1495
 
 
1496
 
 
1497
/*
 
1498
===============
 
1499
=
 
1500
= FixDoorAreaNumbers
 
1501
=
 
1502
===============
 
1503
*/
 
1504
void FixDoorAreaNumbers ( void )
 
1505
{
 
1506
   int i;
 
1507
   int up,dn,lt,rt;
 
1508
   int tilex,tiley;
 
1509
 
 
1510
   for (i=0;i<doornum;i++)
 
1511
      {
 
1512
      tilex=doorobjlist[i]->tilex;
 
1513
      tiley=doorobjlist[i]->tiley;
 
1514
      up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
 
1515
                dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
 
1516
                lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
 
1517
                rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
 
1518
 
 
1519
      up = ((up>0) && (up<=NUMAREAS));
 
1520
                dn = ((dn>0) && (dn<=NUMAREAS));
 
1521
                lt = ((lt>0) && (lt<=NUMAREAS));
 
1522
                rt = ((rt>0) && (rt<=NUMAREAS));
 
1523
 
 
1524
 
 
1525
                if (doorobjlist[i]->vertical==true)
 
1526
                        {
 
1527
         if (rt)
 
1528
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
 
1529
         else if (lt)
 
1530
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
 
1531
                        else
 
1532
                                Error("FixDoors: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
 
1533
                        }
 
1534
                else
 
1535
                        {
 
1536
         if (dn)
 
1537
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
 
1538
         else if (up)
 
1539
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
 
1540
                        else
 
1541
                                Error("FixDoors: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
 
1542
                        }
 
1543
      if (IsDoorLinked(i))
 
1544
         UtilizeDoor(i,LockLinkedDoor);
 
1545
                }
 
1546
}
 
1547
 
 
1548
 
 
1549
//===========================================================================
 
1550
 
 
1551
/*
 
1552
=====================
 
1553
=
 
1554
= OpenDoor
 
1555
=
 
1556
=====================
 
1557
*/
 
1558
 
 
1559
void OpenDoor (int door)
 
1560
{
 
1561
        if (doorobjlist[door]->action == dr_open)
 
1562
                doorobjlist[door]->ticcount = 0;                        // reset open time
 
1563
        else
 
1564
      {
 
1565
                doorobjlist[door]->action = dr_opening; // start it opening
 
1566
      }
 
1567
}
 
1568
 
 
1569
/*
 
1570
=====================
 
1571
=
 
1572
= DoorUnBlocked
 
1573
=
 
1574
=====================
 
1575
*/
 
1576
 
 
1577
boolean DoorUnBlocked (int door)
 
1578
{
 
1579
        int     tilex,tiley;
 
1580
        objtype *check;
 
1581
        doorobj_t*dptr;
 
1582
 
 
1583
        dptr = doorobjlist[door];
 
1584
 
 
1585
//
 
1586
// don't close on anything solid
 
1587
//
 
1588
 
 
1589
        tilex = dptr->tilex;
 
1590
        tiley = dptr->tiley;
 
1591
        check = (objtype*)actorat[tilex][tiley];
 
1592
 
 
1593
        if (check && (check->which == ACTOR))
 
1594
                return false;
 
1595
 
 
1596
        if (dptr->vertical==true)
 
1597
        {
 
1598
                check = (objtype*)actorat[tilex-1][tiley];
 
1599
                if (check && (check->which==ACTOR) && ((check->x+MINDIST) >> TILESHIFT) == tilex )
 
1600
                        return false;
 
1601
                check = (objtype*)actorat[tilex+1][tiley];
 
1602
                if (check && (check->which==ACTOR) && ((check->x-MINDIST) >> TILESHIFT) == tilex )
 
1603
                        return false;
 
1604
        }
 
1605
        else if (dptr->vertical==false)
 
1606
        {
 
1607
                check = (objtype*)actorat[tilex][tiley-1];
 
1608
                if (check && (check->which==ACTOR) && ((check->y+MINDIST) >> TILESHIFT) == tiley )
 
1609
                        return false;
 
1610
                check = (objtype*)actorat[tilex][tiley+1];
 
1611
                if (check && (check->which==ACTOR) && ((check->y-MINDIST) >> TILESHIFT) == tiley )
 
1612
                        return false;
 
1613
        }
 
1614
   return true;
 
1615
}
 
1616
 
 
1617
 
 
1618
/*
 
1619
=====================
 
1620
=
 
1621
= DoorReadyToClose
 
1622
=
 
1623
= Alter the door's state
 
1624
=
 
1625
=====================
 
1626
*/
 
1627
 
 
1628
boolean DoorReadyToClose(int door)
 
1629
{
 
1630
        doorobj_t*dptr;
 
1631
        int dx,dy;
 
1632
        doorobj_t * dr2;
 
1633
        int tx,ty;
 
1634
 
 
1635
 
 
1636
        dptr = doorobjlist[door];
 
1637
 
 
1638
        if (dptr->action==dr_closed)
 
1639
                return true;
 
1640
 
 
1641
        if (DoorUnBlocked(door)==false)
 
1642
                return false;
 
1643
 
 
1644
        dx=0;dy=0;
 
1645
        if (dptr->vertical==true)
 
1646
                dy=1;
 
1647
        else
 
1648
                dx=1;
 
1649
        tx=dptr->tilex+dx;
 
1650
        ty=dptr->tiley+dy;
 
1651
        while (M_ISDOOR(tx,ty))
 
1652
                {
 
1653
                int num;
 
1654
 
 
1655
                num=tilemap[tx][ty]&0x3ff;
 
1656
                dr2=doorobjlist[num];
 
1657
                if (!(dr2->flags&DF_MULTI))
 
1658
                        break;
 
1659
                if (DoorUnBlocked(num)==false)
 
1660
                        return false;
 
1661
                tx+=dx;
 
1662
                ty+=dy;
 
1663
                }
 
1664
        tx=dptr->tilex-dx;
 
1665
        ty=dptr->tiley-dy;
 
1666
        while (M_ISDOOR(tx,ty))
 
1667
                {
 
1668
                int num;
 
1669
 
 
1670
                num=tilemap[tx][ty]&0x3ff;
 
1671
                dr2=doorobjlist[num];
 
1672
                if (!(dr2->flags&DF_MULTI))
 
1673
                        break;
 
1674
                if (DoorUnBlocked(num)==false)
 
1675
                        return false;
 
1676
                tx-=dx;
 
1677
                ty-=dy;
 
1678
                }
 
1679
        return true;
 
1680
}
 
1681
 
 
1682
 
 
1683
/*
 
1684
=====================
 
1685
=
 
1686
= CloseDoor
 
1687
=
 
1688
=====================
 
1689
*/
 
1690
 
 
1691
void CloseDoor (int door)
 
1692
{
 
1693
        int     tilex,tiley,area;
 
1694
        doorobj_t*dptr;
 
1695
 
 
1696
        dptr = doorobjlist[door];
 
1697
   if (dptr->action == dr_closed)
 
1698
      return;
 
1699
        tilex = dptr->tilex;
 
1700
        tiley = dptr->tiley;
 
1701
 
 
1702
//
 
1703
// play door sound
 
1704
//
 
1705
   area = MAPSPOT(tilex,tiley,0)-AREATILE;
 
1706
   if (areabyplayer[area])
 
1707
      {
 
1708
      dptr->soundhandle=SD_PlaySoundRTP ( SD_CLOSEDOORSND, dptr->tilex<<16, dptr->tiley<<16 );
 
1709
      }
 
1710
 
 
1711
        dptr->action = dr_closing;
 
1712
//
 
1713
// make the door space solid
 
1714
//
 
1715
        actorat[tilex][tiley] = dptr;
 
1716
}
 
1717
 
 
1718
 
 
1719
 
 
1720
/*
 
1721
=====================
 
1722
=
 
1723
= OperateDoor
 
1724
=
 
1725
= The player wants to change the door's direction
 
1726
=
 
1727
=====================
 
1728
*/
 
1729
 
 
1730
void OperateDoor (int keys, int door, boolean localplayer )
 
1731
{
 
1732
        int     lock;
 
1733
        doorobj_t*dptr;
 
1734
 
 
1735
        dptr = doorobjlist[door];
 
1736
        if ( ( dptr->flags & DF_ELEVLOCKED ) ||
 
1737
      ( MISCVARS->GASON && ( MAPSPOT( dptr->tilex,
 
1738
      dptr->tiley, 1 ) == GASVALUE ) ) )
 
1739
      {
 
1740
      if ( localplayer )
 
1741
         {
 
1742
         // locked
 
1743
         SD_Play ( SD_NOITEMSND );
 
1744
         }
 
1745
      return;
 
1746
      }
 
1747
 
 
1748
   lock = dptr->lock;
 
1749
        if ( lock && !( keys & ( 1 << ( lock - 1 ) ) ) )
 
1750
      {
 
1751
      if ( localplayer )
 
1752
         {
 
1753
         // locked
 
1754
         switch (lock)
 
1755
            {
 
1756
            case 1:
 
1757
               AddMessage("You need the \\EGOLD key",MSG_DOOR);
 
1758
               break;
 
1759
 
 
1760
            case 2:
 
1761
               AddMessage("You need the \\FSILVER key",MSG_DOOR);
 
1762
               break;
 
1763
 
 
1764
            case 3:
 
1765
               AddMessage("You need the \\8IRON key",MSG_DOOR);
 
1766
               break;
 
1767
 
 
1768
            case 4:
 
1769
               AddMessage("You need the \\AOSCURO key",MSG_DOOR);
 
1770
               break;
 
1771
 
 
1772
            default:
 
1773
               AddMessage("This door appears to be locked",MSG_DOOR);
 
1774
               break;
 
1775
            }
 
1776
 
 
1777
         SD_Play( SD_NOITEMSND );
 
1778
         }
 
1779
      return;
 
1780
      }
 
1781
   UseDoor(door);
 
1782
   }
 
1783
 
 
1784
/*
 
1785
=====================
 
1786
=
 
1787
= LinkedOpenDoor
 
1788
=
 
1789
=====================
 
1790
*/
 
1791
 
 
1792
void LinkedOpenDoor (int door)
 
1793
{
 
1794
   UtilizeDoor(door,OpenDoor);
 
1795
}
 
1796
 
 
1797
/*
 
1798
=====================
 
1799
=
 
1800
= LinkedCloseDoor
 
1801
=
 
1802
=====================
 
1803
*/
 
1804
 
 
1805
void LinkedCloseDoor (int door)
 
1806
{
 
1807
   if (DoorReadyToClose(door)==true)
 
1808
      UtilizeDoor(door,CloseDoor);
 
1809
}
 
1810
 
 
1811
/*
 
1812
=====================
 
1813
=
 
1814
= UtilizeDoor
 
1815
=
 
1816
= Alter the door's state
 
1817
=
 
1818
=====================
 
1819
*/
 
1820
 
 
1821
void UtilizeDoor (int door,void (*action)(int))
 
1822
{
 
1823
        doorobj_t*dptr;
 
1824
   int dx,dy;
 
1825
   doorobj_t * dr2;
 
1826
   int tx,ty;
 
1827
 
 
1828
        dptr = doorobjlist[door];
 
1829
 
 
1830
   action(door);
 
1831
 
 
1832
   dx=0;dy=0;
 
1833
   if (dptr->vertical==true)
 
1834
      dy=1;
 
1835
   else
 
1836
      dx=1;
 
1837
   tx=dptr->tilex+dx;
 
1838
   ty=dptr->tiley+dy;
 
1839
        while (M_ISDOOR(tx,ty))
 
1840
      {
 
1841
      int num;
 
1842
 
 
1843
      num=tilemap[tx][ty]&0x3ff;
 
1844
      dr2=doorobjlist[num];
 
1845
      if (!(dr2->flags&DF_MULTI))
 
1846
         break;
 
1847
      action(num);
 
1848
      tx+=dx;
 
1849
      ty+=dy;
 
1850
      }
 
1851
   tx=dptr->tilex-dx;
 
1852
   ty=dptr->tiley-dy;
 
1853
        while (M_ISDOOR(tx,ty))
 
1854
      {
 
1855
      int num;
 
1856
 
 
1857
      num=tilemap[tx][ty]&0x3ff;
 
1858
      dr2=doorobjlist[num];
 
1859
      if (!(dr2->flags&DF_MULTI))
 
1860
         break;
 
1861
      action(num);
 
1862
      tx-=dx;
 
1863
      ty-=dy;
 
1864
      }
 
1865
}
 
1866
 
 
1867
/*
 
1868
=====================
 
1869
=
 
1870
= UseDoor
 
1871
=
 
1872
= Alter the door's state
 
1873
=
 
1874
=====================
 
1875
*/
 
1876
 
 
1877
void UseDoor (int door)
 
1878
{
 
1879
        switch (doorobjlist[door]->action)
 
1880
        {
 
1881
        case dr_closing:
 
1882
                SD_StopSound(doorobjlist[door]->soundhandle);
 
1883
        case dr_closed:
 
1884
      UtilizeDoor(door,OpenDoor);
 
1885
                break;
 
1886
        case dr_opening:
 
1887
                SD_StopSound(doorobjlist[door]->soundhandle);
 
1888
        case dr_open:
 
1889
      if (DoorReadyToClose(door)==true)
 
1890
         UtilizeDoor(door,CloseDoor);
 
1891
                break;
 
1892
        }
 
1893
}
 
1894
 
 
1895
//===========================================================================
 
1896
 
 
1897
/*
 
1898
===============
 
1899
=
 
1900
= DoorOpen
 
1901
=
 
1902
= Close the door after three seconds
 
1903
=
 
1904
===============
 
1905
*/
 
1906
 
 
1907
void DoorOpen (int door)
 
1908
{doorobj_t* dptr;
 
1909
 
 
1910
 dptr = doorobjlist[door];
 
1911
 dptr->ticcount += 1;
 
1912
 if ((dptr->ticcount >= OPENTICS) &&
 
1913
     (!(dptr->flags & DF_TIMED)) &&
 
1914
     (DoorReadyToClose(door)==true))
 
1915
    UtilizeDoor(door,CloseDoor);
 
1916
}
 
1917
 
 
1918
 
 
1919
 
 
1920
/*
 
1921
===============
 
1922
=
 
1923
= DoorOpening
 
1924
=
 
1925
===============
 
1926
*/
 
1927
 
 
1928
void DoorOpening (int door)
 
1929
{
 
1930
        int             area1,area2;
 
1931
        word    *map;
 
1932
        long       position;
 
1933
        int      tilex,tiley;
 
1934
 
 
1935
        position = doorobjlist[door]->position;
 
1936
        tilex = doorobjlist[door]->tilex;
 
1937
        tiley = doorobjlist[door]->tiley;
 
1938
        if (!position)
 
1939
        {
 
1940
        //
 
1941
        // door is just starting to open, so connect the areas
 
1942
        //
 
1943
                map = &MAPSPOT(tilex,tiley,0);
 
1944
 
 
1945
                if (doorobjlist[door]->vertical==true)
 
1946
                {
 
1947
                        area1 = *(map+1);
 
1948
                        area2 = *(map-1);
 
1949
                }
 
1950
                else
 
1951
                {
 
1952
                 area1 =        *(map-mapwidth);
 
1953
                 area2 =        *(map+mapwidth);
 
1954
                }
 
1955
                area1 -= AREATILE;
 
1956
                area2 -= AREATILE;
 
1957
                areaconnect[area1][area2]++;
 
1958
                areaconnect[area2][area1]++;
 
1959
                if ((insetupgame==false) && (loadedgame==false))
 
1960
                        ConnectAreas ();
 
1961
           if (areabyplayer[area1])
 
1962
           {
 
1963
         doorobjlist[door]->soundhandle=SD_PlaySoundRTP ( SD_OPENDOORSND, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
 
1964
         }
 
1965
        }
 
1966
 
 
1967
//
 
1968
// slide the door by an adaptive amount
 
1969
//
 
1970
        position += 1<<12;
 
1971
        if (position >= 0xffff)
 
1972
        {
 
1973
        //
 
1974
        // door is all the way open
 
1975
        //
 
1976
                position = 0xffff;
 
1977
                doorobjlist[door]->ticcount = 0;
 
1978
                doorobjlist[door]->action = dr_open;
 
1979
                if (doorobjlist[door] == actorat[tilex][tiley])
 
1980
                        actorat[tilex][tiley] = 0;
 
1981
        }
 
1982
 
 
1983
        doorobjlist[door]->position = position;
 
1984
        doorobjlist[door]->texture=doorobjlist[door]->basetexture+((position+1)>>13);
 
1985
}
 
1986
 
 
1987
 
 
1988
/*
 
1989
===============
 
1990
=
 
1991
= DoorClosing
 
1992
=
 
1993
===============
 
1994
*/
 
1995
 
 
1996
void DoorClosing (int door)
 
1997
{
 
1998
        int             area1,area2;
 
1999
        word       *map;
 
2000
        long       position;
 
2001
        int             tilex,tiley;
 
2002
        doorobj_t *dptr;
 
2003
 
 
2004
        dptr = doorobjlist[door];
 
2005
 
 
2006
        tilex = dptr->tilex;
 
2007
        tiley = dptr->tiley;
 
2008
 
 
2009
        position = dptr->position;
 
2010
 
 
2011
//
 
2012
// slide the door by an adaptive amount
 
2013
//
 
2014
        position -= 1<<12;
 
2015
        if (position < (0xffff >> 1))
 
2016
           ResolveDoorSpace(tilex,tiley);
 
2017
 
 
2018
 
 
2019
        if (position <= 0)
 
2020
        {
 
2021
        //
 
2022
        // door is closed all the way, so disconnect the areas
 
2023
        //
 
2024
                position = 0;
 
2025
 
 
2026
                dptr->action = dr_closed;
 
2027
 
 
2028
 
 
2029
 
 
2030
                map = &MAPSPOT(tilex,tiley,0);
 
2031
 
 
2032
      if (areabyplayer[(*map-AREATILE)])
 
2033
         {
 
2034
         dptr->soundhandle=SD_PlaySoundRTP ( SD_DOORHITSND, dptr->tilex<<16, dptr->tiley<<16 );
 
2035
         }
 
2036
 
 
2037
      if (dptr->vertical==true)
 
2038
                {
 
2039
                        area1 = *(map+1);
 
2040
                        area2 = *(map-1);
 
2041
                }
 
2042
                else
 
2043
                {
 
2044
                        area1 = *(map-mapwidth);
 
2045
                        area2 = *(map+mapwidth);
 
2046
                }
 
2047
                area1 -= AREATILE;
 
2048
                area2 -= AREATILE;
 
2049
                areaconnect[area1][area2]--;
 
2050
                areaconnect[area2][area1]--;
 
2051
 
 
2052
                ConnectAreas ();
 
2053
   }
 
2054
 
 
2055
        dptr->position = position;
 
2056
        dptr->texture=dptr->basetexture+((position+1)>>13);
 
2057
}
 
2058
 
 
2059
/*
 
2060
===============
 
2061
=
 
2062
= IsMaskedWall
 
2063
=
 
2064
===============
 
2065
*/
 
2066
 
 
2067
int IsMaskedWall (int tilex, int tiley)
 
2068
{
 
2069
        int map;
 
2070
 
 
2071
        if (IsPlatform(tilex,tiley))
 
2072
                return 1;
 
2073
 
 
2074
        map=MAPSPOT(tilex,tiley,0);
 
2075
 
 
2076
        if ((map>=157) && (map<=160))
 
2077
                return 1;
 
2078
 
 
2079
        if ((map>=162) && (map<=179))
 
2080
                return 1;
 
2081
 
 
2082
        if (M_ISMWALL(tilex,tiley))
 
2083
      return 1;
 
2084
 
 
2085
        return 0;
 
2086
}
 
2087
 
 
2088
/*
 
2089
===============
 
2090
=
 
2091
= SpawnMaskedWall
 
2092
=
 
2093
===============
 
2094
*/
 
2095
 
 
2096
 
 
2097
void SpawnMaskedWall (int tilex, int tiley, int which, int flags)
 
2098
{word *map;
 
2099
 int area1, area2;
 
2100
 int up,dn,lt,rt;
 
2101
 int himask;
 
2102
 boolean sidepic;
 
2103
 int side, middle, above, bottom;
 
2104
 maskedwallobj_t * lastmaskobj;
 
2105
 boolean metal;
 
2106
 int maskedstart;
 
2107
 int abovemaskedwallstart;
 
2108
 int swallstart;
 
2109
 
 
2110
        himask=W_GetNumForName("HMSKSTRT")+1;
 
2111
   maskedstart=W_GetNumForName("MASKSTRT");
 
2112
   abovemaskedwallstart=W_GetNumForName("ABVMSTRT");
 
2113
   swallstart=W_GetNumForName("SIDESTRT");
 
2114
 
 
2115
        maskobjlist[maskednum]=(maskedwallobj_t*)Z_LevelMalloc(sizeof(maskedwallobj_t),PU_LEVELSTRUCT,NULL);
 
2116
        memset(maskobjlist[maskednum],0,sizeof(maskedwallobj_t));
 
2117
        lastmaskobj=maskobjlist[maskednum];
 
2118
 
 
2119
   sidepic=true;
 
2120
 
 
2121
        lastmaskobj->tilex = tilex;
 
2122
        lastmaskobj->tiley = tiley;
 
2123
        lastmaskobj->which = MWALL;
 
2124
        up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
 
2125
        dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
 
2126
        lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
 
2127
        rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
 
2128
 
 
2129
   if (IsMaskedWall(tilex,tiley-1)) up=2;
 
2130
   else if (IsWall(tilex,tiley-1)) up=1;
 
2131
   else up=0;
 
2132
 
 
2133
   if (IsMaskedWall(tilex,tiley+1)) dn=2;
 
2134
   else if (IsWall(tilex,tiley+1)) dn=1;
 
2135
   else dn=0;
 
2136
 
 
2137
   if (IsMaskedWall(tilex-1,tiley)) lt=2;
 
2138
   else if (IsWall(tilex-1,tiley)) lt=1;
 
2139
   else lt=0;
 
2140
 
 
2141
   if (IsMaskedWall(tilex+1,tiley)) rt=2;
 
2142
   else if (IsWall(tilex+1,tiley)) rt=1;
 
2143
   else rt=0;
 
2144
 
 
2145
        if ((up==1) && (dn==1))
 
2146
                lastmaskobj->vertical = true;
 
2147
        else if ((lt==1) && (rt==1))
 
2148
                lastmaskobj->vertical = false;
 
2149
        else if ((up>0) && (dn>0))
 
2150
                lastmaskobj->vertical = true;
 
2151
        else if ((lt>0) && (rt>0))
 
2152
                lastmaskobj->vertical = false;
 
2153
        else if (up>0)
 
2154
                lastmaskobj->vertical = true;
 
2155
        else if (dn>0)
 
2156
                lastmaskobj->vertical = true;
 
2157
        else if (lt>0)
 
2158
                lastmaskobj->vertical = false;
 
2159
        else if (rt>0)
 
2160
                lastmaskobj->vertical = false;
 
2161
 
 
2162
        tilemap[tilex][tiley] = maskednum | 0xc000;
 
2163
        map = &MAPSPOT(tilex,tiley,0);
 
2164
 
 
2165
        if (lastmaskobj->vertical==true)
 
2166
                {
 
2167
                area1 = *(map+1);
 
2168
                area2 = *(map-1);
 
2169
      area1 -= AREATILE;
 
2170
                area2 -= AREATILE;
 
2171
                if (lt==0 && rt==0)
 
2172
                        {
 
2173
                        areaconnect[area1][area2]++;
 
2174
                        areaconnect[area2][area1]++;
 
2175
                        }
 
2176
                }
 
2177
        else
 
2178
                {
 
2179
                area1 = *(map-mapwidth);
 
2180
                area2 = *(map+mapwidth);
 
2181
      area1 -= AREATILE;
 
2182
                area2 -= AREATILE;
 
2183
                if (up==0 && dn==0)
 
2184
                        {
 
2185
                        areaconnect[area1][area2]++;
 
2186
                        areaconnect[area2][area1]++;
 
2187
                        }
 
2188
                }
 
2189
        lastmaskobj->flags=flags;
 
2190
 
 
2191
   if (IsPlatform(tilex,tiley))
 
2192
      {
 
2193
      if (MAPSPOT(tilex,tiley,0)==21)
 
2194
         {
 
2195
         metal=true;
 
2196
                        actorat[tilex][tiley]=0;
 
2197
         }
 
2198
      else
 
2199
         metal=false;
 
2200
      }
 
2201
 
 
2202
 
 
2203
 
 
2204
   switch (which)
 
2205
      {
 
2206
      case mw_peephole:
 
2207
 
 
2208
      //#if (SHAREWARE == 1)
 
2209
         side = W_GetNumForName("SIDE21");
 
2210
         middle = W_GetNumForName("ABOVEM4A") ;
 
2211
         above  = W_GetNumForName("ABOVEM4") ;
 
2212
      /*
 
2213
      #else
 
2214
         side   = W_GetNumForName("SIDE16");
 
2215
         middle = W_GetNumForName("ABOVEM3A") ;
 
2216
         above  = W_GetNumForName("ABOVEM2A") ;
 
2217
 
 
2218
      #endif
 
2219
      */
 
2220
         bottom = W_GetNumForName("PEEPMASK");
 
2221
         break;
 
2222
 
 
2223
 
 
2224
      case mw_dogwall:
 
2225
 
 
2226
         side = W_GetNumForName("SIDE21");
 
2227
         above  = W_GetNumForName("ABOVEM4") ;
 
2228
 
 
2229
   #if (SHAREWARE == 1)
 
2230
         middle = W_GetNumForName("ABOVEM4A") ;
 
2231
   #else
 
2232
         middle = W_GetNumForName("ABOVEM9") ;
 
2233
 
 
2234
   #endif
 
2235
         bottom = W_GetNumForName("DOGMASK");
 
2236
         break;
 
2237
 
 
2238
      case mw_multi1:
 
2239
 
 
2240
  /*
 
2241
      #if (SHAREWARE == 1)
 
2242
         side = W_GetNumForName("SIDE21");
 
2243
         middle = W_GetNumForName("ABOVEM4A") ;
 
2244
         above  = W_GetNumForName("ABOVEM4") ;
 
2245
 
 
2246
      #else
 
2247
  */
 
2248
         //side   = W_GetNumForName("SIDE23") ;
 
2249
         side   = W_GetNumForName("SIDE21") ;
 
2250
         middle = W_GetNumForName("ABOVEM5A") ;
 
2251
         above  = W_GetNumForName("ABOVEM5") ;
 
2252
 
 
2253
     // #endif
 
2254
 
 
2255
         bottom = W_GetNumForName("MULTI1");
 
2256
         break;
 
2257
 
 
2258
      case mw_multi2:
 
2259
      /*
 
2260
      #if (SHAREWARE == 1)
 
2261
         side = W_GetNumForName("SIDE21");
 
2262
         middle = W_GetNumForName("ABOVEM4A");
 
2263
         above  = W_GetNumForName("ABOVEM4") ;
 
2264
 
 
2265
      #else
 
2266
      */
 
2267
         //side   = W_GetNumForName("SIDE23") ;
 
2268
         side   = W_GetNumForName("SIDE21") ;
 
2269
         middle = W_GetNumForName("ABOVEM5B");
 
2270
         above  = W_GetNumForName("ABOVEM5") ;
 
2271
 
 
2272
 
 
2273
      //#endif
 
2274
 
 
2275
         bottom = W_GetNumForName("MULTI2");
 
2276
         break;
 
2277
 
 
2278
      case mw_multi3:
 
2279
 
 
2280
      /*
 
2281
      #if (SHAREWARE == 1)
 
2282
         side = W_GetNumForName("SIDE21");
 
2283
         middle = W_GetNumForName("ABOVEM4A") ;
 
2284
         above  = W_GetNumForName("ABOVEM4")  ;
 
2285
 
 
2286
      #else
 
2287
      */
 
2288
         //side   = W_GetNumForName("SIDE23") ;
 
2289
         side   = W_GetNumForName("SIDE21") ;
 
2290
         middle = W_GetNumForName("ABOVEM5C") ;
 
2291
         above  = W_GetNumForName("ABOVEM5")  ;
 
2292
 
 
2293
 
 
2294
      //#endif
 
2295
 
 
2296
         bottom = W_GetNumForName("MULTI3");
 
2297
         break;
 
2298
 
 
2299
      case mw_singlepane:
 
2300
 
 
2301
   //   #if (SHAREWARE == 1)
 
2302
         side = W_GetNumForName("SIDE21");
 
2303
 
 
2304
   //   #else
 
2305
   //      side   = W_GetNumForName("SIDE22") ;
 
2306
   //   #endif
 
2307
 
 
2308
         middle = W_GetNumForName("ABOVEM4A") ;
 
2309
         above  = W_GetNumForName("ABOVEM4")  ;
 
2310
         bottom = W_GetNumForName("MASKED4");
 
2311
         break;
 
2312
 
 
2313
      case mw_normal1:
 
2314
         side = W_GetNumForName("SIDE21");
 
2315
 
 
2316
 
 
2317
     // #if (SHAREWARE == 1)
 
2318
         middle = W_GetNumForName("ABOVEM4A") ;
 
2319
         above  = W_GetNumForName("ABOVEM4")  ;
 
2320
 
 
2321
      //#else
 
2322
       //  middle = W_GetNumForName("ABOVEM1A") ;
 
2323
       //  above  = W_GetNumForName("ABOVEM1")  ;
 
2324
 
 
2325
 
 
2326
      //#endif
 
2327
 
 
2328
         bottom = W_GetNumForName("MASKED1");
 
2329
         break;
 
2330
 
 
2331
      case mw_normal2:
 
2332
         side = W_GetNumForName("SIDE21");
 
2333
 
 
2334
      //#if (SHAREWARE == 1)
 
2335
         middle = W_GetNumForName("ABOVEM4A") ;
 
2336
         above  = W_GetNumForName("ABOVEM4")  ;
 
2337
 
 
2338
      //#else
 
2339
      //   middle = W_GetNumForName("ABOVEM2A") ;
 
2340
      //   above  = W_GetNumForName("ABOVEM2")  ;
 
2341
 
 
2342
      //#endif
 
2343
 
 
2344
         bottom = W_GetNumForName("MASKED2");
 
2345
         break;
 
2346
 
 
2347
      case mw_normal3:
 
2348
         side = W_GetNumForName("SIDE21");
 
2349
 
 
2350
      //#if (SHAREWARE == 1)
 
2351
         middle = W_GetNumForName("ABOVEM4A") ;
 
2352
         above  = W_GetNumForName("ABOVEM4")  ;
 
2353
 
 
2354
      //#else
 
2355
      //   middle = W_GetNumForName("ABOVEM3A") ;
 
2356
      //   above  = W_GetNumForName("ABOVEM3")  ;
 
2357
 
 
2358
      //#endif
 
2359
 
 
2360
         bottom = W_GetNumForName("MASKED3");
 
2361
         break;
 
2362
 
 
2363
      case mw_exitarch:
 
2364
 
 
2365
         side = W_GetNumForName("SIDE21");
 
2366
 
 
2367
      //#if (SHAREWARE == 1)
 
2368
         middle = W_GetNumForName("ABOVEM4A") ;
 
2369
         above  = W_GetNumForName("ABOVEM4")  ;
 
2370
 
 
2371
      //#else
 
2372
      //   middle = W_GetNumForName("ABOVEM6A") ;
 
2373
      //   above  = W_GetNumForName("ABOVEM6")  ;
 
2374
 
 
2375
      //#endif
 
2376
 
 
2377
         bottom = W_GetNumForName("EXITARCH");
 
2378
         break;
 
2379
 
 
2380
      case mw_secretexitarch:
 
2381
 
 
2382
         side = W_GetNumForName("SIDE21");
 
2383
 
 
2384
      //#if (SHAREWARE == 1)
 
2385
         middle = W_GetNumForName("ABOVEM4A") ;
 
2386
         above  = W_GetNumForName("ABOVEM4")  ;
 
2387
 
 
2388
      //#else
 
2389
      //   middle = W_GetNumForName("ABOVEM8A") ;
 
2390
      //   above  = W_GetNumForName("ABOVEM8")  ;
 
2391
 
 
2392
      //#endif
 
2393
 
 
2394
         bottom = W_GetNumForName("EXITARCA");
 
2395
         break;
 
2396
 
 
2397
      case mw_railing:
 
2398
         sidepic = false;
 
2399
         middle = -1;
 
2400
         above  = -1;
 
2401
         bottom = W_GetNumForName("RAILING");
 
2402
         break;
 
2403
 
 
2404
      case mw_hiswitchon:
 
2405
         sidepic = false;
 
2406
         middle = himask+1;
 
2407
         above = himask+3;
 
2408
         bottom = himask;
 
2409
         break;
 
2410
 
 
2411
      case mw_hiswitchoff:
 
2412
         sidepic = false;
 
2413
         middle = himask+1;
 
2414
         above = himask+2;
 
2415
         bottom = himask;
 
2416
         break;
 
2417
 
 
2418
      case mw_entrygate:
 
2419
         side = W_GetNumForName("SIDE21");
 
2420
 
 
2421
      //#if (SHAREWARE == 1)
 
2422
         //side = W_GetNumForName("SIDE21");
 
2423
         middle = W_GetNumForName("ABOVEM4A") ;
 
2424
         above  = W_GetNumForName("ABOVEM4")  ;
 
2425
 
 
2426
      //#else
 
2427
         //side   = W_GetNumForName("SIDE20") ;
 
2428
      //   middle = W_GetNumForName("ABOVEM7A") ;
 
2429
      //   above  = W_GetNumForName("ABOVEM7")  ;
 
2430
 
 
2431
 
 
2432
      //#endif
 
2433
 
 
2434
         bottom = W_GetNumForName("ENTRARCH");
 
2435
         break;
 
2436
 
 
2437
      case mw_platform1:
 
2438
         sidepic = false;
 
2439
         bottom = -1;
 
2440
         middle = -1;
 
2441
         above  = himask+10;
 
2442
         if (metal==true)
 
2443
            {
 
2444
            bottom = -1;
 
2445
            middle = -1;
 
2446
            above  = himask+15;
 
2447
            }
 
2448
         break;
 
2449
      case mw_platform2:
 
2450
         sidepic = false;
 
2451
         bottom = himask+8;
 
2452
         middle = -1;
 
2453
         above = -1;
 
2454
         if (metal==true)
 
2455
            {
 
2456
            bottom = himask+14;
 
2457
            middle = -1;
 
2458
            above = -1;
 
2459
            }
 
2460
         else
 
2461
            lastmaskobj->flags|=MW_BOTTOMFLIPPING;
 
2462
         break;
 
2463
      case mw_platform3:
 
2464
         sidepic = false;
 
2465
         bottom = himask+8;
 
2466
         middle = -1;
 
2467
         above = himask+10;
 
2468
         if (metal==true)
 
2469
            {
 
2470
            bottom = himask+14;
 
2471
            middle = -1;
 
2472
            above = himask+15;
 
2473
            }
 
2474
         else
 
2475
            lastmaskobj->flags|=MW_BOTTOMFLIPPING;
 
2476
         break;
 
2477
      case mw_platform4:
 
2478
         sidepic = false;
 
2479
         bottom = himask+12;
 
2480
         middle = himask+7;
 
2481
         above = himask+7;
 
2482
         if (metal==true)
 
2483
            {
 
2484
            bottom = -1;
 
2485
            middle = himask+15;
 
2486
            above = himask+15;
 
2487
            }
 
2488
         break;
 
2489
      case mw_platform5:
 
2490
         sidepic = false;
 
2491
         bottom = himask+12;
 
2492
         middle = himask+7;
 
2493
         above = himask+5;
 
2494
         if (metal==true)
 
2495
            {
 
2496
            bottom = -1;
 
2497
            middle = himask+15;
 
2498
            above = -1;
 
2499
            }
 
2500
         else
 
2501
            lastmaskobj->flags|=MW_TOPFLIPPING;
 
2502
         break;
 
2503
      case mw_platform6:
 
2504
         sidepic = false;
 
2505
         bottom = himask+4;
 
2506
         middle = himask+7;
 
2507
         above = himask+5;
 
2508
         if (metal==true)
 
2509
            {
 
2510
            bottom = himask+14;
 
2511
            middle = himask+15;
 
2512
            above = -1;
 
2513
            }
 
2514
         else
 
2515
            lastmaskobj->flags|=MW_TOPFLIPPING;
 
2516
         break;
 
2517
      case mw_platform7:
 
2518
         sidepic = false;
 
2519
         bottom = himask+4;
 
2520
         middle = himask+7;
 
2521
         above = himask+5;
 
2522
         if ((up==1) || (dn==1))
 
2523
            lastmaskobj->vertical=true;
 
2524
         else if ((lt==1) || (rt==1))
 
2525
            lastmaskobj->vertical=false;
 
2526
         else
 
2527
            Error("Perpendicular platform used with no wall near it\n");
 
2528
         if (metal==true)
 
2529
            {
 
2530
            bottom = himask+14;
 
2531
            middle = himask+15;
 
2532
            above = -1;
 
2533
            }
 
2534
         else
 
2535
            lastmaskobj->flags|=MW_TOPFLIPPING;
 
2536
         break;
 
2537
      }
 
2538
 
 
2539
   switch (which)
 
2540
      {
 
2541
      case mw_multi1:
 
2542
      case mw_multi2:
 
2543
      case mw_multi3:
 
2544
      case mw_singlepane:
 
2545
      case mw_normal1:
 
2546
      case mw_normal2:
 
2547
      case mw_normal3:
 
2548
         if (!(flags & MW_SHOOTABLE))
 
2549
            bottom+=9;
 
2550
         break;
 
2551
      }
 
2552
   lastmaskobj->midtexture=middle;
 
2553
   lastmaskobj->toptexture=above;
 
2554
   lastmaskobj->bottomtexture=bottom;
 
2555
 
 
2556
   if (sidepic == true)
 
2557
      {
 
2558
      lastmaskobj->sidepic=side;
 
2559
      if (lastmaskobj->vertical==true)
 
2560
         {
 
2561
         if (up==1)
 
2562
            tilemap[tilex][tiley-1] |= 0x4000;
 
2563
         if (dn==1)
 
2564
            tilemap[tilex][tiley+1] |= 0x4000;
 
2565
         }
 
2566
      else
 
2567
         {
 
2568
         if (lt==1)
 
2569
            tilemap[tilex-1][tiley] |= 0x4000;
 
2570
         if (rt==1)
 
2571
            tilemap[tilex+1][tiley] |= 0x4000;
 
2572
         }
 
2573
      }
 
2574
 
 
2575
        // Cache in the broken version
 
2576
 
 
2577
        if (lastmaskobj->flags & MW_SHOOTABLE)
 
2578
      {
 
2579
      int i;
 
2580
 
 
2581
      for (i=1;i<AMW_NUMFRAMES;i++)
 
2582
         {
 
2583
         PreCacheLump(lastmaskobj->bottomtexture+i,PU_CACHEWALLS);
 
2584
         }
 
2585
      SD_PreCacheSound(SD_GLASSBREAKSND);
 
2586
                }
 
2587
   if (sidepic==true)
 
2588
      {
 
2589
      PreCacheLump(lastmaskobj->sidepic,PU_CACHEWALLS);
 
2590
      }
 
2591
   if (lastmaskobj->bottomtexture>=0)
 
2592
      PreCacheLump(lastmaskobj->bottomtexture,PU_CACHEWALLS);
 
2593
   if (lastmaskobj->toptexture>=0)
 
2594
      PreCacheLump(lastmaskobj->toptexture,PU_CACHEWALLS);
 
2595
   if (lastmaskobj->midtexture>=0)
 
2596
      PreCacheLump(lastmaskobj->midtexture,PU_CACHEWALLS);
 
2597
        maskednum++;
 
2598
        lastmaskobj++;
 
2599
        if (maskednum==MAXMASKED)
 
2600
                Error ("Too many masked walls\n");
 
2601
}
 
2602
 
 
2603
/*
 
2604
===============
 
2605
=
 
2606
= FixMaskedWallAreaNumbers
 
2607
=
 
2608
===============
 
2609
*/
 
2610
void FixMaskedWallAreaNumbers ( void )
 
2611
{
 
2612
        int i;
 
2613
        int up,dn,lt,rt;
 
2614
        int tilex,tiley;
 
2615
 
 
2616
        for (i=0;i<maskednum;i++)
 
2617
                {
 
2618
                int tile;
 
2619
                tilex=maskobjlist[i]->tilex;
 
2620
                tiley=maskobjlist[i]->tiley;
 
2621
      tile=MAPSPOT(tilex,tiley,0)-AREATILE;
 
2622
                if ((tile<=NUMAREAS) && (tile>0))
 
2623
                   {
 
2624
         maskobjlist[i]->areanumber = tile;
 
2625
                        continue;
 
2626
                   }
 
2627
                up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
 
2628
                dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
 
2629
                lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
 
2630
                rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
 
2631
 
 
2632
 
 
2633
 
 
2634
                up = ((up>0) && (up<=NUMAREAS));
 
2635
                dn = ((dn>0) && (dn<=NUMAREAS));
 
2636
                lt = ((lt>0) && (lt<=NUMAREAS));
 
2637
                rt = ((rt>0) && (rt<=NUMAREAS));
 
2638
 
 
2639
                if (maskobjlist[i]->vertical==true)
 
2640
                        {
 
2641
                        if (rt)
 
2642
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
 
2643
                        else if (lt)
 
2644
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
 
2645
                        else if (up)
 
2646
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
 
2647
                        else if (dn)
 
2648
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
 
2649
                        else
 
2650
                                Error("FixMaskedWalls: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
 
2651
                        }
 
2652
                else
 
2653
                        {
 
2654
                        if (dn)
 
2655
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
 
2656
                        else if (up)
 
2657
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
 
2658
                        else if (rt)
 
2659
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
 
2660
                        else if (lt)
 
2661
                                MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
 
2662
                        else
 
2663
                                Error("FixMaskedWalls: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
 
2664
                        }
 
2665
                maskobjlist[i]->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
 
2666
                if ((maskobjlist[i]->areanumber <0) || (maskobjlist[i]->areanumber > NUMAREAS))
 
2667
                  Error("Bad masked wall areanumber of %d",maskobjlist[i]->areanumber);
 
2668
                }
 
2669
}
 
2670
 
 
2671
 
 
2672
/*
 
2673
===============
 
2674
=
 
2675
= CheckMaskedWall
 
2676
=
 
2677
===============
 
2678
*/
 
2679
 
 
2680
int CheckMaskedWall( maskedwallobj_t * mw )
 
2681
{
 
2682
        int result;
 
2683
 
 
2684
        result=0;
 
2685
        if (mw->flags & MW_SHOOTABLE)
 
2686
                {
 
2687
                if (mw->flags & MW_BLOCKINGCHANGES)
 
2688
         {
 
2689
         mw->flags&=~MW_BLOCKINGCHANGES;
 
2690
         mw->flags&=~MW_BLOCKING;
 
2691
         mw->flags|=MW_BOTTOMPASSABLE;
 
2692
         }
 
2693
      mw->flags&=~MW_SHOOTABLE;
 
2694
//      mw->bottomtexture++;
 
2695
      result=1;
 
2696
      }
 
2697
   return result;
 
2698
}
 
2699
 
 
2700
 
 
2701
/*
 
2702
===============
 
2703
=
 
2704
= UpdateMaskedWall
 
2705
=
 
2706
===============
 
2707
*/
 
2708
 
 
2709
int UpdateMaskedWall (int num)
 
2710
{
 
2711
   maskedwallobj_t * mw;
 
2712
   int result;
 
2713
 
 
2714
 
 
2715
   mw=maskobjlist[num];
 
2716
   result=CheckMaskedWall(mw);
 
2717
   if (result==1)
 
2718
      {
 
2719
      SpawnAnimatedMaskedWall(num);
 
2720
      if (loadedgame==false)
 
2721
              SD_PlaySoundRTP(SD_GLASSBREAKSND,mw->tilex<<16,mw->tiley<<16);
 
2722
      if (mw->flags&MW_MULTI)
 
2723
         {
 
2724
         int i;
 
2725
         int dx,dy;
 
2726
         int r;
 
2727
         maskedwallobj_t * mw2;
 
2728
 
 
2729
         dx=0;dy=0;
 
2730
         if (mw->vertical==true)
 
2731
            dy=1;
 
2732
         else
 
2733
            dx=1;
 
2734
         i=1;
 
2735
                        while (M_ISMWALL(mw->tilex+(dx*i),mw->tiley+(dy*i)))
 
2736
            {
 
2737
            int num;
 
2738
 
 
2739
            num=tilemap[mw->tilex+(dx*i)][mw->tiley+(dy*i)]&0x3ff;
 
2740
            mw2=maskobjlist[num];
 
2741
            if (!(mw2->flags&MW_MULTI))
 
2742
               break;
 
2743
            r=CheckMaskedWall(mw2);
 
2744
            if (r==1)
 
2745
               {
 
2746
               SpawnAnimatedMaskedWall(num);
 
2747
               if (loadedgame==false)
 
2748
                       SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
 
2749
               }
 
2750
            i++;
 
2751
            }
 
2752
         i=1;
 
2753
                        while (M_ISMWALL(mw->tilex-(dx*i),mw->tiley-(dy*i)))
 
2754
            {
 
2755
            int num;
 
2756
 
 
2757
            num=tilemap[mw->tilex-(dx*i)][mw->tiley-(dy*i)]&0x3ff;
 
2758
            mw2=maskobjlist[num];
 
2759
            if (!(mw2->flags&MW_MULTI))
 
2760
               break;
 
2761
            r=CheckMaskedWall(mw2);
 
2762
            if (r==1)
 
2763
               {
 
2764
               SpawnAnimatedMaskedWall(num);
 
2765
               if (loadedgame==false)
 
2766
                       SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
 
2767
               }
 
2768
            i++;
 
2769
            }
 
2770
         }
 
2771
      }
 
2772
   return result;
 
2773
}
 
2774
 
 
2775
 
 
2776
 
 
2777
/*
 
2778
============================
 
2779
=
 
2780
= ExecuteElevatorStopActions
 
2781
=
 
2782
============================
 
2783
*/
 
2784
 
 
2785
 
 
2786
void ExecuteElevatorStopActions(elevator_t *eptr, int teleport_location,
 
2787
                                int desttilex,int desttiley)
 
2788
   {
 
2789
   eptr->state = ev_doorclosing;
 
2790
   eptr->doorclosing = eptr->doortoopen;
 
2791
   doorobjlist[eptr->doortoopen]->flags &= ~DF_ELEVLOCKED;
 
2792
   OpenDoor(eptr->doortoopen);
 
2793
   SD_PlaySoundRTP(SD_ELEVATORENDSND,desttilex,desttiley);
 
2794
   Teleport(eptr,teleport_location);
 
2795
   eptr->ticcount = OPENTICS;
 
2796
   eptr->doortoopen = -1;
 
2797
   if (MISCVARS->elevatormusicon == true)
 
2798
      {
 
2799
      MU_StartSong(song_level);
 
2800
      MU_RestoreSongPosition();
 
2801
      MISCVARS->elevatormusicon = false;
 
2802
 
 
2803
      }
 
2804
   }
 
2805
 
 
2806
 
 
2807
boolean PlayerInElevator(elevator_t *eptr)
 
2808
   {
 
2809
   if (eptr->state == ev_mts)
 
2810
      {
 
2811
      if ((eptr->dx == player->tilex) && (eptr->dy == player->tiley))
 
2812
         return true;
 
2813
      }
 
2814
   else if (eptr->state == ev_mtd)
 
2815
      {
 
2816
      if ((eptr->sx == player->tilex) && (eptr->sy == player->tiley))
 
2817
         return true;
 
2818
      }
 
2819
 
 
2820
   return false;
 
2821
 
 
2822
   }
 
2823
 
 
2824
#define SHOULD_START_ELEVATOR_MUSIC(eptr)                              \
 
2825
        ((demoplayback == false) && (demorecord == false) &&           \
 
2826
         (MusicStarted() == true) &&                                   \
 
2827
         (!BATTLEMODE) && \
 
2828
         (!(player->flags & FL_GODMODE)) &&\
 
2829
         (GameRandomNumber("elevator music",0) < 25) && \
 
2830
         (PlayerInElevator(eptr))                                      \
 
2831
        )                                                              \
 
2832
 
 
2833
 
 
2834
/*
 
2835
==========================
 
2836
=
 
2837
= SetElevatorOperationTime
 
2838
=
 
2839
==========================
 
2840
*/
 
2841
 
 
2842
 
 
2843
void SetElevatorOperationTime(elevator_t*eptr)
 
2844
   {
 
2845
   if (SHOULD_START_ELEVATOR_MUSIC(eptr))
 
2846
      {
 
2847
      MU_StoreSongPosition();
 
2848
      MU_StartSong(song_elevator);
 
2849
      MISCVARS->elevatormusicon = true;
 
2850
      eptr->ticcount = ELEVATORMUSICTIME;
 
2851
      }
 
2852
 
 
2853
   else if (AREANUMBER(eptr->sx,eptr->sy) == AREANUMBER(eptr->dx,eptr->dy))
 
2854
      eptr->ticcount = 70;
 
2855
   else
 
2856
      eptr->ticcount = 170;
 
2857
 
 
2858
   }
 
2859
 
 
2860
 
 
2861
/*
 
2862
=====================
 
2863
=
 
2864
= CheckElevatorStart
 
2865
=
 
2866
=====================
 
2867
*/
 
2868
 
 
2869
void CheckElevatorStart (elevator_t*eptr)
 
2870
   {
 
2871
   doorobj_t *dptr = doorobjlist[eptr->doorclosing];
 
2872
 
 
2873
   if (dptr->action == dr_closed)
 
2874
      {
 
2875
 
 
2876
      if (eptr->nextaction!=-1)
 
2877
         {
 
2878
         eptr->state = eptr->nextaction;
 
2879
         eptr->nextaction = -1;
 
2880
         switch (eptr->state)
 
2881
            {
 
2882
            case ev_mtd:
 
2883
               eptr->doortoopen = eptr->door2;
 
2884
               SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->sx<<16,eptr->sy<<16);
 
2885
               //eptr->doorclosing = eptr->door1;
 
2886
 
 
2887
               SetElevatorOperationTime(eptr);
 
2888
               break;
 
2889
 
 
2890
            case ev_mts:
 
2891
               eptr->doortoopen = eptr->door1;
 
2892
 
 
2893
               SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->dx<<16,eptr->dy<<16);
 
2894
 
 
2895
               SetElevatorOperationTime(eptr);
 
2896
               break;
 
2897
            }
 
2898
         }
 
2899
 
 
2900
      else if (eptr->doorclosing == eptr->door1)
 
2901
         eptr->state = ev_ras;
 
2902
 
 
2903
 
 
2904
      else if (eptr->doorclosing == eptr->door2)
 
2905
         eptr->state = ev_rad;
 
2906
 
 
2907
 
 
2908
      eptr->doorclosing = -1;
 
2909
      }
 
2910
   }
 
2911
 
 
2912
 
 
2913
/*
 
2914
=====================
 
2915
=
 
2916
= ProcessElevators
 
2917
=
 
2918
= Called from PlayLoop
 
2919
=
 
2920
=====================
 
2921
*/
 
2922
 
 
2923
void ProcessElevators (void)
 
2924
   {
 
2925
        int               ectr;
 
2926
        elevator_t *eptr;
 
2927
 
 
2928
        for (ectr = 0 ; ectr < _numelevators ; ectr++)
 
2929
      {
 
2930
      eptr = &ELEVATOR[ectr];
 
2931
                if (eptr->ticcount)
 
2932
                        eptr->ticcount --;
 
2933
                else
 
2934
         {
 
2935
         switch (eptr->state)
 
2936
            {
 
2937
            /*
 
2938
            case ev_ras:
 
2939
               break;
 
2940
 
 
2941
            case ev_rad:
 
2942
               break;
 
2943
            */
 
2944
            case ev_mts:
 
2945
               ExecuteElevatorStopActions(eptr,0,(eptr->sx << 16),(eptr->sy << 16));
 
2946
               break;
 
2947
 
 
2948
            case ev_mtd:
 
2949
               ExecuteElevatorStopActions(eptr,1,(eptr->dx << 16),(eptr->dy << 16));
 
2950
               break;
 
2951
 
 
2952
            case ev_doorclosing:
 
2953
               CheckElevatorStart(eptr);
 
2954
               break;
 
2955
            }
 
2956
         }
 
2957
      }
 
2958
   }
 
2959
 
 
2960
 
 
2961
 
 
2962
void Teleport(elevator_t*eptr,int destination)
 
2963
{statobj_t*tstat;
 
2964
 objtype*temp;
 
2965
 int startx,starty,destx,desty;
 
2966
 
 
2967
 if (destination) // move to dest
 
2968
        {startx = eptr->sx;
 
2969
         starty = eptr->sy;
 
2970
         destx = eptr->dx;
 
2971
         desty = eptr->dy;
 
2972
    tilemap[eptr->esx][eptr->esy] = (elevatorstart + 5) | 0x2000;
 
2973
 
 
2974
        }
 
2975
 else
 
2976
        {startx = eptr->dx;
 
2977
         starty = eptr->dy;
 
2978
         destx = eptr->sx;
 
2979
         desty = eptr->sy;
 
2980
         tilemap[eptr->edx][eptr->edy] = (elevatorstart + 5) | 0x2000;
 
2981
        }
 
2982
 
 
2983
 for(tstat=firstactivestat;tstat;tstat=tstat->nextactive)
 
2984
        {if ((tstat->tilex == startx) && (tstat->tiley == starty))
 
2985
                {
 
2986
                 tstat->x += ((destx - tstat->tilex) << TILESHIFT);
 
2987
                 tstat->y += ((desty - tstat->tiley) << TILESHIFT);
 
2988
                 tstat->tilex = tstat->x >> TILESHIFT;
 
2989
                 tstat->tiley = tstat->y >> TILESHIFT;
 
2990
                 tstat->visspot = &spotvis[tstat->tilex][tstat->tiley];
 
2991
                 if (sprites[startx][starty] == tstat)
 
2992
                        {sprites[startx][starty] = NULL;
 
2993
                         sprites[destx][desty] = tstat;
 
2994
 
 
2995
                        }
 
2996
 
 
2997
                }
 
2998
        }
 
2999
 
 
3000
 for(temp=firstactive;temp;temp=temp->nextactive)
 
3001
        {if ((temp->tilex == startx) && (temp->tiley == starty))
 
3002
                {temp->x += ((destx - temp->tilex) << TILESHIFT);
 
3003
                 temp->y += ((desty - temp->tiley) << TILESHIFT);
 
3004
                 temp->tilex = temp->x >> TILESHIFT;
 
3005
                 temp->tiley = temp->y >> TILESHIFT;
 
3006
                 if (temp->obclass!=inertobj)
 
3007
                         {
 
3008
                         RemoveFromArea (temp);
 
3009
                         temp->areanumber = AREANUMBER(temp->tilex,temp->tiley);
 
3010
                         MakeLastInArea (temp);
 
3011
                         }
 
3012
                 if (temp == player)
 
3013
                        SHAKETICS = 10;
 
3014
                }
 
3015
        }
 
3016
 
 
3017
 
 
3018
 
 
3019
}
 
3020
 
 
3021
 
 
3022
 
 
3023
void OperateElevatorDoor(int dnum)
 
3024
{
 
3025
 elevator_t*eptr;
 
3026
 doorobj_t *dptr,*door1,*door2;
 
3027
 
 
3028
 dptr = doorobjlist[dnum];
 
3029
 eptr = &ELEVATOR[dptr->eindex];
 
3030
 door1 = doorobjlist[eptr->door1];
 
3031
 door2 = doorobjlist[eptr->door2];
 
3032
 
 
3033
 switch(eptr->state)
 
3034
        {/*
 
3035
         case ev_mtd:               // if already on the way to request,
 
3036
                                                                                 // ignore; else, put request in
 
3037
                if (dnum == eptr->door1)
 
3038
                  {eptr->nextaction = ev_mts;
 
3039
                        //eptr->doortoopen = eptr->door1;
 
3040
         #if (DEVELOPMENT == 1)
 
3041
         #if (ELEVATORTEST == 1)
 
3042
                        Debug("\nplayer at source requesting elev %d mtd",dptr->eindex);
 
3043
                        #endif
 
3044
                        #endif
 
3045
                  }
 
3046
                break;
 
3047
 
 
3048
         case ev_mts:
 
3049
                if (dnum == eptr->door2)
 
3050
                  {eptr->nextaction = ev_mtd;
 
3051
                        //eptr->doortoopen = eptr->door2;
 
3052
         #if (DEVELOPMENT == 1)
 
3053
         #if (ELEVATORTEST == 1)
 
3054
                        Debug("\nplayer at dest requesting elev %d mts",dptr->eindex);
 
3055
                        #endif
 
3056
                        #endif
 
3057
                  }
 
3058
                break;
 
3059
         */
 
3060
         case ev_rad:                          // if ready at other place,
 
3061
                if ((dnum == eptr->door1) && (eptr->nextaction != ev_mts))  // process request, lock doors,
 
3062
 
 
3063
                        {
 
3064
         #if (DEVELOPMENT == 1)
 
3065
         #if (ELEVATORTEST == 1)
 
3066
                        Debug("\nplayer at source requesting elev %d rad",dptr->eindex);
 
3067
                        #endif
 
3068
                        #endif
 
3069
                                                                                                // start moving to current loc;
 
3070
                         SetNextAction(eptr,0);         // if already there, do nothing
 
3071
 
 
3072
                        }
 
3073
                break;
 
3074
 
 
3075
         case ev_ras:
 
3076
                if ((dnum == eptr->door2) && (eptr->nextaction != ev_mtd))
 
3077
                        {
 
3078
         #if (DEVELOPMENT == 1)
 
3079
         #if (ELEVATORTEST == 1)
 
3080
                         Debug("\nplayer at dest requesting elev %d ras",dptr->eindex);
 
3081
                        #endif
 
3082
                        #endif
 
3083
                         SetNextAction(eptr,1);
 
3084
 
 
3085
                        }
 
3086
                break;
 
3087
 
 
3088
         case ev_doorclosing:
 
3089
                if (eptr->doorclosing == dnum)      // if opening door at current loc,
 
3090
                                                                                                                // reset elev state to ready
 
3091
                  {//if (eptr->door1 == dnum)
 
3092
                        // eptr->nextaction = ev_ras;
 
3093
                        //else
 
3094
                         //eptr->nextaction = ev_rad;
 
3095
                  }
 
3096
                else                                //else prepare for movement
 
3097
                  {if ((eptr->door1 == dnum) && (eptr->nextaction != ev_mts))
 
3098
                          {
 
3099
            #if ((DEVELOPMENT == 1))
 
3100
            #if ((ELEVATORTEST == 1))
 
3101
                                Debug("\nplayer at source requesting elev %d dc",dptr->eindex);
 
3102
                                #endif
 
3103
                                #endif
 
3104
                                SetNextAction(eptr,0);
 
3105
 
 
3106
                          }
 
3107
                        else if ((eptr->door2 == dnum) && (eptr->nextaction != ev_mtd))
 
3108
                          {
 
3109
            #if ((DEVELOPMENT == 1))
 
3110
            #if ((ELEVATORTEST == 1))
 
3111
                                Debug("\nplayer at dest requesting elev %d dc",dptr->eindex);
 
3112
                                #endif
 
3113
                                #endif
 
3114
                                SetNextAction(eptr,1);
 
3115
 
 
3116
                          }
 
3117
                  }
 
3118
          break;
 
3119
 
 
3120
 
 
3121
         }
 
3122
 
 
3123
}
 
3124
 
 
3125
 
 
3126
int SetNextAction(elevator_t*eptr,int action)
 
3127
{int dn;
 
3128
 
 
3129
 if (action)
 
3130
        {if (!DoorReadyToClose(eptr->door1))
 
3131
          return false;
 
3132
 
 
3133
         eptr->nextaction = ev_mtd;
 
3134
         dn = eptr->door1;
 
3135
        }
 
3136
 else
 
3137
        {if (!DoorReadyToClose(eptr->door2))
 
3138
          return false;
 
3139
 
 
3140
         eptr->nextaction = ev_mts;
 
3141
         dn = eptr->door2;
 
3142
        }
 
3143
 eptr->state = ev_doorclosing;
 
3144
 
 
3145
 eptr->doorclosing = dn;
 
3146
 #if (DEVELOPMENT == 1)
 
3147
 #if (ELEVATORTEST == 1)
 
3148
        Debug("\nCloseDoor %d",dn);
 
3149
 #endif
 
3150
 #endif
 
3151
 if (doorobjlist[dn]->action != dr_closed)
 
3152
  CloseDoor(dn);
 
3153
 doorobjlist[dn]->flags |= DF_ELEVLOCKED;
 
3154
 
 
3155
 return true;
 
3156
}
 
3157
 
 
3158
 
 
3159
void OperateElevatorSwitch(objtype*ob,int elevnum,int checkx,int checky)
 
3160
{elevator_t*eptr;
 
3161
 doorobj_t *door1,*door2;
 
3162
 
 
3163
 eptr = &ELEVATOR[elevnum];
 
3164
 
 
3165
 if ((eptr->state == ev_mts) ||
 
3166
          (eptr->state == ev_mtd))
 
3167
        {
 
3168
    #if (DEVELOPMENT == 1)
 
3169
    #if (ELEVATORTEST == 1)
 
3170
         Debug("\nobj %d tried to use elevator %d switch while in use",ob->obclass,elevnum);
 
3171
         #endif
 
3172
         #endif
 
3173
         return;
 
3174
        }
 
3175
 
 
3176
 door1 = doorobjlist[eptr->door1];
 
3177
 door2 = doorobjlist[eptr->door2];
 
3178
 
 
3179
 if ((abs(ob->tilex-door1->tilex)<=1) && //switch at source
 
3180
          (abs(ob->tiley-door1->tiley)<=1))
 
3181
        {if (!SetNextAction(eptr,1)) // set next to dest
 
3182
                return;
 
3183
    #if (DEVELOPMENT == 1)
 
3184
    #if (ELEVATORTEST == 1)
 
3185
         Debug("\nswitch at src %d flipped",elevnum);
 
3186
         #endif
 
3187
         #endif
 
3188
         eptr->ticcount = 0;
 
3189
        }
 
3190
 else //switch at dest
 
3191
        {if (!SetNextAction(eptr,0)) // set next to src
 
3192
                return;
 
3193
    #if (DEVELOPMENT == 1)
 
3194
    #if (ELEVATORTEST == 1)
 
3195
         Debug("\nswitch at dest %d flipped",elevnum);
 
3196
         #endif
 
3197
         #endif
 
3198
         eptr->ticcount = 0;
 
3199
        }
 
3200
 
 
3201
 tilemap[checkx][checky] = (elevatorstart + 6) | 0x2000;
 
3202
 SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
 
3203
 
 
3204
}
 
3205
 
 
3206
 
 
3207
 
 
3208
 
 
3209
/*
 
3210
=====================
 
3211
=
 
3212
= MoveDoors
 
3213
=
 
3214
= Called from PlayLoop
 
3215
=
 
3216
=====================
 
3217
*/
 
3218
 
 
3219
void MoveDoors (void)
 
3220
{
 
3221
        int             door;
 
3222
 
 
3223
        for (door = 0 ; door < doornum ; door++)
 
3224
                switch (doorobjlist[door]->action)
 
3225
                {
 
3226
                case dr_open:
 
3227
                        DoorOpen (door);
 
3228
                        break;
 
3229
 
 
3230
                case dr_opening:
 
3231
                        DoorOpening(door);
 
3232
         SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
 
3233
                        break;
 
3234
 
 
3235
                case dr_closing:
 
3236
                        DoorClosing(door);
 
3237
         SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
 
3238
                        break;
 
3239
                default:
 
3240
                    ;
 
3241
                }
 
3242
}
 
3243
 
 
3244
 
 
3245
//===========================================================
 
3246
//
 
3247
//                   PUSHWALLS
 
3248
//
 
3249
//===========================================================
 
3250
 
 
3251
 
 
3252
/*
 
3253
===============
 
3254
=
 
3255
= GetAreaNumber
 
3256
=
 
3257
===============
 
3258
*/
 
3259
int GetAreaNumber ( int tilex, int tiley, int dir )
 
3260
{
 
3261
   int up,dn,lt,rt;
 
3262
 
 
3263
   up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
 
3264
   dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
 
3265
   lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
 
3266
   rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
 
3267
   if ((up<=0) || (up>NUMAREAS)) up=0;
 
3268
   if ((dn<=0) || (dn>NUMAREAS)) dn=0;
 
3269
   if ((lt<=0) || (lt>NUMAREAS)) lt=0;
 
3270
   if ((rt<=0) || (rt>NUMAREAS)) rt=0;
 
3271
        switch (dir)
 
3272
                {
 
3273
                case north:
 
3274
                        if (up)
 
3275
                                return up;
 
3276
                        else if (dn)
 
3277
                                return dn;
 
3278
                        break;
 
3279
                case south:
 
3280
                        if (dn)
 
3281
                                return dn;
 
3282
                        else if (up)
 
3283
                                return up;
 
3284
                        break;
 
3285
                case east:
 
3286
                        if (rt)
 
3287
                                return rt;
 
3288
                        else if (lt)
 
3289
                                return lt;
 
3290
                        break;
 
3291
                case west:
 
3292
                        if (lt)
 
3293
                                return lt;
 
3294
                        else if (rt)
 
3295
                                return rt;
 
3296
                        break;
 
3297
                }
 
3298
        if (up)
 
3299
                return up;
 
3300
        else if (dn)
 
3301
                return dn;
 
3302
        else if (lt)
 
3303
                return lt;
 
3304
        else if (rt)
 
3305
                return rt;
 
3306
        else
 
3307
                Error("Cannot find an area number for tile at x=%ld y=%ld\n",tilex,tiley);
 
3308
        return -1;
 
3309
}
 
3310
 
 
3311
/*
 
3312
===============
 
3313
=
 
3314
= SpawnPushWall
 
3315
=
 
3316
===============
 
3317
*/
 
3318
 
 
3319
void SpawnPushWall (int tilex, int tiley, int lock, int texture, int dir, int type)
 
3320
{
 
3321
   pwallobj_t * lastpwallobj;
 
3322
 
 
3323
        if (pwallnum==MAXPWALLS)
 
3324
                Error ("MAXPWALLS on level!");
 
3325
 
 
3326
   pwallobjlist[pwallnum]=(pwallobj_t*)Z_LevelMalloc(sizeof(pwallobj_t),PU_LEVELSTRUCT,NULL);
 
3327
   memset(pwallobjlist[pwallnum],0,sizeof(pwallobj_t));
 
3328
   lastpwallobj=pwallobjlist[pwallnum];
 
3329
 
 
3330
        lastpwallobj->x = (tilex<<16)+0x8000;
 
3331
        lastpwallobj->y = (tiley<<16)+0x8000;
 
3332
   lastpwallobj->momentumx=0;
 
3333
   lastpwallobj->momentumy=0;
 
3334
   lastpwallobj->tilex = tilex;
 
3335
   lastpwallobj->tiley = tiley;
 
3336
        lastpwallobj->lock = lock;
 
3337
        lastpwallobj->action = pw_npushed;
 
3338
        lastpwallobj->which = PWALL;
 
3339
        lastpwallobj->dir = dir;
 
3340
   lastpwallobj->num = pwallnum;
 
3341
        actorat[tilex][tiley] = (pwallobj_t*)(lastpwallobj);    // consider it a solid wall
 
3342
 
 
3343
   if ( (MAPSPOT(tilex,tiley,0)==44) ||
 
3344
        (MAPSPOT(tilex,tiley,0)==233)
 
3345
      )
 
3346
      lastpwallobj->flags=PW_DAMAGE;
 
3347
 
 
3348
        lastpwallobj->texture = texture;
 
3349
   if (!texture&0x1000)
 
3350
           PreCacheLump(texture,PU_CACHEWALLS);
 
3351
   lastpwallobj->areanumber = GetAreaNumber(tilex,tiley,lastpwallobj->dir);
 
3352
 
 
3353
   MAPSPOT (tilex, tiley, 0)=(word)(lastpwallobj->areanumber+AREATILE);
 
3354
 
 
3355
   switch(type)
 
3356
      {
 
3357
      case 0:
 
3358
      case 1:
 
3359
                case 3:
 
3360
              lastpwallobj->speed = 2;
 
3361
         break;
 
3362
      case 2:
 
3363
      case 4:
 
3364
              lastpwallobj->speed = 4;
 
3365
         break;
 
3366
      default:
 
3367
         Error("Illegal PushWall type passed into SpawnPushWall\n");
 
3368
         break;
 
3369
      }
 
3370
   if (type>2)
 
3371
      {
 
3372
      tilemap[tilex][tiley] = 0;
 
3373
           ActivateMoveWall(pwallnum);
 
3374
      }
 
3375
   else
 
3376
      {
 
3377
      tilemap[tilex][tiley] = texture|0x800;
 
3378
      if ((loadedgame==false) && (type==0))
 
3379
         gamestate.secrettotal++;
 
3380
      }
 
3381
 
 
3382
        pwallnum++;
 
3383
        lastpwallobj++;
 
3384
 
 
3385
        SD_PreCacheSoundGroup(SD_PUSHWALLSND,SD_TURBOWALLSND);
 
3386
}
 
3387
 
 
3388
 
 
3389
 
 
3390
/*
 
3391
=====================
 
3392
=
 
3393
= OperatePushWall
 
3394
=
 
3395
= The player wants to change the pushwall's direction
 
3396
=
 
3397
=====================
 
3398
*/
 
3399
void OperatePushWall (int pwall, int dir, boolean localplayer )
 
3400
{
 
3401
   pwallobj_t * pw;
 
3402
 
 
3403
   pw=pwallobjlist[pwall];
 
3404
 
 
3405
   if (pw->lock)
 
3406
                {
 
3407
      if ( localplayer )
 
3408
         {
 
3409
         // Can't push
 
3410
         AddMessage("This push wall appears to be locked...",MSG_DOOR);
 
3411
         PlayNoWaySound();
 
3412
         }
 
3413
                return;
 
3414
                }
 
3415
        switch (pw->action)
 
3416
           {
 
3417
           case pw_npushed:
 
3418
         if ((dir!=pw->dir) && (pw->dir!=nodir))
 
3419
            {
 
3420
            // Can't push
 
3421
            if ( localplayer )
 
3422
               {
 
3423
               PlayNoWaySound();
 
3424
               }
 
3425
            return;
 
3426
            }
 
3427
         else if (localplayer && (gamestate.difficulty == gd_baby))
 
3428
            AddMessage("Push Wall Activated.",MSG_GAME);
 
3429
 
 
3430
         pw->action=pw_pushing;
 
3431
         pw->dir=dir;
 
3432
         SD_PlaySoundRTP ( SD_TOUCHPLATESND, pw->x, pw->y );
 
3433
         ConnectPushWall(pwall);
 
3434
         SetupPushWall(pwall);
 
3435
           gamestate.secretcount++;
 
3436
                   break;
 
3437
           default:
 
3438
         // Can't push
 
3439
         if ( localplayer )
 
3440
            {
 
3441
            PlayNoWaySound();
 
3442
            }
 
3443
                   break;
 
3444
           }
 
3445
}
 
3446
 
 
3447
/*
 
3448
=====================
 
3449
=
 
3450
= ActivateAllPushWalls
 
3451
=
 
3452
= A Push wall has beeen activated by a touch plate
 
3453
=
 
3454
=====================
 
3455
*/
 
3456
 
 
3457
void ActivateAllPushWalls(void)
 
3458
   {
 
3459
   int i;
 
3460
 
 
3461
   for(i=0;i<pwallnum;i++)
 
3462
      {
 
3463
      if (pwallobjlist[i]->dir != nodir)
 
3464
         {
 
3465
         ActivatePushWall(i);
 
3466
         }
 
3467
      }
 
3468
   }
 
3469
 
 
3470
/*
 
3471
=====================
 
3472
=
 
3473
= ActivatePushWall
 
3474
=
 
3475
= A Push wall has beeen activated by a touch plate
 
3476
=
 
3477
=====================
 
3478
*/
 
3479
 
 
3480
void ActivatePushWall (int pwall)
 
3481
{
 
3482
   pwallobj_t * pw;
 
3483
 
 
3484
   pw=pwallobjlist[pwall];
 
3485
 
 
3486
        switch (pw->action)
 
3487
        {
 
3488
        case pw_npushed:
 
3489
      pw->action=pw_pushing;
 
3490
      ConnectPushWall(pwall);
 
3491
      SetupPushWall(pwall);
 
3492
        gamestate.secretcount++;
 
3493
                break;
 
3494
        default:
 
3495
      // Can't push
 
3496
      SD_Play( SD_BADTOUCHSND );
 
3497
                break;
 
3498
        }
 
3499
}
 
3500
 
 
3501
/*
 
3502
=====================
 
3503
=
 
3504
= ActivateMoveWall
 
3505
=
 
3506
= A Push wall has beeen activated by a touch plate
 
3507
=
 
3508
=====================
 
3509
*/
 
3510
 
 
3511
void ActivateMoveWall (int pwall)
 
3512
{
 
3513
   pwallobj_t * pw;
 
3514
 
 
3515
   pw=pwallobjlist[pwall];
 
3516
 
 
3517
        switch (pw->action)
 
3518
        {
 
3519
        case pw_npushed:
 
3520
      pw->action=pw_moving;
 
3521
      SetupPushWall(pwall);
 
3522
      break;
 
3523
        default:
 
3524
      SD_Play( SD_BADTOUCHSND );
 
3525
                break;
 
3526
        }
 
3527
}
 
3528
 
 
3529
 
 
3530
 
 
3531
/*
 
3532
===============
 
3533
=
 
3534
= ConnectPushWall
 
3535
=
 
3536
===============
 
3537
*/
 
3538
 
 
3539
void ConnectPushWall (int pwall)
 
3540
{
 
3541
        int      checkx;
 
3542
        int      checky;
 
3543
        int             area1,area2;
 
3544
        int             area3,area4;
 
3545
        word    *map;
 
3546
        pwallobj_t * pw;
 
3547
 
 
3548
        pw=pwallobjlist[pwall];
 
3549
 
 
3550
        checkx=pw->tilex;
 
3551
        checky=pw->tiley;
 
3552
        tilemap[checkx][checky] = 0;
 
3553
        map = &MAPSPOT (checkx, checky, 0);
 
3554
 
 
3555
        area1 = *(map-mapwidth);
 
3556
        area2 = *(map+mapwidth);
 
3557
        area3 =  *(map+1);
 
3558
        area4 =  *(map-1);
 
3559
 
 
3560
        area1 -= AREATILE;
 
3561
        area2 -= AREATILE;
 
3562
        area3 -= AREATILE;
 
3563
        area4 -= AREATILE;
 
3564
        if (((area1>0) && (area1<NUMAREAS)) &&
 
3565
                 ((area2>0) && (area2<NUMAREAS)))
 
3566
                {
 
3567
                areaconnect[area1][area2]++;
 
3568
                areaconnect[area2][area1]++;
 
3569
 
 
3570
                if ((insetupgame==false) && (loadedgame==false))
 
3571
                        ConnectAreas ();
 
3572
                }
 
3573
        if (((area3>0) && (area3<NUMAREAS)) &&
 
3574
                 ((area4>0) && (area4<NUMAREAS)))
 
3575
                {
 
3576
                areaconnect[area3][area4]++;
 
3577
                areaconnect[area4][area3]++;
 
3578
 
 
3579
                if ((insetupgame==false) && (loadedgame==false))
 
3580
                        ConnectAreas ();
 
3581
                }
 
3582
}
 
3583
 
 
3584
/*
 
3585
===============
 
3586
=
 
3587
= SetupPushWall
 
3588
=
 
3589
===============
 
3590
*/
 
3591
 
 
3592
void SetupPushWall (int pwall)
 
3593
{
 
3594
        pwallobj_t * pw;
 
3595
        int speed;
 
3596
 
 
3597
        pw=pwallobjlist[pwall];
 
3598
        speed=pw->speed<<PUSHWALLSPEED;
 
3599
        switch (pw->dir)
 
3600
        {
 
3601
        case north:
 
3602
                pw->momentumx=0;
 
3603
                pw->momentumy=-speed;
 
3604
                break;
 
3605
 
 
3606
        case east:
 
3607
                pw->momentumx=speed;
 
3608
                pw->momentumy=0;
 
3609
                break;
 
3610
 
 
3611
        case northeast:
 
3612
                pw->momentumx=speed;
 
3613
                pw->momentumy=-speed;
 
3614
                break;
 
3615
 
 
3616
        case southeast:
 
3617
                pw->momentumx=speed;
 
3618
                pw->momentumy=speed;
 
3619
                break;
 
3620
 
 
3621
        case south:
 
3622
                pw->momentumx=0;
 
3623
                pw->momentumy=speed;
 
3624
                break;
 
3625
 
 
3626
        case west:
 
3627
                pw->momentumx=-speed;
 
3628
                pw->momentumy=0;
 
3629
                break;
 
3630
 
 
3631
        case northwest:
 
3632
                pw->momentumx=-speed;
 
3633
                pw->momentumy=-speed;
 
3634
                break;
 
3635
 
 
3636
        case southwest:
 
3637
                pw->momentumx=-speed;
 
3638
                pw->momentumy=speed;
 
3639
                break;
 
3640
        }
 
3641
        if (pw->action==pw_pushing)
 
3642
                {
 
3643
      if (loadedgame==false)
 
3644
         pw->soundhandle=SD_PlaySoundRTP ( SD_PUSHWALLSND, pw->x, pw->y );
 
3645
      pw->state=(0x20000L/speed);
 
3646
                }
 
3647
        if (pw->action==pw_moving)
 
3648
      pw->state=(0x10000L/speed);
 
3649
}
 
3650
 
 
3651
 
 
3652
/*
 
3653
=====================
 
3654
=
 
3655
= MovePWalls
 
3656
=
 
3657
= Called from PlayLoop
 
3658
=
 
3659
=====================
 
3660
*/
 
3661
 
 
3662
void MovePWalls (void)
 
3663
{
 
3664
        int             pwall;
 
3665
 
 
3666
        for (pwall = 0 ; pwall < pwallnum ; pwall++)
 
3667
                {
 
3668
                if (pwallobjlist[pwall]->action==pw_pushing)
 
3669
                        {
 
3670
                        WallPushing (pwall);
 
3671
                        SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
 
3672
                        }
 
3673
                if (pwallobjlist[pwall]->action==pw_moving)
 
3674
                        {
 
3675
                        WallMoving (pwall);
 
3676
                        SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
 
3677
                        }
 
3678
                }
 
3679
}
 
3680
 
 
3681
 
 
3682
void ClearActorat(pwallobj_t*pw)
 
3683
{int txhigh,txlow,tyhigh,tylow;
 
3684
 int tryx,tryy,x,y;
 
3685
 int pwrad = 0x6fff;
 
3686
 
 
3687
 
 
3688
 tryx = pw->x;
 
3689
 tryy = pw->y;
 
3690
 txlow = (tryx - pwrad) >> 16;
 
3691
 txhigh = (tryx + pwrad) >> 16;
 
3692
 tylow = (tryy - pwrad) >> 16;
 
3693
 tyhigh = (tryy + pwrad) >> 16;
 
3694
 for(y=tylow;y<=tyhigh;y++)
 
3695
         for(x=txlow;x<=txhigh;x++)
 
3696
                {if (actorat[x][y] == pw)
 
3697
                        actorat[x][y] = NULL;
 
3698
                }
 
3699
}
 
3700
 
 
3701
void SetActorat(pwallobj_t*pw)
 
3702
{int txhigh,txlow,tyhigh,tylow;
 
3703
 int tryx,tryy,x,y;
 
3704
 int pwrad = 0x6fff;
 
3705
 
 
3706
 tryx = pw->x;
 
3707
 tryy = pw->y;
 
3708
 txlow = (tryx - pwrad) >> 16;
 
3709
 txhigh = (tryx + pwrad) >> 16;
 
3710
 tylow = (tryy - pwrad) >> 16;
 
3711
 tyhigh = (tryy + pwrad) >> 16;
 
3712
 
 
3713
 for(y=tylow;y<=tyhigh;y++)
 
3714
         for(x=txlow;x<=txhigh;x++)
 
3715
                actorat[x][y] = pw;
 
3716
}
 
3717
 
 
3718
/*
 
3719
=================
 
3720
=
 
3721
= FinishPushWall
 
3722
=
 
3723
=================
 
3724
*/
 
3725
void FinishPushWall (pwallobj_t * pw)
 
3726
{
 
3727
   pw->action = pw_pushed;
 
3728
   actorat[pw->tilex][pw->tiley] = (wall_t*)&walls[GetWallIndex(pw->texture)];
 
3729
   tilemap[pw->tilex][pw->tiley] = pw->texture;
 
3730
}
 
3731
 
 
3732
/*
 
3733
=================
 
3734
=
 
3735
= ResetPushWall
 
3736
=
 
3737
=================
 
3738
*/
 
3739
void ResetPushWall (pwallobj_t * pw)
 
3740
{
 
3741
   SetActorat(pw);
 
3742
   tilemap[pw->tilex][pw->tiley] = pw->texture|0x800;
 
3743
}
 
3744
 
 
3745
/*
 
3746
=================
 
3747
=
 
3748
= WallPushing
 
3749
=
 
3750
=================
 
3751
*/
 
3752
void WallPushing (int pwall)
 
3753
{
 
3754
        int      checkx,checky;
 
3755
        int      spot;
 
3756
        pwallobj_t * pw;
 
3757
 
 
3758
        pw=pwallobjlist[pwall];
 
3759
 
 
3760
   ClearActorat(pw);
 
3761
 
 
3762
        PushWallMove(pwall);
 
3763
        pw->x+=pw->momentumx;
 
3764
        pw->y+=pw->momentumy;
 
3765
 
 
3766
        pw->state--;
 
3767
 
 
3768
        checkx=pw->tilex;
 
3769
        checky=pw->tiley;
 
3770
 
 
3771
        pw->tilex=pw->x>>16;
 
3772
        pw->tiley=pw->y>>16;
 
3773
 
 
3774
        if ((pw->tilex!=checkx) || (pw->tiley!=checky))
 
3775
                {
 
3776
                int x,y;
 
3777
                int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
 
3778
 
 
3779
                if ((area<=0) || (area>NUMAREAS))
 
3780
                        {
 
3781
                        area=pw->areanumber;
 
3782
                        MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
 
3783
                        }
 
3784
                // block crossed into a new block
 
3785
                //
 
3786
                // the tile can now be walked into
 
3787
                //
 
3788
                mapseen[checkx][checky] = 0;
 
3789
                pw->areanumber = area;
 
3790
                if (pw->momentumx>0)
 
3791
                        x=1;
 
3792
                else if (pw->momentumx<0)
 
3793
                        x=-1;
 
3794
                else
 
3795
                        x=0;
 
3796
                if (pw->momentumy>0)
 
3797
                        y=1;
 
3798
                else if (pw->momentumy<0)
 
3799
                        y=-1;
 
3800
                else
 
3801
                        y=0;
 
3802
                if (tilemap[pw->tilex+x][pw->tiley+y])
 
3803
                        {
 
3804
                        pw->state=(0x8000L/(pw->speed<<PUSHWALLSPEED));
 
3805
                        }
 
3806
                if (actorat[pw->tilex+x][pw->tiley+y])
 
3807
                  ResolveDoorSpace(pw->tilex+x,pw->tiley+y);
 
3808
                }
 
3809
 
 
3810
 
 
3811
        if (pw->state==0)
 
3812
                {
 
3813
                pw->x=(pw->tilex<<16)+0x8000;
 
3814
                pw->y=(pw->tiley<<16)+0x8000;
 
3815
                spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
 
3816
                if ((spot >= 0) && (spot <= 7))
 
3817
                        {
 
3818
         pw->action = pw_npushed;
 
3819
                        pw->dir = spot;
 
3820
         ResetPushWall (pw);
 
3821
         if (pw->lock)
 
3822
                                {
 
3823
            pw->action=pw_pushing;
 
3824
                                ConnectPushWall(pwall);
 
3825
                                SetupPushWall(pwall);
 
3826
                                }
 
3827
         else
 
3828
            {
 
3829
            gamestate.secrettotal++;
 
3830
            }
 
3831
         }
 
3832
                else
 
3833
                        {
 
3834
         FinishPushWall (pw);
 
3835
                        }
 
3836
                }
 
3837
   else
 
3838
      SetActorat(pw);
 
3839
}
 
3840
 
 
3841
 
 
3842
/*
 
3843
=================
 
3844
=
 
3845
= WallMoving
 
3846
=
 
3847
=================
 
3848
*/
 
3849
void WallMoving (int pwall)
 
3850
{
 
3851
        int      checkx,checky;
 
3852
        int      spot;
 
3853
        pwallobj_t * pw;
 
3854
 
 
3855
        pw=pwallobjlist[pwall];
 
3856
 
 
3857
   ClearActorat(pw);
 
3858
 
 
3859
        PushWallMove(pwall);
 
3860
        pw->x+=pw->momentumx;
 
3861
        pw->y+=pw->momentumy;
 
3862
 
 
3863
        pw->state--;
 
3864
 
 
3865
        checkx=pw->tilex;
 
3866
        checky=pw->tiley;
 
3867
 
 
3868
        pw->tilex=pw->x>>16;
 
3869
        pw->tiley=pw->y>>16;
 
3870
 
 
3871
        if ((pw->tilex!=checkx) || (pw->tiley!=checky))
 
3872
                {
 
3873
                int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
 
3874
 
 
3875
                if ((area<=0) || (area>NUMAREAS))
 
3876
                        {
 
3877
                        area=pw->areanumber;
 
3878
                        MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
 
3879
                        }
 
3880
                // block crossed into a new block
 
3881
                //
 
3882
                // the tile can now be walked into
 
3883
                //
 
3884
                if (areabyplayer[area])
 
3885
                        {
 
3886
                        if (pw->speed==2)
 
3887
                                pw->soundhandle=SD_PlaySoundRTP ( SD_GOWALLSND, pw->x, pw->y );
 
3888
                        else
 
3889
                                pw->soundhandle=SD_PlaySoundRTP ( SD_TURBOWALLSND, pw->x, pw->y );
 
3890
                        }
 
3891
 
 
3892
                if (actorat[pw->tilex][pw->tilex])
 
3893
                  ResolveDoorSpace(pw->tilex,pw->tiley);
 
3894
                mapseen[checkx][checky] = 0;
 
3895
                pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
 
3896
                //actorat[pw->tilex][pw->tiley]=pw;
 
3897
                if ( (pw->tilex==0) || (pw->tilex==127) ||
 
3898
                          (pw->tiley==0) || (pw->tiley==127) )
 
3899
                        {
 
3900
         if (W_CheckNumForName("imfree")>=0)
 
3901
            {
 
3902
            lbm_t *LBM;
 
3903
 
 
3904
            LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("imfree"), PU_CACHE, Cvt_lbm_t, 1);
 
3905
            VL_DecompressLBM (LBM,true);
 
3906
            VW_UpdateScreen ();
 
3907
            I_Delay (2000);
 
3908
            }
 
3909
                        Error ("PushWall Attempting to escape off the edge of the map\nIt is located at x=%ld y=%ld\nI'm Free!!!!\n",
 
3910
                                          pw->tilex, pw->tiley);
 
3911
                        }
 
3912
                }
 
3913
        if (pw->state==0)
 
3914
                {
 
3915
                pw->x=(pw->tilex<<16)+0x8000;
 
3916
                pw->y=(pw->tiley<<16)+0x8000;
 
3917
                spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
 
3918
                if ((spot >= 0) && (spot <= 7))
 
3919
                        {
 
3920
                        int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
 
3921
 
 
3922
                        if ((area<=0) || (area>NUMAREAS))
 
3923
                                {
 
3924
                                area=pw->areanumber;
 
3925
                                MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
 
3926
                                }
 
3927
 
 
3928
                        if (areabyplayer[area] && (abs(spot-pw->dir)==4))
 
3929
                                SD_PlaySoundRTP ( SD_PUSHWALLHITSND, pw->x, pw->y );
 
3930
                        pw->dir = spot;
 
3931
                        }
 
3932
                SetupPushWall(pwall);
 
3933
                }
 
3934
   else
 
3935
      SetActorat(pw);
 
3936
}
 
3937
 
 
3938
 
 
3939
 
 
3940
/*
 
3941
=================
 
3942
=
 
3943
= SavePushWalls
 
3944
=
 
3945
=================
 
3946
*/
 
3947
void SavePushWalls(byte ** buf, int * sz)
 
3948
{
 
3949
  int unitsize;
 
3950
  pwallobj_t * pw;
 
3951
  byte * bufptr;
 
3952
  int i;
 
3953
  int size;
 
3954
 
 
3955
  if (pwallnum==0)
 
3956
          {
 
3957
          *sz=0;
 
3958
          *buf=SafeMalloc(16);
 
3959
          return;
 
3960
          }
 
3961
  pw=pwallobjlist[0];
 
3962
  unitsize=0;
 
3963
  unitsize+=sizeof(pw->state);
 
3964
  unitsize+=sizeof(pw->x);
 
3965
  unitsize+=sizeof(pw->y);
 
3966
  unitsize+=sizeof(pw->dir);
 
3967
  unitsize+=sizeof(pw->speed);
 
3968
  unitsize+=sizeof(pw->action);
 
3969
 
 
3970
  *sz=pwallnum*unitsize;
 
3971
 
 
3972
  *buf=SafeMalloc(*sz);
 
3973
  bufptr=*buf;
 
3974
 
 
3975
  for (i=0;i<pwallnum;i++)
 
3976
     {
 
3977
     pw=pwallobjlist[i];
 
3978
     size=sizeof(pw->state);
 
3979
     memcpy(bufptr,&(pw->state),size);
 
3980
     bufptr+=size;
 
3981
 
 
3982
     size=sizeof(pw->x);
 
3983
     memcpy(bufptr,&(pw->x),size);
 
3984
     bufptr+=size;
 
3985
 
 
3986
     size=sizeof(pw->y);
 
3987
     memcpy(bufptr,&(pw->y),size);
 
3988
     bufptr+=size;
 
3989
 
 
3990
     size=sizeof(pw->dir);
 
3991
     memcpy(bufptr,&(pw->dir),size);
 
3992
     bufptr+=size;
 
3993
 
 
3994
     size=sizeof(pw->speed);
 
3995
     memcpy(bufptr,&(pw->speed),size);
 
3996
     bufptr+=size;
 
3997
 
 
3998
     size=sizeof(pw->action);
 
3999
     memcpy(bufptr,&(pw->action),size);
 
4000
     bufptr+=size;
 
4001
     }
 
4002
}
 
4003
 
 
4004
/*
 
4005
=================
 
4006
=
 
4007
= LoadPushWalls
 
4008
=
 
4009
=================
 
4010
*/
 
4011
void LoadPushWalls(byte * bufptr, int sz)
 
4012
{
 
4013
  int unitsize;
 
4014
  pwallobj_t * pw;
 
4015
  pwallobj_t new;
 
4016
  int i;
 
4017
  int num;
 
4018
  int size;
 
4019
  int area;
 
4020
 
 
4021
  if (sz==0)
 
4022
     return;
 
4023
  SetupPushWalls();
 
4024
  pw=pwallobjlist[0];
 
4025
  unitsize=0;
 
4026
  unitsize+=sizeof(pw->state);
 
4027
  unitsize+=sizeof(pw->x);
 
4028
  unitsize+=sizeof(pw->y);
 
4029
  unitsize+=sizeof(pw->dir);
 
4030
  unitsize+=sizeof(pw->speed);
 
4031
  unitsize+=sizeof(pw->action);
 
4032
 
 
4033
  num=sz/unitsize;
 
4034
  if (pwallnum!=num)
 
4035
     Error("Different number of Push Walls when trying to load a game\npwallnum=%ld num=%ld",pwallnum,num);
 
4036
 
 
4037
  for (i=0;i<pwallnum;i++)
 
4038
     {
 
4039
     pw=pwallobjlist[i];
 
4040
 
 
4041
     size=sizeof(new.state);
 
4042
     memcpy(&(new.state),bufptr,size);
 
4043
     bufptr+=size;
 
4044
 
 
4045
     size=sizeof(new.x);
 
4046
     memcpy(&(new.x),bufptr,size);
 
4047
     bufptr+=size;
 
4048
 
 
4049
     size=sizeof(new.y);
 
4050
     memcpy(&(new.y),bufptr,size);
 
4051
     bufptr+=size;
 
4052
 
 
4053
     size=sizeof(new.dir);
 
4054
     memcpy(&(new.dir),bufptr,size);
 
4055
     bufptr+=size;
 
4056
 
 
4057
     size=sizeof(new.speed);
 
4058
     memcpy(&(new.speed),bufptr,size);
 
4059
     bufptr+=size;
 
4060
 
 
4061
     size=sizeof(new.action);
 
4062
     memcpy(&(new.action),bufptr,size);
 
4063
     bufptr+=size;
 
4064
 
 
4065
          actorat[pw->tilex][pw->tiley] = 0;
 
4066
     mapseen[pw->tilex][pw->tiley] = 0;
 
4067
 
 
4068
     new.tilex=new.x>>16;
 
4069
     new.tiley=new.y>>16;
 
4070
 
 
4071
     if ((new.tilex!=pw->tilex) || (new.tiley!=pw->tiley))
 
4072
        {
 
4073
        ClearActorat(pw);
 
4074
        tilemap[pw->tilex][pw->tiley] = 0;
 
4075
        if (pw->state!=pw_moving)
 
4076
           {
 
4077
#if 0
 
4078
           if (pw->dir==nodir)
 
4079
              {
 
4080
              if (tilemap[pw->tilex+1][pw->tiley]==0)
 
4081
                 pw->dir=east;
 
4082
              else if (tilemap[pw->tilex-1][pw->tiley]==0)
 
4083
                 pw->dir=west;
 
4084
              else if (tilemap[pw->tilex][pw->tiley+1]==0)
 
4085
                 pw->dir=south;
 
4086
              else
 
4087
                 pw->dir=north;
 
4088
              }
 
4089
#endif
 
4090
           ConnectPushWall(i);
 
4091
           }
 
4092
        }
 
4093
 
 
4094
//   fixup area if needed
 
4095
 
 
4096
     area = MAPSPOT(new.tilex,new.tiley,0)-AREATILE;
 
4097
     if ((area<=0) || (area>NUMAREAS))
 
4098
        {
 
4099
        MAPSPOT (new.tilex, new.tiley, 0)=(word)(pw->areanumber+AREATILE);
 
4100
        }
 
4101
 
 
4102
     pw->tilex=new.tilex;
 
4103
     pw->tiley=new.tiley;
 
4104
     pw->x=new.x;
 
4105
     pw->y=new.y;
 
4106
     pw->action=new.action;
 
4107
     pw->dir=new.dir;
 
4108
     pw->speed=new.speed;
 
4109
     SetupPushWall(i);
 
4110
     pw->state=new.state;
 
4111
 
 
4112
     pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
 
4113
 
 
4114
     if (pw->action==pw_pushed)
 
4115
        {
 
4116
        FinishPushWall (pw);
 
4117
        }
 
4118
     else if (pw->action==pw_npushed)
 
4119
        {
 
4120
        ResetPushWall (pw);
 
4121
        }
 
4122
     else
 
4123
        {
 
4124
        SetActorat(pw);
 
4125
        }
 
4126
     }
 
4127
}
 
4128
 
 
4129
 
 
4130
 
 
4131
 
 
4132
 
 
4133
/*
 
4134
=================
 
4135
=
 
4136
= SaveMaskedWalls
 
4137
=
 
4138
=================
 
4139
*/
 
4140
void SaveMaskedWalls(byte ** buf, int * size)
 
4141
{
 
4142
  int unitsize;
 
4143
  maskedwallobj_t * mw;
 
4144
  byte * bufptr;
 
4145
  int i;
 
4146
  int sz;
 
4147
 
 
4148
  if (maskednum==0)
 
4149
     {
 
4150
     *size=0;
 
4151
     *buf=SafeMalloc(16);
 
4152
     return;
 
4153
     }
 
4154
  mw=maskobjlist[0];
 
4155
  unitsize=0;
 
4156
  unitsize+=sizeof(mw->flags);
 
4157
 
 
4158
  *size=maskednum*unitsize;
 
4159
 
 
4160
  *buf=SafeMalloc(*size);
 
4161
  bufptr=*buf;
 
4162
 
 
4163
  for (i=0;i<maskednum;i++)
 
4164
     {
 
4165
     mw=maskobjlist[i];
 
4166
     sz=sizeof(mw->flags);
 
4167
     memcpy(bufptr,&(mw->flags),sz);
 
4168
     bufptr+=sz;
 
4169
     }
 
4170
}
 
4171
 
 
4172
/*
 
4173
=================
 
4174
=
 
4175
= LoadMaskedWalls
 
4176
=
 
4177
=================
 
4178
*/
 
4179
void LoadMaskedWalls(byte * bufptr, int sz)
 
4180
{
 
4181
  int unitsize;
 
4182
  maskedwallobj_t * mw;
 
4183
  int i;
 
4184
  int size;
 
4185
  int num;
 
4186
 
 
4187
  if (sz==0)
 
4188
     return;
 
4189
 
 
4190
  SetupMaskedWalls();
 
4191
  FixMaskedWallAreaNumbers();
 
4192
 
 
4193
  mw=maskobjlist[0];
 
4194
  unitsize=0;
 
4195
  unitsize+=sizeof(mw->flags);
 
4196
 
 
4197
  num=sz/unitsize;
 
4198
  if (maskednum!=num)
 
4199
     Error("Different number of Masked Walls when trying to load a game\nmaskednum=%ld num=%ld",maskednum,num);
 
4200
 
 
4201
  for (i=0;i<maskednum;i++)
 
4202
     {
 
4203
     byte flags;
 
4204
 
 
4205
     mw=maskobjlist[i];
 
4206
     size=sizeof(mw->flags);
 
4207
     memcpy(&flags,bufptr,size);
 
4208
     bufptr+=size;
 
4209
     if (flags!=mw->flags)
 
4210
        UpdateMaskedWall(i);
 
4211
     if (mw->flags&MW_SWITCHON)
 
4212
        mw->toptexture--;
 
4213
     }
 
4214
}
 
4215
 
 
4216
 
 
4217
/*
 
4218
=================
 
4219
=
 
4220
= SaveDoors
 
4221
=
 
4222
=================
 
4223
*/
 
4224
 
 
4225
void SaveDoors (byte ** buf, int * size)
 
4226
{
 
4227
   int door;
 
4228
   int doorsave;
 
4229
   byte doorflag;
 
4230
   byte doorlocked;
 
4231
   signed char dooreindex;
 
4232
   short int doortime;
 
4233
   int unitsize;
 
4234
   byte *ptr;
 
4235
 
 
4236
   if (doornum==0)
 
4237
      {
 
4238
      *size=0;
 
4239
      *buf=SafeMalloc(16);
 
4240
      return;
 
4241
      }
 
4242
 
 
4243
   //
 
4244
   // Size = (int + byte + byte) * numdoors
 
4245
   //
 
4246
 
 
4247
   unitsize=0;
 
4248
   unitsize+=sizeof(doorsave);
 
4249
   unitsize+=sizeof(doorflag);
 
4250
   unitsize+=sizeof(doorlocked);
 
4251
   unitsize+=sizeof(doortime);
 
4252
   unitsize+=sizeof(dooreindex);
 
4253
 
 
4254
   *size = unitsize*doornum;
 
4255
   *buf = (byte *) SafeMalloc (*size);
 
4256
 
 
4257
   ptr = *buf;
 
4258
 
 
4259
        for (door = 0; door < doornum ; door++)
 
4260
   {
 
4261
      doorsave   = doorobjlist[door]->position & ~3;
 
4262
      doorsave  |= doorobjlist[door]->action;
 
4263
      doorflag   = doorobjlist[door]->flags;
 
4264
      doorlocked = doorobjlist[door]->lock;
 
4265
      doortime   = doorobjlist[door]->ticcount;
 
4266
      dooreindex = doorobjlist[door]->eindex;
 
4267
 
 
4268
      memcpy (ptr, &doorsave, sizeof (doorsave));
 
4269
      ptr += sizeof (doorsave);
 
4270
      memcpy (ptr, &doorflag, sizeof (doorflag));
 
4271
      ptr += sizeof (doorflag);
 
4272
      memcpy (ptr, &doorlocked, sizeof (doorlocked));
 
4273
      ptr += sizeof (doorlocked);
 
4274
      memcpy (ptr, &doortime, sizeof (doortime));
 
4275
      ptr += sizeof (doortime);
 
4276
      memcpy (ptr, &dooreindex, sizeof (dooreindex));
 
4277
      ptr += sizeof (dooreindex);
 
4278
   }
 
4279
}
 
4280
 
 
4281
 
 
4282
/*
 
4283
=================
 
4284
=
 
4285
= LoadDoors
 
4286
=
 
4287
=================
 
4288
*/
 
4289
 
 
4290
void LoadDoors (byte * buf, int size)
 
4291
{
 
4292
   int door;
 
4293
   int doorsave;
 
4294
   byte doorflag;
 
4295
   byte doorlocked;
 
4296
   signed char dooreindex;
 
4297
   short int doortime;
 
4298
   byte *ptr;
 
4299
   int unitsize;
 
4300
   int num;
 
4301
 
 
4302
   SetupDoors ();
 
4303
   FixDoorAreaNumbers();
 
4304
   ptr  = buf;
 
4305
 
 
4306
   unitsize=0;
 
4307
   unitsize+=sizeof(doorsave);
 
4308
   unitsize+=sizeof(doorflag);
 
4309
   unitsize+=sizeof(doorlocked);
 
4310
   unitsize+=sizeof(doortime);
 
4311
   unitsize+=sizeof(dooreindex);
 
4312
 
 
4313
   num=size/unitsize;
 
4314
   if (doornum!=num)
 
4315
      Error("Different number of Doors when trying to load a game\ndoornum=%ld num=%ld",doornum,num);
 
4316
 
 
4317
   for (door = 0; door < doornum; door++)
 
4318
   {
 
4319
      memcpy (&doorsave, ptr, sizeof (doorsave));
 
4320
      ptr += sizeof (doorsave);
 
4321
      memcpy (&doorflag, ptr, sizeof (doorflag));
 
4322
      ptr += sizeof (doorflag);
 
4323
      memcpy (&doorlocked, ptr, sizeof (doorlocked));
 
4324
      ptr += sizeof (doorlocked);
 
4325
      memcpy (&doortime, ptr, sizeof (doortime));
 
4326
      ptr += sizeof (doortime);
 
4327
      memcpy (&dooreindex, ptr, sizeof (dooreindex));
 
4328
      ptr += sizeof (dooreindex);
 
4329
 
 
4330
      doorobjlist[door]->action    = doorsave & 3;
 
4331
 
 
4332
      // Update Areas
 
4333
 
 
4334
      if (doorobjlist[door]->action != dr_closed)
 
4335
         DoorOpening(door);
 
4336
 
 
4337
      doorobjlist[door]->action    = doorsave & 3;
 
4338
      doorobjlist[door]->position = doorsave;
 
4339
      doorobjlist[door]->flags     = doorflag;
 
4340
      doorobjlist[door]->lock      = doorlocked;
 
4341
      doorobjlist[door]->ticcount  = doortime;
 
4342
      doorobjlist[door]->eindex    = dooreindex;
 
4343
 
 
4344
      if (doorobjlist[door]->action == dr_open)
 
4345
         doorobjlist[door]->position = 0xFFFF;
 
4346
 
 
4347
      else if (doorobjlist[door]->action == dr_closed)
 
4348
         doorobjlist[door]->position = 0;
 
4349
 
 
4350
      if (
 
4351
           (doorobjlist[door]->action == dr_closing) ||
 
4352
           (doorobjlist[door]->action == dr_closed)
 
4353
         )
 
4354
         {
 
4355
         actorat[doorobjlist[door]->tilex][doorobjlist[door]->tiley] = doorobjlist[door];
 
4356
         }
 
4357
      doorobjlist[door]->texture = doorobjlist[door]->basetexture +
 
4358
                                  ((doorobjlist[door]->position+1)>>13);
 
4359
   }
 
4360
}
 
4361
 
 
4362
 
 
4363
/*
 
4364
=====================
 
4365
=
 
4366
= SaveElevators
 
4367
=
 
4368
=
 
4369
=====================
 
4370
*/
 
4371
 
 
4372
void SaveElevators(byte ** buffer,int *size)
 
4373
{int i;
 
4374
 byte * tptr;
 
4375
 
 
4376
 *size = _numelevators*sizeof(elevator_t);
 
4377
 
 
4378
 *buffer = (byte *)SafeMalloc(*size);
 
4379
 tptr = *buffer;
 
4380
 
 
4381
 for(i=0;i<_numelevators;i++)
 
4382
  {memcpy(tptr,&ELEVATOR[i],sizeof(elevator_t));
 
4383
        tptr += sizeof(elevator_t);
 
4384
  }
 
4385
}
 
4386
 
 
4387
 
 
4388
/*
 
4389
=====================
 
4390
=
 
4391
= LoadElevators
 
4392
=
 
4393
=
 
4394
=====================
 
4395
*/
 
4396
 
 
4397
void LoadElevators(byte * buffer,int size)
 
4398
{int i;
 
4399
 
 
4400
 _numelevators = size/sizeof(elevator_t);
 
4401
 
 
4402
 
 
4403
 for(i=0;i<_numelevators;i++)
 
4404
  {memcpy(&ELEVATOR[i],buffer,sizeof(elevator_t));
 
4405
        buffer += sizeof(elevator_t);
 
4406
  }
 
4407
}
 
4408