4415 lines
90 KiB
C
Executable File
4415 lines
90 KiB
C
Executable File
/*
|
|
Copyright (C) 1994-1995 Apogee Software, Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
#include "rt_def.h"
|
|
#include "rt_sound.h"
|
|
#include "rt_door.h"
|
|
#include "rt_actor.h"
|
|
#include "rt_stat.h"
|
|
#include "_rt_door.h"
|
|
#include "z_zone.h"
|
|
#include "w_wad.h"
|
|
#include "rt_ted.h"
|
|
#include "rt_draw.h"
|
|
#include "rt_main.h"
|
|
#include "rt_playr.h"
|
|
#include "rt_util.h"
|
|
#include "rt_menu.h"
|
|
#include "rt_ted.h"
|
|
#include "rt_msg.h"
|
|
#include "rt_game.h"
|
|
#include "rt_vid.h"
|
|
#include "rt_net.h"
|
|
#include "isr.h"
|
|
#include "develop.h"
|
|
#include "rt_rand.h"
|
|
#include "engine.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
//MED
|
|
#include "memcheck.h"
|
|
|
|
/*=============================================================================
|
|
|
|
DOORS
|
|
|
|
doorobjlist[] holds most of the information for the doors
|
|
|
|
Open doors conect two areas, so sounds will travel between them and sight
|
|
will be checked when the player is in a connected area.
|
|
|
|
Areaconnect is incremented/decremented by each door. If >0 they connect
|
|
|
|
Every time a door opens or closes the areabyplayer matrix gets recalculated.
|
|
An area is true if it connects with the player's current spor.
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
// Global Variables
|
|
|
|
|
|
#define ELEVATORMUSICTIME 560
|
|
|
|
elevator_t ELEVATOR[MAXELEVATORS];
|
|
int _numelevators;
|
|
animmaskedwallobj_t* FIRSTANIMMASKEDWALL,*LASTANIMMASKEDWALL;
|
|
maskedwallobj_t* FIRSTMASKEDWALL,*LASTMASKEDWALL;
|
|
byte touchindices[MAPSIZE][MAPSIZE],lasttouch;
|
|
touchplatetype *touchplate[MAXTOUCHPLATES],*lastaction[MAXTOUCHPLATES];
|
|
|
|
byte numactions[MAXTOUCHPLATES];
|
|
int totalactions;
|
|
|
|
byte TRIGGER[MAXTOUCHPLATES];
|
|
doorobj_t *doorobjlist[MAXDOORS];
|
|
int doornum;
|
|
maskedwallobj_t *maskobjlist[MAXMASKED];
|
|
int maskednum;
|
|
|
|
pwallobj_t *pwallobjlist[MAXPWALLS];
|
|
int pwallnum;
|
|
|
|
byte areaconnect[NUMAREAS][NUMAREAS];
|
|
|
|
boolean areabyplayer[NUMAREAS];
|
|
|
|
|
|
// Local Variables
|
|
|
|
static void (*touchactions[NUMTOUCHPLATEACTIONS])(long) =
|
|
{ActivatePushWall,
|
|
ActivateMoveWall,
|
|
LinkedOpenDoor,
|
|
LinkedCloseDoor,
|
|
EnableObject,
|
|
DisableObject,
|
|
ActivateLight,
|
|
DeactivateLight};
|
|
|
|
#if ((DEVELOPMENT == 1))
|
|
#if ((LOADSAVETEST == 1))
|
|
static char*touchstrings[NUMTOUCHPLATEACTIONS] =
|
|
{"ActivatePushWall",
|
|
"ActivateMoveWall",
|
|
"LinkedOpenDoor",
|
|
"LinkedCloseDoor",
|
|
"EnableObject",
|
|
"DisableObject",
|
|
"ActivateLight",
|
|
"DeactivateLight"
|
|
};
|
|
#endif
|
|
#endif
|
|
#if ((DEVELOPMENT == 1))
|
|
#if ((ELEVATORTEST == 1))
|
|
|
|
static char*elevstring[NUMELEVATORACTIONS] =
|
|
{"ready at source",
|
|
"ready at destination",
|
|
"moving to source",
|
|
"moving to destination",
|
|
"doorclosing"
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
void UtilizeDoor (int door,void (*action)(int));
|
|
void UseDoor (int door);
|
|
void Teleport(elevator_t*eptr,int destination);
|
|
void ConnectPushWall (int pwall);
|
|
void SetupPushWall (int pwall);
|
|
void WallMoving (int pwall);
|
|
int SetNextAction(elevator_t*eptr,int action);
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= MakeMaskedWallActive
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void MakeMaskedWallActive(maskedwallobj_t* tmwall)
|
|
{if (!FIRSTMASKEDWALL)
|
|
FIRSTMASKEDWALL = tmwall;
|
|
else
|
|
{tmwall->prev = LASTMASKEDWALL;
|
|
LASTMASKEDWALL->next = tmwall;
|
|
}
|
|
LASTMASKEDWALL = tmwall;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= MakeMaskedWallInactive
|
|
=
|
|
===============
|
|
*/
|
|
|
|
|
|
void MakeMaskedWallInactive(maskedwallobj_t* tmwall)
|
|
{
|
|
if (tmwall == LASTMASKEDWALL)
|
|
LASTMASKEDWALL = tmwall->prev;
|
|
else
|
|
tmwall->next->prev = tmwall->prev;
|
|
|
|
if (tmwall == FIRSTMASKEDWALL)
|
|
FIRSTMASKEDWALL = tmwall->next;
|
|
else
|
|
tmwall->prev->next = tmwall->next;
|
|
|
|
tmwall->prev = NULL;
|
|
tmwall->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= ActivateAnimMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void ActivateAnimMaskedWall(animmaskedwallobj_t* amwall)
|
|
{
|
|
if (!FIRSTANIMMASKEDWALL)
|
|
FIRSTANIMMASKEDWALL = amwall;
|
|
else
|
|
{
|
|
amwall->prev = LASTANIMMASKEDWALL;
|
|
LASTANIMMASKEDWALL->next = amwall;
|
|
}
|
|
LASTANIMMASKEDWALL = amwall;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= DeactivateAnimMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
|
|
void DeactivateAnimMaskedWall(animmaskedwallobj_t* amwall)
|
|
{
|
|
if (amwall == LASTANIMMASKEDWALL)
|
|
LASTANIMMASKEDWALL = amwall->prev;
|
|
else
|
|
amwall->next->prev = amwall->prev;
|
|
|
|
if (amwall == FIRSTANIMMASKEDWALL)
|
|
FIRSTANIMMASKEDWALL = amwall->next;
|
|
else
|
|
amwall->prev->next = amwall->next;
|
|
|
|
amwall->prev = NULL;
|
|
amwall->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
int PlatformHeight(int tilex,int tiley)
|
|
{
|
|
int platform;
|
|
|
|
if (!IsPlatform(tilex,tiley))
|
|
return nominalheight;
|
|
|
|
platform = MAPSPOT(tilex,tiley,2);
|
|
|
|
switch(platform)
|
|
{
|
|
case 1:
|
|
return -10;
|
|
case 4:
|
|
return nominalheight;
|
|
case 5:
|
|
case 6:
|
|
return nominalheight - 64;
|
|
case 7:
|
|
return nominalheight;
|
|
case 8:
|
|
case 9:
|
|
return -10;
|
|
}
|
|
|
|
return -1000;
|
|
}
|
|
|
|
void SpawnAnimatedMaskedWall ( int num )
|
|
{
|
|
animmaskedwallobj_t * temp;
|
|
|
|
temp = (animmaskedwallobj_t *)Z_LevelMalloc(sizeof(animmaskedwallobj_t),PU_LEVELSTRUCT,NULL);
|
|
if (!temp)
|
|
Error("SpawnAnimatedMaskedWall: Failed on allocation of animated masked wall");
|
|
temp->num=num;
|
|
temp->count=AMW_NUMFRAMES;
|
|
temp->ticcount=AMW_TICCOUNT;
|
|
temp->next=NULL;
|
|
temp->prev=NULL;
|
|
ActivateAnimMaskedWall(temp);
|
|
}
|
|
|
|
void KillAnimatedMaskedWall ( animmaskedwallobj_t * temp )
|
|
{
|
|
DeactivateAnimMaskedWall(temp);
|
|
Z_Free(temp);
|
|
}
|
|
|
|
|
|
void DoAnimatedMaskedWalls ( void )
|
|
{
|
|
boolean done;
|
|
animmaskedwallobj_t * temp;
|
|
|
|
for(temp=FIRSTANIMMASKEDWALL;temp;)
|
|
{
|
|
done=false;
|
|
temp->ticcount-=tics;
|
|
while (temp->ticcount<0)
|
|
{
|
|
temp->ticcount+=AMW_TICCOUNT;
|
|
temp->count--;
|
|
maskobjlist[temp->num]->bottomtexture++;
|
|
if (temp->count==0)
|
|
{
|
|
done=true;
|
|
break;
|
|
}
|
|
}
|
|
if (done==true)
|
|
{
|
|
animmaskedwallobj_t * temp2;
|
|
|
|
temp2=temp->next;
|
|
KillAnimatedMaskedWall(temp);
|
|
temp=temp2;
|
|
}
|
|
else
|
|
temp=temp->next;
|
|
}
|
|
}
|
|
|
|
|
|
int GetIndexForAction(void (*action)(long))
|
|
{int i;
|
|
|
|
for(i=0;i<NUMTOUCHPLATEACTIONS;i++)
|
|
if (action == touchactions[i])
|
|
return i;
|
|
|
|
Error("Touchplate Action Not Matched");
|
|
return -1;
|
|
}
|
|
|
|
|
|
void SaveTouchPlates(byte ** buffer,int *size)
|
|
{int i,k;
|
|
byte * tptr;
|
|
touchplatetype *temp;
|
|
saved_touch_type dummy;
|
|
|
|
*size = sizeof(TRIGGER);
|
|
*size += sizeof(numactions);
|
|
*size += sizeof(saved_touch_type)*totalactions;
|
|
|
|
*buffer = (byte *)SafeMalloc(*size);
|
|
tptr = *buffer;
|
|
memcpy(tptr,&TRIGGER[0],sizeof(TRIGGER));
|
|
tptr+=sizeof(TRIGGER);
|
|
|
|
memcpy(tptr,&numactions[0],sizeof(numactions));
|
|
tptr+=sizeof(numactions);
|
|
|
|
#if ((DEVELOPMENT == 1))
|
|
#if (LOADSAVETEST == 1)
|
|
Debug("\n\nSAVE INFO\n");
|
|
Debug("---------");
|
|
|
|
Debug("\n\nTOUCHINDICES\n");
|
|
Debug("------------\n\n");
|
|
for(i=0;i<MAPSIZE;i++)
|
|
for(j=0;j< MAPSIZE;j++)
|
|
if (touchindices[i][j])
|
|
Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
|
|
|
|
Debug("\n\nTRIGGER: ");
|
|
for(i=0;i<(sizeof(TRIGGER)/sizeof(TRIGGER[0]));i++)
|
|
if (TRIGGER[i])
|
|
Debug("%1d",TRIGGER[i]);
|
|
Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
|
|
Debug("-------------------------\n\n");
|
|
for(i=0;i<(sizeof(numactions)/sizeof(numactions[0]));i++)
|
|
if (numactions[i])
|
|
Debug("\n %2d: %2d",i,numactions[i]);
|
|
#endif
|
|
#endif
|
|
|
|
for(i=0;i<lasttouch;i++)
|
|
{
|
|
#if ((DEVELOPMENT == 1))
|
|
#if (LOADSAVETEST == 1)
|
|
Debug("\n\nTOUCHPLATE[%2d]\n",i);
|
|
Debug("--------------\n\n");
|
|
#endif
|
|
#endif
|
|
|
|
for(k=0,temp=touchplate[i];temp;k++,temp = temp->nextaction)
|
|
{
|
|
dummy.tictime = temp->tictime;
|
|
dummy.ticcount = temp->ticcount;
|
|
dummy.triggered = temp->triggered;
|
|
dummy.done = temp->done;
|
|
dummy.complete = temp->complete;
|
|
|
|
if (temp->action)
|
|
dummy.actionindex = GetIndexForAction(temp->action);
|
|
else
|
|
dummy.actionindex = -1;
|
|
|
|
if (temp->swapaction)
|
|
dummy.swapactionindex = GetIndexForAction(temp->swapaction);
|
|
else
|
|
dummy.swapactionindex = -1;
|
|
if ((dummy.actionindex > 5) || (dummy.swapactionindex > 5)) // means whichobj holds pointer to actor
|
|
{
|
|
statobj_t *tstat;
|
|
|
|
tstat = (statobj_t*)(temp->whichobj);
|
|
dummy.whichobj = (tstat->whichstat|FL_TSTAT);
|
|
}
|
|
|
|
else if ((dummy.actionindex > 3) || (dummy.swapactionindex > 3))
|
|
|
|
{
|
|
objtype *tactor;
|
|
|
|
tactor = (objtype*)(temp->whichobj);
|
|
dummy.whichobj = (tactor->whichactor|FL_TACT);
|
|
}
|
|
|
|
else
|
|
dummy.whichobj = temp->whichobj;
|
|
|
|
#if ((DEVELOPMENT == 1))
|
|
#if (LOADSAVETEST == 1)
|
|
Debug("action node %d: tictime: %d, ticcount: %d ",k,dummy.tictime,dummy.ticcount);
|
|
if (dummy.actionindex == -1)
|
|
Debug("action: -1,");
|
|
else
|
|
Debug("action: %13s,",touchstrings[dummy.actionindex]);
|
|
|
|
if (dummy.swapactionindex == -1)
|
|
Debug("swapaction: -1,");
|
|
else
|
|
Debug("swapaction: %13s,",touchstrings[dummy.swapactionindex]);
|
|
|
|
if (dummy.whichobj & FL_TACT)
|
|
Debug("whichobj (actor): %4x\n",(dummy.whichobj & ~FL_TACT));
|
|
else
|
|
Debug("whichobj (nonactor): %4x\n",dummy.whichobj);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
memcpy(tptr,&dummy,sizeof(saved_touch_type));
|
|
tptr+=sizeof(saved_touch_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
statobj_t* GetStatForIndex(int index)
|
|
{statobj_t *temp;
|
|
|
|
for(temp = FIRSTSTAT;temp;temp=temp->statnext)
|
|
if (temp->whichstat == index)
|
|
return temp;
|
|
|
|
SoftError("\nstat not found in GetStatForIndex");
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
void LoadTouchPlates(byte * buffer, int size)
|
|
{touchplatetype *temp;
|
|
int i,savedactions,loadedactions,index=0;
|
|
saved_touch_type dummy;
|
|
|
|
savedactions = (size-sizeof(TRIGGER)-sizeof(numactions))/sizeof(saved_touch_type);
|
|
memset(touchplate,0,sizeof(touchplate));
|
|
memset(lastaction,0,sizeof(lastaction));
|
|
memset(numactions,0,sizeof(numactions));
|
|
totalactions = 0;
|
|
|
|
memcpy(&TRIGGER[0],buffer,sizeof(TRIGGER));
|
|
buffer += sizeof(TRIGGER);
|
|
|
|
memcpy(&numactions[0],buffer,sizeof(numactions));
|
|
buffer += sizeof(numactions);
|
|
|
|
for(loadedactions=0,index=0,i=0;i<savedactions;i++)
|
|
{memcpy(&dummy,buffer,sizeof(saved_touch_type));
|
|
temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
|
|
if (!temp)
|
|
Error("LoadTouchplates: Failed on allocation of touchplates %d of %d",i,savedactions);
|
|
memset(temp,0,sizeof(*temp));
|
|
|
|
temp->tictime = dummy.tictime;
|
|
temp->ticcount = dummy.ticcount;
|
|
temp->triggered = dummy.triggered;
|
|
temp->done = dummy.done;
|
|
temp->complete = dummy.complete;
|
|
|
|
if (dummy.whichobj & FL_TACT)
|
|
temp->whichobj = (long)(objlist[dummy.whichobj & ~FL_TACT]);
|
|
|
|
else if (dummy.whichobj & FL_TSTAT)
|
|
temp->whichobj = (long)(GetStatForIndex(dummy.whichobj & ~FL_TSTAT));
|
|
else
|
|
temp->whichobj = dummy.whichobj;
|
|
if (dummy.actionindex != -1)
|
|
temp->action = touchactions[dummy.actionindex];
|
|
else
|
|
temp->action = NULL;
|
|
|
|
if (dummy.swapactionindex != -1)
|
|
temp->swapaction = touchactions[dummy.swapactionindex];
|
|
else
|
|
temp->swapaction = NULL;
|
|
|
|
buffer+=sizeof(saved_touch_type);
|
|
|
|
while (!numactions[index])
|
|
index ++;
|
|
|
|
AddTouchplateAction(temp,index);
|
|
|
|
/*if (touchplate[index])
|
|
lastaction[index]->nextaction = temp;
|
|
else
|
|
touchplate[index] = temp;
|
|
lastaction[index] = temp;*/
|
|
|
|
totalactions ++;
|
|
|
|
loadedactions++;
|
|
if (loadedactions == numactions[index]) // found end of a touchplate's actions, goto next touch.
|
|
{loadedactions = 0;
|
|
index++;
|
|
}
|
|
}
|
|
|
|
|
|
#if ((DEVELOPMENT == 1))
|
|
#if (LOADSAVETEST == 1)
|
|
Debug("\n\nLOAD INFO\n");
|
|
Debug("---------");
|
|
|
|
Debug("\n\nTOUCHINDICES\n");
|
|
Debug("------------\n\n");
|
|
for(i=0;i<MAPSIZE;i++)
|
|
for(j=0;j< MAPSIZE;j++)
|
|
if (touchindices[i][j])
|
|
Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
|
|
|
|
Debug("\n\nTRIGGER: ");
|
|
for(i=0;i<(sizeof(TRIGGER)/sizeof(TRIGGER[0]));i++)
|
|
if (TRIGGER[i])
|
|
Debug("%1d",TRIGGER[i]);
|
|
Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
|
|
Debug("-------------------------\n\n");
|
|
for(i=0;i<(sizeof(numactions)/sizeof(numactions[0]));i++)
|
|
if (numactions[i])
|
|
Debug("\n %2d: %2d",i,numactions[i]);
|
|
|
|
for(i=0;i<lasttouch;i++)
|
|
{
|
|
Debug("\n\nTOUCHPLATE[%2d]\n",i);
|
|
Debug("--------------\n\n");
|
|
|
|
for(k=0,temp=touchplate[i];temp;k++,temp = temp->nextaction)
|
|
{
|
|
Debug("action node %d: tictime: %d, ticcount: %d ",k,temp->tictime,temp->ticcount);
|
|
if (!temp->action)
|
|
Debug("action: NULL,");
|
|
else
|
|
Debug("action: %13s,",touchstrings[GetIndexForAction(temp->action)]);
|
|
|
|
if (!temp->swapaction)
|
|
Debug("swapaction: NULL,");
|
|
else
|
|
Debug("swapaction: %13s,",touchstrings[GetIndexForAction(temp->swapaction)]);
|
|
|
|
Debug("whichobj: %4x\n",(int)temp->whichobj);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
SafeFree(objlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AddTouchplateAction(touchplatetype *tplate,int index)
|
|
{
|
|
if (touchplate[index])
|
|
{tplate->prevaction = lastaction[index];
|
|
lastaction[index]->nextaction = tplate;
|
|
}
|
|
else
|
|
touchplate[index] = tplate;
|
|
lastaction[index] = tplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RemoveTouchplateAction(touchplatetype *tplate,int index)
|
|
{
|
|
if (tplate == lastaction[index]) // remove from master list
|
|
lastaction[index] = tplate->prevaction;
|
|
else
|
|
tplate->nextaction->prevaction = tplate->prevaction;
|
|
|
|
if (tplate == touchplate[index])
|
|
touchplate[index] = tplate->nextaction;
|
|
else
|
|
tplate->prevaction->nextaction = tplate->nextaction;
|
|
|
|
Z_Free(tplate);
|
|
numactions[index]--;
|
|
totalactions--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Link_To_Touchplate(word touchlocx, word touchlocy, void (*maction)(long), void (*swapaction)(long), long wobj, int delaytime)
|
|
{touchplatetype *temp;
|
|
int index;
|
|
|
|
index = touchindices[touchlocx][touchlocy]-1;
|
|
|
|
temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
|
|
if (!temp)
|
|
Error("Link_To_Touchplate: Failed on allocation of touchplate\n");
|
|
memset(temp,0,sizeof(*temp));
|
|
temp->action = maction;
|
|
temp->swapaction = swapaction;
|
|
temp->whichobj = wobj;
|
|
temp->tictime = temp->ticcount = delaytime;
|
|
|
|
AddTouchplateAction(temp,index);
|
|
/*if(touchplate[index])
|
|
lastaction[index]->nextaction=temp;
|
|
else
|
|
touchplate[index] = temp;
|
|
lastaction[index] = temp;*/
|
|
numactions[index]++;
|
|
totalactions++;
|
|
}
|
|
|
|
|
|
|
|
void ClockLink (void (*saction)(long), void (*eaction)(long), long wobj,int whichclock)
|
|
{touchplatetype*temp;
|
|
|
|
|
|
// adding two actions per clock
|
|
temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
|
|
if (!temp)
|
|
Error("ClockLink: Failed on allocation of clock");
|
|
memset(temp,0,sizeof(*temp));
|
|
temp->action = saction;
|
|
temp->swapaction = eaction;
|
|
temp->whichobj = wobj;
|
|
temp->clocktype = 1;
|
|
|
|
AddTouchplateAction(temp,whichclock);
|
|
/* if(touchplate[whichclock])
|
|
lastaction[whichclock]->nextaction = temp;
|
|
else
|
|
touchplate[whichclock] = temp;
|
|
lastaction[whichclock]=temp;*/
|
|
|
|
numactions[whichclock]++;
|
|
totalactions ++;
|
|
}
|
|
|
|
|
|
void DisplayMessageForAction(touchplatetype *temp, boolean *wallmessage,
|
|
boolean *doormessage, boolean*columnmessage)
|
|
{
|
|
|
|
if ((temp->action == ActivatePushWall) ||
|
|
(temp->action == ActivateMoveWall)
|
|
)
|
|
{
|
|
if (*wallmessage == false)
|
|
{
|
|
if (temp->clocktype)
|
|
AddMessage("Time-delay wall moves.",MSG_GAME);
|
|
else
|
|
AddMessage("A wall moves.",MSG_GAME);
|
|
*wallmessage = true;
|
|
}
|
|
}
|
|
|
|
else if (temp->action == LinkedCloseDoor)
|
|
{
|
|
if (*doormessage == false)
|
|
{
|
|
if (temp->clocktype)
|
|
AddMessage("Time-delay door closes.",MSG_GAME);
|
|
else
|
|
AddMessage("A door closes.",MSG_GAME);
|
|
*doormessage = true;
|
|
}
|
|
}
|
|
|
|
else if (temp->action == LinkedOpenDoor)
|
|
{
|
|
if (*doormessage == false)
|
|
{
|
|
if (temp->clocktype)
|
|
AddMessage("Time-delay door opens.",MSG_GAME);
|
|
else
|
|
AddMessage("A door opens.",MSG_GAME);
|
|
*doormessage = true;
|
|
}
|
|
}
|
|
|
|
else if (temp->action == EnableObject)
|
|
{
|
|
objtype *tempactor = (objtype*)(temp->whichobj);
|
|
|
|
if (M_ISACTOR(tempactor) && (tempactor->obclass == pillarobj))
|
|
{
|
|
if (*columnmessage == false)
|
|
{
|
|
if (temp->clocktype)
|
|
AddMessage("Time-delay column moves.",MSG_GAME);
|
|
else
|
|
AddMessage("A column moves.",MSG_GAME);
|
|
*columnmessage = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TriggerStuff(void)
|
|
{
|
|
touchplatetype *temp;
|
|
int i,touchcomplete,j;
|
|
int playeron;
|
|
void (*tempact)(long);
|
|
boolean wallmessage,doormessage,columnmessage;
|
|
|
|
for(i=0;i<lasttouch;i++)
|
|
{
|
|
playeron = false;
|
|
for( j = 0; j < numplayers; j++ )
|
|
{
|
|
if ( i == touchindices[ PLAYER[ j ]->tilex ][ PLAYER[ j ]->tiley ] - 1 )
|
|
{
|
|
playeron = true;
|
|
break;
|
|
}
|
|
}
|
|
#if (BNACRASHPREVENT == 1)
|
|
//SetTextMode ( ); qwert
|
|
// CRASH IN SHAREWARE 'ride em cowboy' BNA FIX
|
|
// DONT ALLOW BAD touchplate ( == 0 ) see rt_playr.c
|
|
if (touchplate[i] == 0) {continue;}
|
|
#endif
|
|
|
|
if (!TRIGGER[i])
|
|
continue;
|
|
|
|
else if (touchplate[i]->complete)
|
|
{
|
|
if (!playeron)
|
|
TRIGGER[i] = 0;
|
|
continue;
|
|
}
|
|
|
|
if (touchplate[i]->done)
|
|
{
|
|
if (!playeron)
|
|
{
|
|
for(temp = touchplate[i];temp;temp = temp->nextaction)
|
|
temp->triggered=false;
|
|
TRIGGER[i] = 0;
|
|
touchplate[i]->done = false;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
wallmessage = false;
|
|
doormessage = false;
|
|
columnmessage = false;
|
|
|
|
for(temp = touchplate[i];temp;temp = temp->nextaction)
|
|
{
|
|
if (temp->action && (!temp->triggered))
|
|
{
|
|
if (!temp->ticcount)
|
|
{
|
|
temp->action(temp->whichobj);
|
|
if (temp->action == ActivateMoveWall)
|
|
{
|
|
int tilex,tiley;
|
|
|
|
tilex = pwallobjlist[temp->whichobj]->tilex;
|
|
tiley = pwallobjlist[temp->whichobj]->tiley;
|
|
tilemap[tilex][tiley] = 0;
|
|
|
|
}
|
|
if (gamestate.difficulty == gd_baby)
|
|
{
|
|
DisplayMessageForAction(temp,&wallmessage,&doormessage,&columnmessage);
|
|
}
|
|
|
|
tempact = temp->action;
|
|
temp->action = temp->swapaction;
|
|
temp->swapaction = tempact;
|
|
temp->ticcount = temp->tictime;
|
|
temp->triggered = true;
|
|
}
|
|
|
|
else
|
|
temp->ticcount --;
|
|
}
|
|
}
|
|
//done:
|
|
|
|
// check to see if any actions will ever be triggered by this
|
|
// touchplate again; if not, null touchplate out; else,
|
|
// check status of other actions
|
|
|
|
touchcomplete = 1;
|
|
for(temp = touchplate[i];temp;temp = temp->nextaction)
|
|
{
|
|
if (temp->action)
|
|
{
|
|
touchcomplete = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (touchcomplete)
|
|
touchplate[i]->complete = 1; // this touchplate is out of commission
|
|
else
|
|
{
|
|
touchplate[i]->done = true;
|
|
for(temp = touchplate[i];temp;temp = temp->nextaction)
|
|
{
|
|
if (temp->action && (!temp->triggered))
|
|
{
|
|
touchplate[i]->done = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//==================== Tile stuff ====================================
|
|
|
|
boolean CheckTile(int x, int y)
|
|
{
|
|
|
|
if ((x < 2) || (x > (MAPSIZE-1)) || (y < 2) || (y > (MAPSIZE - 1)))
|
|
return false;
|
|
|
|
if (actorat[x][y])
|
|
{objtype *check = (objtype*)(actorat[x][y]);
|
|
if (insetupgame)
|
|
return false;
|
|
if (!(M_ISACTOR(check) && (check->obclass == playerobj)))
|
|
return false;
|
|
}
|
|
if (DiskAt(x,y))
|
|
return false;
|
|
if (sprites[x][y])
|
|
return false;
|
|
if ((tilemap[x][y]) && (IsPlatform(x,y)==false))
|
|
return false;
|
|
if ((AREANUMBER(x,y)<=0) || (AREANUMBER(x,y)>NUMAREAS))
|
|
return false;
|
|
if (IsWindow(x,y))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
#define CountTile(x,y) \
|
|
{ \
|
|
if (oldarea == AREANUMBER(x,y))\
|
|
{if (CheckTile(x,y)) \
|
|
numemptytiles ++; \
|
|
\
|
|
areanumbercount++; \
|
|
if (areanumbercount == numareatiles[oldarea])\
|
|
return numemptytiles; \
|
|
} \
|
|
\
|
|
} \
|
|
|
|
|
|
int Number_of_Empty_Tiles_In_Area_Around(int x, int y)
|
|
{int roverx,rovery,areanumbercount=0,
|
|
numemptytiles=0,oldarea,i,limit,j;
|
|
|
|
oldarea = AREANUMBER(x,y);
|
|
|
|
for (i=1;;i++)
|
|
{roverx = x-i;
|
|
rovery = y-i;
|
|
|
|
CountTile(roverx,rovery);
|
|
limit = i<<1;
|
|
|
|
for(j=0;j<limit;j++)
|
|
{roverx++;
|
|
CountTile(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit;j++)
|
|
{rovery++;
|
|
CountTile(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit;j++)
|
|
{roverx--;
|
|
CountTile(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit-1;j++)
|
|
{rovery--;
|
|
CountTile(roverx,rovery);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#define CheckSet(x,y) \
|
|
{if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y))) \
|
|
{*stilex = x; \
|
|
*stiley = y; \
|
|
return; \
|
|
} \
|
|
} \
|
|
|
|
|
|
|
|
void FindEmptyTile(int *stilex, int *stiley)
|
|
{
|
|
int i,j,x,y,oldarea,roverx,rovery,limit;
|
|
|
|
oldarea = AREANUMBER(*stilex,*stiley);
|
|
|
|
x = *stilex;
|
|
y = *stiley;
|
|
|
|
if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y)))
|
|
return;
|
|
|
|
for (i=1;;i++)
|
|
{roverx = x-i;
|
|
rovery = y-i;
|
|
|
|
CheckSet(roverx,rovery);
|
|
limit = i<<1;
|
|
|
|
for(j=0;j<limit;j++)
|
|
{roverx++;
|
|
CheckSet(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit;j++)
|
|
{rovery++;
|
|
CheckSet(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit;j++)
|
|
{roverx--;
|
|
CheckSet(roverx,rovery);
|
|
}
|
|
|
|
for(j=0;j<limit-1;j++)
|
|
{rovery--;
|
|
CheckSet(roverx,rovery);
|
|
}
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
|
|
|
|
|
|
|
|
void RecursiveConnect (int areanumber)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<NUMAREAS;i++)
|
|
{
|
|
if (areaconnect[areanumber][i] && !areabyplayer[i])
|
|
{
|
|
areabyplayer[i] = true;
|
|
RecursiveConnect (i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= ConnectAreas
|
|
=
|
|
= Scans outward from playerarea, marking all connected areas
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void ConnectAreas (void)
|
|
{objtype*temp;
|
|
statobj_t*tstat;
|
|
int i;
|
|
#define MASTER_DISK(ob) ((ob->obclass == diskobj) && (ob->flags & FL_MASTER))
|
|
|
|
memset (areabyplayer,0,sizeof(areabyplayer));
|
|
for (i=0;i<numplayers;i++)
|
|
{
|
|
areabyplayer[PLAYER[i]->areanumber] = true;
|
|
RecursiveConnect (PLAYER[i]->areanumber);
|
|
}
|
|
for(temp=FIRSTACTOR;temp;temp=temp->next)
|
|
{
|
|
if (MASTER_DISK(temp))
|
|
continue;
|
|
if (!areabyplayer[temp->areanumber])
|
|
continue;
|
|
if (!(temp->flags & FL_ABP))
|
|
{temp->flags |= FL_ABP;
|
|
MakeActive(temp);
|
|
}
|
|
}
|
|
|
|
for(tstat=FIRSTSTAT;tstat;tstat=tstat->statnext)
|
|
{if (areabyplayer[tstat->areanumber])
|
|
{if (!(tstat->flags & FL_ABP))
|
|
{tstat->flags |= FL_ABP;
|
|
MakeStatActive(tstat);
|
|
}
|
|
}
|
|
else if (tstat->flags & FL_ABP)
|
|
{MakeStatInactive(tstat);
|
|
tstat->flags &= ~FL_ABP;
|
|
}
|
|
}
|
|
|
|
for(i=0;i<maskednum;i++)
|
|
{if (areabyplayer[maskobjlist[i]->areanumber])
|
|
{if (!(maskobjlist[i]->flags & MW_ABP))
|
|
{maskobjlist[i]->flags |= MW_ABP;
|
|
MakeMaskedWallActive(maskobjlist[i]);
|
|
}
|
|
}
|
|
else if (maskobjlist[i]->flags & MW_ABP)
|
|
{MakeMaskedWallInactive(maskobjlist[i]);
|
|
maskobjlist[i]->flags &= ~MW_ABP;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void InitAreas (void)
|
|
{
|
|
memset (areabyplayer,0,sizeof(areabyplayer));
|
|
memset (areaconnect,0,sizeof(areaconnect));
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= InitDoorList
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void InitDoorList (void)
|
|
{
|
|
doornum=0;
|
|
pwallnum=0;
|
|
maskednum=0;
|
|
lasttouch = 0;
|
|
numclocks=0;
|
|
|
|
memset(touchindices,0,sizeof(touchindices));
|
|
memset(touchplate,0,sizeof(touchplate));
|
|
memset(lastaction,0,sizeof(lastaction));
|
|
memset(numactions,0,sizeof(numactions));
|
|
totalactions = 0;
|
|
memset(TRIGGER,0,sizeof(TRIGGER));
|
|
memset(Clocks,0,sizeof(Clocks));
|
|
FIRSTMASKEDWALL=NULL;
|
|
LASTMASKEDWALL=NULL;
|
|
FIRSTANIMMASKEDWALL=NULL;
|
|
LASTANIMMASKEDWALL=NULL;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= IsWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int IsWall (int tilex, int tiley)
|
|
{
|
|
int map;
|
|
|
|
map=MAPSPOT(tilex,tiley,0);
|
|
|
|
if ((map>=1) && (map<=89))
|
|
return 1;
|
|
|
|
else if ((map>=106) && (map<=107))
|
|
return 1;
|
|
|
|
else if ((map>=224) && (map<=233))
|
|
return 1;
|
|
|
|
else if ((map>=242) && (map<=244))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= InitElevators
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void InitElevators(void)
|
|
{_numelevators = 0;
|
|
memset(ELEVATOR,0,sizeof(ELEVATOR));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= IsDoor
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int IsDoor (int tilex, int tiley)
|
|
{
|
|
int map;
|
|
|
|
map=MAPSPOT(tilex,tiley,0);
|
|
|
|
if ((map>=33) && (map<=35))
|
|
return 1;
|
|
|
|
if ((map>=90) && (map<=104))
|
|
return 1;
|
|
|
|
if ((map>=154) && (map<=156))
|
|
return 1;
|
|
|
|
if (M_ISDOOR(tilex,tiley))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= SpawnDoor
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void SpawnDoor (int tilex, int tiley, int lock, int texture)
|
|
{
|
|
int i;
|
|
doorobj_t * lastdoorobj;
|
|
int up,dn,lt,rt;
|
|
int abovewallstart;
|
|
int swallstart;
|
|
int basetexture;
|
|
|
|
abovewallstart=W_GetNumForName("ABVWSTRT")+1;
|
|
swallstart=W_GetNumForName("SIDESTRT")+1;
|
|
|
|
doorobjlist[doornum]=(doorobj_t*)Z_LevelMalloc(sizeof(doorobj_t),PU_LEVELSTRUCT,NULL);
|
|
if (!doorobjlist[doornum])
|
|
Error("SpawnDoor: Failed on allocation of door %d ",doornum);
|
|
memset(doorobjlist[doornum],0,sizeof(doorobj_t));
|
|
lastdoorobj=doorobjlist[doornum];
|
|
|
|
if (
|
|
( MAPSPOT(tilex,tiley,1) >= 29 ) &&
|
|
( MAPSPOT(tilex,tiley,1) <= 32 )
|
|
)
|
|
{
|
|
lock = MAPSPOT(tilex,tiley,1) - 28;
|
|
}
|
|
|
|
lastdoorobj->position = 0;
|
|
lastdoorobj->tilex = tilex;
|
|
lastdoorobj->tiley = tiley;
|
|
lastdoorobj->lock = lock;
|
|
lastdoorobj->action = dr_closed;
|
|
lastdoorobj->which = DOOR;
|
|
lastdoorobj->flags = 0;
|
|
lastdoorobj->eindex = -1;
|
|
|
|
//
|
|
// make the door space solid
|
|
//
|
|
|
|
if (loadedgame==false)
|
|
actorat[tilex][tiley] = lastdoorobj;
|
|
|
|
if (IsDoor(tilex,tiley-1)) up=2;
|
|
else if (IsWall(tilex,tiley-1)) up=1;
|
|
else up=0;
|
|
|
|
if (IsDoor(tilex,tiley+1)) dn=2;
|
|
else if (IsWall(tilex,tiley+1)) dn=1;
|
|
else dn=0;
|
|
|
|
if (IsDoor(tilex-1,tiley)) lt=2;
|
|
else if (IsWall(tilex-1,tiley)) lt=1;
|
|
else lt=0;
|
|
|
|
if (IsDoor(tilex+1,tiley)) rt=2;
|
|
else if (IsWall(tilex+1,tiley)) rt=1;
|
|
else rt=0;
|
|
|
|
if ((up==1) && (dn==1))
|
|
lastdoorobj->vertical = true;
|
|
else if ((lt==1) && (rt==1))
|
|
lastdoorobj->vertical = false;
|
|
else if ((up>0) && (dn>0))
|
|
lastdoorobj->vertical = true;
|
|
else if ((lt>0) && (rt>0))
|
|
lastdoorobj->vertical = false;
|
|
else if (up>0)
|
|
lastdoorobj->vertical = true;
|
|
else if (dn>0)
|
|
lastdoorobj->vertical = true;
|
|
else if (lt>0)
|
|
lastdoorobj->vertical = false;
|
|
else if (rt>0)
|
|
lastdoorobj->vertical = false;
|
|
|
|
switch (texture)
|
|
{
|
|
|
|
case 0:
|
|
case 8:
|
|
basetexture = W_GetNumForName("RAMDOOR1\0");
|
|
break;
|
|
|
|
case 1:
|
|
case 9:
|
|
basetexture = W_GetNumForName("DOOR2\0");
|
|
break;
|
|
|
|
|
|
case 2:
|
|
case 3:
|
|
case 13:
|
|
basetexture = W_GetNumForName("TRIDOOR1\0");
|
|
break;
|
|
|
|
case 10:
|
|
case 11:
|
|
case 14:
|
|
basetexture = W_GetNumForName("SDOOR4\0");
|
|
break;
|
|
|
|
|
|
|
|
case 12:
|
|
basetexture = W_GetNumForName("EDOOR\0");
|
|
break;
|
|
case 15:
|
|
basetexture = W_GetNumForName("SNDOOR\0");
|
|
break;
|
|
case 16:
|
|
basetexture = W_GetNumForName("SNADOOR\0");
|
|
break;
|
|
case 17:
|
|
basetexture = W_GetNumForName("SNKDOOR\0");
|
|
break;
|
|
|
|
case 18:
|
|
basetexture = W_GetNumForName("TNDOOR\0");
|
|
break;
|
|
case 19:
|
|
basetexture = W_GetNumForName("TNADOOR\0");
|
|
break;
|
|
case 20:
|
|
basetexture = W_GetNumForName("TNKDOOR\0");
|
|
break;
|
|
default:
|
|
Error("Illegal door value encountered\n");
|
|
break;
|
|
}
|
|
lastdoorobj->basetexture = basetexture;
|
|
lastdoorobj->texture = lastdoorobj->basetexture;
|
|
|
|
SD_PreCacheSoundGroup(SD_OPENDOORSND,SD_CLOSEDOORSND);
|
|
|
|
//
|
|
// make the door tile a special tile, and mark the adjacent tiles
|
|
// for door sides
|
|
//
|
|
tilemap[tilex][tiley] = doornum | 0x8000;
|
|
|
|
switch (texture)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
lastdoorobj->sidepic = W_GetNumForName("SIDE8");
|
|
lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
|
|
break;
|
|
|
|
case 15:
|
|
case 16:
|
|
case 17:
|
|
#if (SHAREWARE == 1)
|
|
lastdoorobj->sidepic = W_GetNumForName("SIDE8");
|
|
|
|
#else
|
|
lastdoorobj->sidepic = W_GetNumForName("SIDE16");
|
|
#endif
|
|
|
|
lastdoorobj->alttexture = W_GetNumForName("ABOVEW16");
|
|
break;
|
|
|
|
case 18:
|
|
case 19:
|
|
case 20:
|
|
#if (SHAREWARE == 1)
|
|
lastdoorobj->sidepic = W_GetNumForName("SIDE8");
|
|
lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
|
|
|
|
#else
|
|
lastdoorobj->sidepic = W_GetNumForName("SIDE17");
|
|
lastdoorobj->alttexture = W_GetNumForName("ABOVEW17");
|
|
|
|
#endif
|
|
|
|
break;
|
|
default:
|
|
Error("Illegal door value encountered\n");
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
if ((lock>0) && (lock<5))
|
|
lastdoorobj->sidepic = W_GetNumForName("lock1")+lock-1;
|
|
|
|
PreCacheLump(lastdoorobj->sidepic,PU_CACHEWALLS,cache_pic_t);
|
|
PreCacheLump(lastdoorobj->alttexture,PU_CACHEWALLS,cache_pic_t);
|
|
|
|
if (lastdoorobj->vertical==true)
|
|
{
|
|
if (up==1)
|
|
tilemap[tilex][tiley-1] |= 0x4000;
|
|
else if (up==2)
|
|
lastdoorobj->flags|=DF_MULTI;
|
|
if (dn==1)
|
|
tilemap[tilex][tiley+1] |= 0x4000;
|
|
else if (dn==2)
|
|
lastdoorobj->flags|=DF_MULTI;
|
|
}
|
|
else
|
|
{
|
|
if (lt==1)
|
|
tilemap[tilex-1][tiley] |= 0x4000;
|
|
else if (lt==2)
|
|
lastdoorobj->flags|=DF_MULTI;
|
|
if (rt==1)
|
|
tilemap[tilex+1][tiley] |= 0x4000;
|
|
else if (rt==2)
|
|
lastdoorobj->flags|=DF_MULTI;
|
|
}
|
|
|
|
PreCacheLump(lastdoorobj->texture,PU_CACHEWALLS,cache_pic_t);
|
|
for (i=1;i<9;i++) // only first texture is pic_t!
|
|
PreCacheLump(lastdoorobj->texture+i,PU_CACHEWALLS,cache_patch_t);
|
|
doornum++;
|
|
lastdoorobj++;
|
|
if (doornum==MAXDOORS)
|
|
Error ("Too many doors on level!");
|
|
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= MakeWideDoorVisible
|
|
=
|
|
===============
|
|
*/
|
|
void MakeWideDoorVisible ( int doornum )
|
|
{
|
|
int dx,dy;
|
|
doorobj_t * dr2;
|
|
doorobj_t * dr;
|
|
int tx,ty;
|
|
|
|
dr=doorobjlist[doornum];
|
|
|
|
dx=0;dy=0;
|
|
if (dr->vertical==true)
|
|
dy=1;
|
|
else
|
|
dx=1;
|
|
spotvis[dr->tilex][dr->tiley]=1;
|
|
tx=dr->tilex+dx;
|
|
ty=dr->tiley+dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
spotvis[tx][ty]=1;
|
|
|
|
tx+=dx;
|
|
ty+=dy;
|
|
}
|
|
tx=dr->tilex-dx;
|
|
ty=dr->tiley-dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
spotvis[tx][ty]=1;
|
|
|
|
tx-=dx;
|
|
ty-=dy;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= LockLinkedDoor
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void LockLinkedDoor (int door)
|
|
{
|
|
doorobj_t*dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
if (!dptr->lock)
|
|
dptr->lock=5;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= IsDoorLinked
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
boolean IsDoorLinked (int door)
|
|
{
|
|
doorobj_t*dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
if (dptr->lock==5)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= FixDoorAreaNumbers
|
|
=
|
|
===============
|
|
*/
|
|
void FixDoorAreaNumbers ( void )
|
|
{
|
|
int i;
|
|
int up,dn,lt,rt;
|
|
int tilex,tiley;
|
|
|
|
for (i=0;i<doornum;i++)
|
|
{
|
|
tilex=doorobjlist[i]->tilex;
|
|
tiley=doorobjlist[i]->tiley;
|
|
up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
|
|
dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
|
|
lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
|
|
rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
|
|
|
|
up = ((up>0) && (up<=NUMAREAS));
|
|
dn = ((dn>0) && (dn<=NUMAREAS));
|
|
lt = ((lt>0) && (lt<=NUMAREAS));
|
|
rt = ((rt>0) && (rt<=NUMAREAS));
|
|
|
|
|
|
if (doorobjlist[i]->vertical==true)
|
|
{
|
|
if (rt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
|
|
else if (lt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
|
|
else
|
|
Error("FixDoors: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
|
|
}
|
|
else
|
|
{
|
|
if (dn)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
|
|
else if (up)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
|
|
else
|
|
Error("FixDoors: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
|
|
}
|
|
if (IsDoorLinked(i))
|
|
UtilizeDoor(i,LockLinkedDoor);
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= OpenDoor
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void OpenDoor (int door)
|
|
{
|
|
if (doorobjlist[door]->action == dr_open)
|
|
doorobjlist[door]->ticcount = 0; // reset open time
|
|
else
|
|
{
|
|
doorobjlist[door]->action = dr_opening; // start it opening
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= DoorUnBlocked
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
boolean DoorUnBlocked (int door)
|
|
{
|
|
int tilex,tiley;
|
|
objtype *check;
|
|
doorobj_t*dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
|
|
//
|
|
// don't close on anything solid
|
|
//
|
|
|
|
tilex = dptr->tilex;
|
|
tiley = dptr->tiley;
|
|
check = (objtype*)actorat[tilex][tiley];
|
|
|
|
if (check && (check->which == ACTOR))
|
|
return false;
|
|
|
|
if (dptr->vertical==true)
|
|
{
|
|
check = (objtype*)actorat[tilex-1][tiley];
|
|
if (check && (check->which==ACTOR) && ((check->x+MINDIST) >> TILESHIFT) == tilex )
|
|
return false;
|
|
check = (objtype*)actorat[tilex+1][tiley];
|
|
if (check && (check->which==ACTOR) && ((check->x-MINDIST) >> TILESHIFT) == tilex )
|
|
return false;
|
|
}
|
|
else if (dptr->vertical==false)
|
|
{
|
|
check = (objtype*)actorat[tilex][tiley-1];
|
|
if (check && (check->which==ACTOR) && ((check->y+MINDIST) >> TILESHIFT) == tiley )
|
|
return false;
|
|
check = (objtype*)actorat[tilex][tiley+1];
|
|
if (check && (check->which==ACTOR) && ((check->y-MINDIST) >> TILESHIFT) == tiley )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= DoorReadyToClose
|
|
=
|
|
= Alter the door's state
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
boolean DoorReadyToClose(int door)
|
|
{
|
|
doorobj_t*dptr;
|
|
int dx,dy;
|
|
doorobj_t * dr2;
|
|
int tx,ty;
|
|
|
|
|
|
dptr = doorobjlist[door];
|
|
|
|
if (dptr->action==dr_closed)
|
|
return true;
|
|
|
|
if (DoorUnBlocked(door)==false)
|
|
return false;
|
|
|
|
dx=0;dy=0;
|
|
if (dptr->vertical==true)
|
|
dy=1;
|
|
else
|
|
dx=1;
|
|
tx=dptr->tilex+dx;
|
|
ty=dptr->tiley+dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
if (DoorUnBlocked(num)==false)
|
|
return false;
|
|
tx+=dx;
|
|
ty+=dy;
|
|
}
|
|
tx=dptr->tilex-dx;
|
|
ty=dptr->tiley-dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
if (DoorUnBlocked(num)==false)
|
|
return false;
|
|
tx-=dx;
|
|
ty-=dy;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= CloseDoor
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void CloseDoor (int door)
|
|
{
|
|
int tilex,tiley,area;
|
|
doorobj_t*dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
if (dptr->action == dr_closed)
|
|
return;
|
|
tilex = dptr->tilex;
|
|
tiley = dptr->tiley;
|
|
|
|
//
|
|
// play door sound
|
|
//
|
|
area = MAPSPOT(tilex,tiley,0)-AREATILE;
|
|
if (areabyplayer[area])
|
|
{
|
|
dptr->soundhandle=SD_PlaySoundRTP ( SD_CLOSEDOORSND, dptr->tilex<<16, dptr->tiley<<16 );
|
|
}
|
|
|
|
dptr->action = dr_closing;
|
|
//
|
|
// make the door space solid
|
|
//
|
|
actorat[tilex][tiley] = dptr;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= OperateDoor
|
|
=
|
|
= The player wants to change the door's direction
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void OperateDoor (int keys, int door, boolean localplayer )
|
|
{
|
|
int lock;
|
|
doorobj_t*dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
if ( ( dptr->flags & DF_ELEVLOCKED ) ||
|
|
( MISCVARS->GASON && ( MAPSPOT( dptr->tilex,
|
|
dptr->tiley, 1 ) == GASVALUE ) ) )
|
|
{
|
|
if ( localplayer )
|
|
{
|
|
// locked
|
|
SD_Play ( SD_NOITEMSND );
|
|
}
|
|
return;
|
|
}
|
|
|
|
lock = dptr->lock;
|
|
if ( lock && !( keys & ( 1 << ( lock - 1 ) ) ) )
|
|
{
|
|
if ( localplayer )
|
|
{
|
|
// locked
|
|
switch (lock)
|
|
{
|
|
case 1:
|
|
AddMessage("You need the \\EGOLD key",MSG_DOOR);
|
|
break;
|
|
|
|
case 2:
|
|
AddMessage("You need the \\FSILVER key",MSG_DOOR);
|
|
break;
|
|
|
|
case 3:
|
|
AddMessage("You need the \\8IRON key",MSG_DOOR);
|
|
break;
|
|
|
|
case 4:
|
|
AddMessage("You need the \\AOSCURO key",MSG_DOOR);
|
|
break;
|
|
|
|
default:
|
|
AddMessage("This door appears to be locked",MSG_DOOR);
|
|
break;
|
|
}
|
|
|
|
SD_Play( SD_NOITEMSND );
|
|
}
|
|
return;
|
|
}
|
|
UseDoor(door);
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= LinkedOpenDoor
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void LinkedOpenDoor (long door)
|
|
{
|
|
UtilizeDoor(door,OpenDoor);
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= LinkedCloseDoor
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void LinkedCloseDoor (long door)
|
|
{
|
|
if (DoorReadyToClose(door)==true)
|
|
UtilizeDoor(door,CloseDoor);
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= UtilizeDoor
|
|
=
|
|
= Alter the door's state
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void UtilizeDoor (int door,void (*action)(int))
|
|
{
|
|
doorobj_t*dptr;
|
|
int dx,dy;
|
|
doorobj_t * dr2;
|
|
int tx,ty;
|
|
|
|
dptr = doorobjlist[door];
|
|
|
|
action(door);
|
|
|
|
dx=0;dy=0;
|
|
if (dptr->vertical==true)
|
|
dy=1;
|
|
else
|
|
dx=1;
|
|
tx=dptr->tilex+dx;
|
|
ty=dptr->tiley+dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
action(num);
|
|
tx+=dx;
|
|
ty+=dy;
|
|
}
|
|
tx=dptr->tilex-dx;
|
|
ty=dptr->tiley-dy;
|
|
while (M_ISDOOR(tx,ty))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[tx][ty]&0x3ff;
|
|
dr2=doorobjlist[num];
|
|
if (!(dr2->flags&DF_MULTI))
|
|
break;
|
|
action(num);
|
|
tx-=dx;
|
|
ty-=dy;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= UseDoor
|
|
=
|
|
= Alter the door's state
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void UseDoor (int door)
|
|
{
|
|
switch (doorobjlist[door]->action)
|
|
{
|
|
case dr_closing:
|
|
SD_StopSound(doorobjlist[door]->soundhandle);
|
|
case dr_closed:
|
|
UtilizeDoor(door,OpenDoor);
|
|
break;
|
|
case dr_opening:
|
|
SD_StopSound(doorobjlist[door]->soundhandle);
|
|
case dr_open:
|
|
if (DoorReadyToClose(door)==true)
|
|
UtilizeDoor(door,CloseDoor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= DoorOpen
|
|
=
|
|
= Close the door after three seconds
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void DoorOpen (int door)
|
|
{doorobj_t* dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
dptr->ticcount += 1;
|
|
if ((dptr->ticcount >= OPENTICS) &&
|
|
(!(dptr->flags & DF_TIMED)) &&
|
|
(DoorReadyToClose(door)==true))
|
|
UtilizeDoor(door,CloseDoor);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= DoorOpening
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void DoorOpening (int door)
|
|
{
|
|
int area1,area2;
|
|
word *map;
|
|
long position;
|
|
int tilex,tiley;
|
|
|
|
position = doorobjlist[door]->position;
|
|
tilex = doorobjlist[door]->tilex;
|
|
tiley = doorobjlist[door]->tiley;
|
|
if (!position)
|
|
{
|
|
//
|
|
// door is just starting to open, so connect the areas
|
|
//
|
|
map = &MAPSPOT(tilex,tiley,0);
|
|
|
|
if (doorobjlist[door]->vertical==true)
|
|
{
|
|
area1 = *(map+1);
|
|
area2 = *(map-1);
|
|
}
|
|
else
|
|
{
|
|
area1 = *(map-mapwidth);
|
|
area2 = *(map+mapwidth);
|
|
}
|
|
area1 -= AREATILE;
|
|
area2 -= AREATILE;
|
|
areaconnect[area1][area2]++;
|
|
areaconnect[area2][area1]++;
|
|
if ((insetupgame==false) && (loadedgame==false))
|
|
ConnectAreas ();
|
|
if (areabyplayer[area1])
|
|
{
|
|
doorobjlist[door]->soundhandle=SD_PlaySoundRTP ( SD_OPENDOORSND, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
|
|
}
|
|
}
|
|
|
|
//
|
|
// slide the door by an adaptive amount
|
|
//
|
|
position += 1<<12;
|
|
if (position >= 0xffff)
|
|
{
|
|
//
|
|
// door is all the way open
|
|
//
|
|
position = 0xffff;
|
|
doorobjlist[door]->ticcount = 0;
|
|
doorobjlist[door]->action = dr_open;
|
|
if (doorobjlist[door] == actorat[tilex][tiley])
|
|
actorat[tilex][tiley] = 0;
|
|
}
|
|
|
|
doorobjlist[door]->position = position;
|
|
doorobjlist[door]->texture=doorobjlist[door]->basetexture+((position+1)>>13);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= DoorClosing
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void DoorClosing (int door)
|
|
{
|
|
int area1,area2;
|
|
word *map;
|
|
long position;
|
|
int tilex,tiley;
|
|
doorobj_t *dptr;
|
|
|
|
dptr = doorobjlist[door];
|
|
|
|
tilex = dptr->tilex;
|
|
tiley = dptr->tiley;
|
|
|
|
position = dptr->position;
|
|
|
|
//
|
|
// slide the door by an adaptive amount
|
|
//
|
|
position -= 1<<12;
|
|
if (position < (0xffff >> 1))
|
|
ResolveDoorSpace(tilex,tiley);
|
|
|
|
|
|
if (position <= 0)
|
|
{
|
|
//
|
|
// door is closed all the way, so disconnect the areas
|
|
//
|
|
position = 0;
|
|
|
|
dptr->action = dr_closed;
|
|
|
|
|
|
|
|
map = &MAPSPOT(tilex,tiley,0);
|
|
|
|
if (areabyplayer[(*map-AREATILE)])
|
|
{
|
|
dptr->soundhandle=SD_PlaySoundRTP ( SD_DOORHITSND, dptr->tilex<<16, dptr->tiley<<16 );
|
|
}
|
|
|
|
if (dptr->vertical==true)
|
|
{
|
|
area1 = *(map+1);
|
|
area2 = *(map-1);
|
|
}
|
|
else
|
|
{
|
|
area1 = *(map-mapwidth);
|
|
area2 = *(map+mapwidth);
|
|
}
|
|
area1 -= AREATILE;
|
|
area2 -= AREATILE;
|
|
areaconnect[area1][area2]--;
|
|
areaconnect[area2][area1]--;
|
|
|
|
ConnectAreas ();
|
|
}
|
|
|
|
dptr->position = position;
|
|
dptr->texture=dptr->basetexture+((position+1)>>13);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= IsMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int IsMaskedWall (int tilex, int tiley)
|
|
{
|
|
int map;
|
|
|
|
if (IsPlatform(tilex,tiley))
|
|
return 1;
|
|
|
|
map=MAPSPOT(tilex,tiley,0);
|
|
|
|
if ((map>=157) && (map<=160))
|
|
return 1;
|
|
|
|
if ((map>=162) && (map<=179))
|
|
return 1;
|
|
|
|
if (M_ISMWALL(tilex,tiley))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= SpawnMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
|
|
void SpawnMaskedWall (int tilex, int tiley, int which, int flags)
|
|
{word *map;
|
|
int area1, area2;
|
|
int up,dn,lt,rt;
|
|
int himask;
|
|
boolean sidepic;
|
|
int side, middle, above, bottom;
|
|
maskedwallobj_t * lastmaskobj;
|
|
boolean metal;
|
|
int maskedstart;
|
|
int abovemaskedwallstart;
|
|
int swallstart;
|
|
|
|
himask=W_GetNumForName("HMSKSTRT")+1;
|
|
maskedstart=W_GetNumForName("MASKSTRT");
|
|
abovemaskedwallstart=W_GetNumForName("ABVMSTRT");
|
|
swallstart=W_GetNumForName("SIDESTRT");
|
|
|
|
maskobjlist[maskednum]=(maskedwallobj_t*)Z_LevelMalloc(sizeof(maskedwallobj_t),PU_LEVELSTRUCT,NULL);
|
|
memset(maskobjlist[maskednum],0,sizeof(maskedwallobj_t));
|
|
lastmaskobj=maskobjlist[maskednum];
|
|
|
|
sidepic=true;
|
|
|
|
lastmaskobj->tilex = tilex;
|
|
lastmaskobj->tiley = tiley;
|
|
lastmaskobj->which = MWALL;
|
|
up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
|
|
dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
|
|
lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
|
|
rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
|
|
|
|
if (IsMaskedWall(tilex,tiley-1)) up=2;
|
|
else if (IsWall(tilex,tiley-1)) up=1;
|
|
else up=0;
|
|
|
|
if (IsMaskedWall(tilex,tiley+1)) dn=2;
|
|
else if (IsWall(tilex,tiley+1)) dn=1;
|
|
else dn=0;
|
|
|
|
if (IsMaskedWall(tilex-1,tiley)) lt=2;
|
|
else if (IsWall(tilex-1,tiley)) lt=1;
|
|
else lt=0;
|
|
|
|
if (IsMaskedWall(tilex+1,tiley)) rt=2;
|
|
else if (IsWall(tilex+1,tiley)) rt=1;
|
|
else rt=0;
|
|
|
|
if ((up==1) && (dn==1))
|
|
lastmaskobj->vertical = true;
|
|
else if ((lt==1) && (rt==1))
|
|
lastmaskobj->vertical = false;
|
|
else if ((up>0) && (dn>0))
|
|
lastmaskobj->vertical = true;
|
|
else if ((lt>0) && (rt>0))
|
|
lastmaskobj->vertical = false;
|
|
else if (up>0)
|
|
lastmaskobj->vertical = true;
|
|
else if (dn>0)
|
|
lastmaskobj->vertical = true;
|
|
else if (lt>0)
|
|
lastmaskobj->vertical = false;
|
|
else if (rt>0)
|
|
lastmaskobj->vertical = false;
|
|
|
|
tilemap[tilex][tiley] = maskednum | 0xc000;
|
|
map = &MAPSPOT(tilex,tiley,0);
|
|
|
|
if (lastmaskobj->vertical==true)
|
|
{
|
|
area1 = *(map+1);
|
|
area2 = *(map-1);
|
|
area1 -= AREATILE;
|
|
area2 -= AREATILE;
|
|
if (lt==0 && rt==0)
|
|
{
|
|
areaconnect[area1][area2]++;
|
|
areaconnect[area2][area1]++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
area1 = *(map-mapwidth);
|
|
area2 = *(map+mapwidth);
|
|
area1 -= AREATILE;
|
|
area2 -= AREATILE;
|
|
if (up==0 && dn==0)
|
|
{
|
|
areaconnect[area1][area2]++;
|
|
areaconnect[area2][area1]++;
|
|
}
|
|
}
|
|
lastmaskobj->flags=flags;
|
|
|
|
if (IsPlatform(tilex,tiley))
|
|
{
|
|
if (MAPSPOT(tilex,tiley,0)==21)
|
|
{
|
|
metal=true;
|
|
actorat[tilex][tiley]=0;
|
|
}
|
|
else
|
|
metal=false;
|
|
}
|
|
|
|
|
|
|
|
switch (which)
|
|
{
|
|
case mw_peephole:
|
|
|
|
//#if (SHAREWARE == 1)
|
|
side = W_GetNumForName("SIDE21");
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
/*
|
|
#else
|
|
side = W_GetNumForName("SIDE16");
|
|
middle = W_GetNumForName("ABOVEM3A") ;
|
|
above = W_GetNumForName("ABOVEM2A") ;
|
|
|
|
#endif
|
|
*/
|
|
bottom = W_GetNumForName("PEEPMASK");
|
|
break;
|
|
|
|
|
|
case mw_dogwall:
|
|
|
|
side = W_GetNumForName("SIDE21");
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
#if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
#else
|
|
middle = W_GetNumForName("ABOVEM9") ;
|
|
|
|
#endif
|
|
bottom = W_GetNumForName("DOGMASK");
|
|
break;
|
|
|
|
case mw_multi1:
|
|
|
|
/*
|
|
#if (SHAREWARE == 1)
|
|
side = W_GetNumForName("SIDE21");
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
#else
|
|
*/
|
|
//side = W_GetNumForName("SIDE23") ;
|
|
side = W_GetNumForName("SIDE21") ;
|
|
middle = W_GetNumForName("ABOVEM5A") ;
|
|
above = W_GetNumForName("ABOVEM5") ;
|
|
|
|
// #endif
|
|
|
|
bottom = W_GetNumForName("MULTI1");
|
|
break;
|
|
|
|
case mw_multi2:
|
|
/*
|
|
#if (SHAREWARE == 1)
|
|
side = W_GetNumForName("SIDE21");
|
|
middle = W_GetNumForName("ABOVEM4A");
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
#else
|
|
*/
|
|
//side = W_GetNumForName("SIDE23") ;
|
|
side = W_GetNumForName("SIDE21") ;
|
|
middle = W_GetNumForName("ABOVEM5B");
|
|
above = W_GetNumForName("ABOVEM5") ;
|
|
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("MULTI2");
|
|
break;
|
|
|
|
case mw_multi3:
|
|
|
|
/*
|
|
#if (SHAREWARE == 1)
|
|
side = W_GetNumForName("SIDE21");
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
#else
|
|
*/
|
|
//side = W_GetNumForName("SIDE23") ;
|
|
side = W_GetNumForName("SIDE21") ;
|
|
middle = W_GetNumForName("ABOVEM5C") ;
|
|
above = W_GetNumForName("ABOVEM5") ;
|
|
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("MULTI3");
|
|
break;
|
|
|
|
case mw_singlepane:
|
|
|
|
// #if (SHAREWARE == 1)
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
// #else
|
|
// side = W_GetNumForName("SIDE22") ;
|
|
// #endif
|
|
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
bottom = W_GetNumForName("MASKED4");
|
|
break;
|
|
|
|
case mw_normal1:
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
|
|
// #if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
// middle = W_GetNumForName("ABOVEM1A") ;
|
|
// above = W_GetNumForName("ABOVEM1") ;
|
|
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("MASKED1");
|
|
break;
|
|
|
|
case mw_normal2:
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
//#if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
// middle = W_GetNumForName("ABOVEM2A") ;
|
|
// above = W_GetNumForName("ABOVEM2") ;
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("MASKED2");
|
|
break;
|
|
|
|
case mw_normal3:
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
//#if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
// middle = W_GetNumForName("ABOVEM3A") ;
|
|
// above = W_GetNumForName("ABOVEM3") ;
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("MASKED3");
|
|
break;
|
|
|
|
case mw_exitarch:
|
|
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
//#if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
// middle = W_GetNumForName("ABOVEM6A") ;
|
|
// above = W_GetNumForName("ABOVEM6") ;
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("EXITARCH");
|
|
break;
|
|
|
|
case mw_secretexitarch:
|
|
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
//#if (SHAREWARE == 1)
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
// middle = W_GetNumForName("ABOVEM8A") ;
|
|
// above = W_GetNumForName("ABOVEM8") ;
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("EXITARCA");
|
|
break;
|
|
|
|
case mw_railing:
|
|
sidepic = false;
|
|
middle = -1;
|
|
above = -1;
|
|
bottom = W_GetNumForName("RAILING");
|
|
break;
|
|
|
|
case mw_hiswitchon:
|
|
sidepic = false;
|
|
middle = himask+1;
|
|
above = himask+3;
|
|
bottom = himask;
|
|
break;
|
|
|
|
case mw_hiswitchoff:
|
|
sidepic = false;
|
|
middle = himask+1;
|
|
above = himask+2;
|
|
bottom = himask;
|
|
break;
|
|
|
|
case mw_entrygate:
|
|
side = W_GetNumForName("SIDE21");
|
|
|
|
//#if (SHAREWARE == 1)
|
|
//side = W_GetNumForName("SIDE21");
|
|
middle = W_GetNumForName("ABOVEM4A") ;
|
|
above = W_GetNumForName("ABOVEM4") ;
|
|
|
|
//#else
|
|
//side = W_GetNumForName("SIDE20") ;
|
|
// middle = W_GetNumForName("ABOVEM7A") ;
|
|
// above = W_GetNumForName("ABOVEM7") ;
|
|
|
|
|
|
//#endif
|
|
|
|
bottom = W_GetNumForName("ENTRARCH");
|
|
break;
|
|
|
|
case mw_platform1:
|
|
sidepic = false;
|
|
bottom = -1;
|
|
middle = -1;
|
|
above = himask+10;
|
|
if (metal==true)
|
|
{
|
|
bottom = -1;
|
|
middle = -1;
|
|
above = himask+15;
|
|
}
|
|
break;
|
|
case mw_platform2:
|
|
sidepic = false;
|
|
bottom = himask+8;
|
|
middle = -1;
|
|
above = -1;
|
|
if (metal==true)
|
|
{
|
|
bottom = himask+14;
|
|
middle = -1;
|
|
above = -1;
|
|
}
|
|
else
|
|
lastmaskobj->flags|=MW_BOTTOMFLIPPING;
|
|
break;
|
|
case mw_platform3:
|
|
sidepic = false;
|
|
bottom = himask+8;
|
|
middle = -1;
|
|
above = himask+10;
|
|
if (metal==true)
|
|
{
|
|
bottom = himask+14;
|
|
middle = -1;
|
|
above = himask+15;
|
|
}
|
|
else
|
|
lastmaskobj->flags|=MW_BOTTOMFLIPPING;
|
|
break;
|
|
case mw_platform4:
|
|
sidepic = false;
|
|
bottom = himask+12;
|
|
middle = himask+7;
|
|
above = himask+7;
|
|
if (metal==true)
|
|
{
|
|
bottom = -1;
|
|
middle = himask+15;
|
|
above = himask+15;
|
|
}
|
|
break;
|
|
case mw_platform5:
|
|
sidepic = false;
|
|
bottom = himask+12;
|
|
middle = himask+7;
|
|
above = himask+5;
|
|
if (metal==true)
|
|
{
|
|
bottom = -1;
|
|
middle = himask+15;
|
|
above = -1;
|
|
}
|
|
else
|
|
lastmaskobj->flags|=MW_TOPFLIPPING;
|
|
break;
|
|
case mw_platform6:
|
|
sidepic = false;
|
|
bottom = himask+4;
|
|
middle = himask+7;
|
|
above = himask+5;
|
|
if (metal==true)
|
|
{
|
|
bottom = himask+14;
|
|
middle = himask+15;
|
|
above = -1;
|
|
}
|
|
else
|
|
lastmaskobj->flags|=MW_TOPFLIPPING;
|
|
break;
|
|
case mw_platform7:
|
|
sidepic = false;
|
|
bottom = himask+4;
|
|
middle = himask+7;
|
|
above = himask+5;
|
|
if ((up==1) || (dn==1))
|
|
lastmaskobj->vertical=true;
|
|
else if ((lt==1) || (rt==1))
|
|
lastmaskobj->vertical=false;
|
|
else
|
|
Error("Perpendicular platform used with no wall near it\n");
|
|
if (metal==true)
|
|
{
|
|
bottom = himask+14;
|
|
middle = himask+15;
|
|
above = -1;
|
|
}
|
|
else
|
|
lastmaskobj->flags|=MW_TOPFLIPPING;
|
|
break;
|
|
}
|
|
|
|
switch (which)
|
|
{
|
|
case mw_multi1:
|
|
case mw_multi2:
|
|
case mw_multi3:
|
|
case mw_singlepane:
|
|
case mw_normal1:
|
|
case mw_normal2:
|
|
case mw_normal3:
|
|
if (!(flags & MW_SHOOTABLE))
|
|
bottom+=9;
|
|
break;
|
|
}
|
|
lastmaskobj->midtexture=middle;
|
|
lastmaskobj->toptexture=above;
|
|
lastmaskobj->bottomtexture=bottom;
|
|
|
|
if (sidepic == true)
|
|
{
|
|
lastmaskobj->sidepic=side;
|
|
if (lastmaskobj->vertical==true)
|
|
{
|
|
if (up==1)
|
|
tilemap[tilex][tiley-1] |= 0x4000;
|
|
if (dn==1)
|
|
tilemap[tilex][tiley+1] |= 0x4000;
|
|
}
|
|
else
|
|
{
|
|
if (lt==1)
|
|
tilemap[tilex-1][tiley] |= 0x4000;
|
|
if (rt==1)
|
|
tilemap[tilex+1][tiley] |= 0x4000;
|
|
}
|
|
}
|
|
|
|
// Cache in the broken version
|
|
|
|
if (lastmaskobj->flags & MW_SHOOTABLE)
|
|
{
|
|
int i;
|
|
|
|
for (i=1;i<AMW_NUMFRAMES;i++)
|
|
{
|
|
PreCacheLump(lastmaskobj->bottomtexture+i,PU_CACHEWALLS,cache_transpatch_t);
|
|
}
|
|
SD_PreCacheSound(SD_GLASSBREAKSND);
|
|
}
|
|
if (sidepic==true)
|
|
{
|
|
PreCacheLump(lastmaskobj->sidepic,PU_CACHEWALLS,cache_pic_t);
|
|
}
|
|
if (lastmaskobj->bottomtexture>=0)
|
|
PreCacheLump(lastmaskobj->bottomtexture,PU_CACHEWALLS,cache_transpatch_t);
|
|
if (lastmaskobj->toptexture>=0)
|
|
PreCacheLump(lastmaskobj->toptexture,PU_CACHEWALLS,cache_patch_t);
|
|
if (lastmaskobj->midtexture>=0)
|
|
PreCacheLump(lastmaskobj->midtexture,PU_CACHEWALLS,cache_patch_t);
|
|
maskednum++;
|
|
lastmaskobj++;
|
|
if (maskednum==MAXMASKED)
|
|
Error ("Too many masked walls\n");
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= FixMaskedWallAreaNumbers
|
|
=
|
|
===============
|
|
*/
|
|
void FixMaskedWallAreaNumbers ( void )
|
|
{
|
|
int i;
|
|
int up,dn,lt,rt;
|
|
int tilex,tiley;
|
|
|
|
for (i=0;i<maskednum;i++)
|
|
{
|
|
int tile;
|
|
tilex=maskobjlist[i]->tilex;
|
|
tiley=maskobjlist[i]->tiley;
|
|
tile=MAPSPOT(tilex,tiley,0)-AREATILE;
|
|
if ((tile<=NUMAREAS) && (tile>0))
|
|
{
|
|
maskobjlist[i]->areanumber = tile;
|
|
continue;
|
|
}
|
|
up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
|
|
dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
|
|
lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
|
|
rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
|
|
|
|
|
|
|
|
up = ((up>0) && (up<=NUMAREAS));
|
|
dn = ((dn>0) && (dn<=NUMAREAS));
|
|
lt = ((lt>0) && (lt<=NUMAREAS));
|
|
rt = ((rt>0) && (rt<=NUMAREAS));
|
|
|
|
if (maskobjlist[i]->vertical==true)
|
|
{
|
|
if (rt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
|
|
else if (lt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
|
|
else if (up)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
|
|
else if (dn)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
|
|
else
|
|
Error("FixMaskedWalls: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
|
|
}
|
|
else
|
|
{
|
|
if (dn)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
|
|
else if (up)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
|
|
else if (rt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
|
|
else if (lt)
|
|
MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
|
|
else
|
|
Error("FixMaskedWalls: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
|
|
}
|
|
maskobjlist[i]->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
|
|
if ((maskobjlist[i]->areanumber <0) || (maskobjlist[i]->areanumber > NUMAREAS))
|
|
Error("Bad masked wall areanumber of %d",maskobjlist[i]->areanumber);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= CheckMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int CheckMaskedWall( maskedwallobj_t * mw )
|
|
{
|
|
int result;
|
|
|
|
result=0;
|
|
if (mw->flags & MW_SHOOTABLE)
|
|
{
|
|
if (mw->flags & MW_BLOCKINGCHANGES)
|
|
{
|
|
mw->flags&=~MW_BLOCKINGCHANGES;
|
|
mw->flags&=~MW_BLOCKING;
|
|
mw->flags|=MW_BOTTOMPASSABLE;
|
|
}
|
|
mw->flags&=~MW_SHOOTABLE;
|
|
// mw->bottomtexture++;
|
|
result=1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= UpdateMaskedWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int UpdateMaskedWall (int num)
|
|
{
|
|
maskedwallobj_t * mw;
|
|
int result;
|
|
|
|
|
|
mw=maskobjlist[num];
|
|
result=CheckMaskedWall(mw);
|
|
if (result==1)
|
|
{
|
|
SpawnAnimatedMaskedWall(num);
|
|
if (loadedgame==false)
|
|
SD_PlaySoundRTP(SD_GLASSBREAKSND,mw->tilex<<16,mw->tiley<<16);
|
|
if (mw->flags&MW_MULTI)
|
|
{
|
|
int i;
|
|
int dx,dy;
|
|
int r;
|
|
maskedwallobj_t * mw2;
|
|
|
|
dx=0;dy=0;
|
|
if (mw->vertical==true)
|
|
dy=1;
|
|
else
|
|
dx=1;
|
|
i=1;
|
|
while (M_ISMWALL(mw->tilex+(dx*i),mw->tiley+(dy*i)))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[mw->tilex+(dx*i)][mw->tiley+(dy*i)]&0x3ff;
|
|
mw2=maskobjlist[num];
|
|
if (!(mw2->flags&MW_MULTI))
|
|
break;
|
|
r=CheckMaskedWall(mw2);
|
|
if (r==1)
|
|
{
|
|
SpawnAnimatedMaskedWall(num);
|
|
if (loadedgame==false)
|
|
SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
|
|
}
|
|
i++;
|
|
}
|
|
i=1;
|
|
while (M_ISMWALL(mw->tilex-(dx*i),mw->tiley-(dy*i)))
|
|
{
|
|
int num;
|
|
|
|
num=tilemap[mw->tilex-(dx*i)][mw->tiley-(dy*i)]&0x3ff;
|
|
mw2=maskobjlist[num];
|
|
if (!(mw2->flags&MW_MULTI))
|
|
break;
|
|
r=CheckMaskedWall(mw2);
|
|
if (r==1)
|
|
{
|
|
SpawnAnimatedMaskedWall(num);
|
|
if (loadedgame==false)
|
|
SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============================
|
|
=
|
|
= ExecuteElevatorStopActions
|
|
=
|
|
============================
|
|
*/
|
|
|
|
|
|
void ExecuteElevatorStopActions(elevator_t *eptr, int teleport_location,
|
|
int desttilex,int desttiley)
|
|
{
|
|
eptr->state = ev_doorclosing;
|
|
eptr->doorclosing = eptr->doortoopen;
|
|
doorobjlist[eptr->doortoopen]->flags &= ~DF_ELEVLOCKED;
|
|
OpenDoor(eptr->doortoopen);
|
|
SD_PlaySoundRTP(SD_ELEVATORENDSND,desttilex,desttiley);
|
|
Teleport(eptr,teleport_location);
|
|
eptr->ticcount = OPENTICS;
|
|
eptr->doortoopen = -1;
|
|
if (MISCVARS->elevatormusicon == true)
|
|
{
|
|
MU_StartSong(song_level);
|
|
MU_RestoreSongPosition();
|
|
MISCVARS->elevatormusicon = false;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
boolean PlayerInElevator(elevator_t *eptr)
|
|
{
|
|
if (eptr->state == ev_mts)
|
|
{
|
|
if ((eptr->dx == player->tilex) && (eptr->dy == player->tiley))
|
|
return true;
|
|
}
|
|
else if (eptr->state == ev_mtd)
|
|
{
|
|
if ((eptr->sx == player->tilex) && (eptr->sy == player->tiley))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#define SHOULD_START_ELEVATOR_MUSIC(eptr) \
|
|
((demoplayback == false) && (demorecord == false) && \
|
|
(MusicStarted() == true) && \
|
|
(!BATTLEMODE) && \
|
|
(!(player->flags & FL_GODMODE)) &&\
|
|
(GameRandomNumber("elevator music",0) < 25) && \
|
|
(PlayerInElevator(eptr)) \
|
|
) \
|
|
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= SetElevatorOperationTime
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
|
|
void SetElevatorOperationTime(elevator_t*eptr)
|
|
{
|
|
if (SHOULD_START_ELEVATOR_MUSIC(eptr))
|
|
{
|
|
MU_StoreSongPosition();
|
|
MU_StartSong(song_elevator);
|
|
MISCVARS->elevatormusicon = true;
|
|
eptr->ticcount = ELEVATORMUSICTIME;
|
|
}
|
|
|
|
else if (AREANUMBER(eptr->sx,eptr->sy) == AREANUMBER(eptr->dx,eptr->dy))
|
|
eptr->ticcount = 70;
|
|
else
|
|
eptr->ticcount = 170;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= CheckElevatorStart
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void CheckElevatorStart (elevator_t*eptr)
|
|
{
|
|
doorobj_t *dptr = doorobjlist[eptr->doorclosing];
|
|
|
|
if (dptr->action == dr_closed)
|
|
{
|
|
|
|
if (eptr->nextaction!=-1)
|
|
{
|
|
eptr->state = eptr->nextaction;
|
|
eptr->nextaction = -1;
|
|
switch (eptr->state)
|
|
{
|
|
case ev_mtd:
|
|
eptr->doortoopen = eptr->door2;
|
|
SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->sx<<16,eptr->sy<<16);
|
|
//eptr->doorclosing = eptr->door1;
|
|
|
|
SetElevatorOperationTime(eptr);
|
|
break;
|
|
|
|
case ev_mts:
|
|
eptr->doortoopen = eptr->door1;
|
|
|
|
SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->dx<<16,eptr->dy<<16);
|
|
|
|
SetElevatorOperationTime(eptr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
else if (eptr->doorclosing == eptr->door1)
|
|
eptr->state = ev_ras;
|
|
|
|
|
|
else if (eptr->doorclosing == eptr->door2)
|
|
eptr->state = ev_rad;
|
|
|
|
|
|
eptr->doorclosing = -1;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= ProcessElevators
|
|
=
|
|
= Called from PlayLoop
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void ProcessElevators (void)
|
|
{
|
|
int ectr;
|
|
elevator_t *eptr;
|
|
|
|
for (ectr = 0 ; ectr < _numelevators ; ectr++)
|
|
{
|
|
eptr = &ELEVATOR[ectr];
|
|
if (eptr->ticcount)
|
|
eptr->ticcount --;
|
|
else
|
|
{
|
|
switch (eptr->state)
|
|
{
|
|
/*
|
|
case ev_ras:
|
|
break;
|
|
|
|
case ev_rad:
|
|
break;
|
|
*/
|
|
case ev_mts:
|
|
ExecuteElevatorStopActions(eptr,0,(eptr->sx << 16),(eptr->sy << 16));
|
|
break;
|
|
|
|
case ev_mtd:
|
|
ExecuteElevatorStopActions(eptr,1,(eptr->dx << 16),(eptr->dy << 16));
|
|
break;
|
|
|
|
case ev_doorclosing:
|
|
CheckElevatorStart(eptr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Teleport(elevator_t*eptr,int destination)
|
|
{statobj_t*tstat;
|
|
objtype*temp;
|
|
int startx,starty,destx,desty;
|
|
|
|
if (destination) // move to dest
|
|
{startx = eptr->sx;
|
|
starty = eptr->sy;
|
|
destx = eptr->dx;
|
|
desty = eptr->dy;
|
|
tilemap[eptr->esx][eptr->esy] = (elevatorstart + 5) | 0x2000;
|
|
|
|
}
|
|
else
|
|
{startx = eptr->dx;
|
|
starty = eptr->dy;
|
|
destx = eptr->sx;
|
|
desty = eptr->sy;
|
|
tilemap[eptr->edx][eptr->edy] = (elevatorstart + 5) | 0x2000;
|
|
}
|
|
|
|
for(tstat=firstactivestat;tstat;tstat=tstat->nextactive)
|
|
{if ((tstat->tilex == startx) && (tstat->tiley == starty))
|
|
{
|
|
tstat->x += ((destx - tstat->tilex) << TILESHIFT);
|
|
tstat->y += ((desty - tstat->tiley) << TILESHIFT);
|
|
tstat->tilex = tstat->x >> TILESHIFT;
|
|
tstat->tiley = tstat->y >> TILESHIFT;
|
|
tstat->visspot = &spotvis[tstat->tilex][tstat->tiley];
|
|
if (sprites[startx][starty] == tstat)
|
|
{sprites[startx][starty] = NULL;
|
|
sprites[destx][desty] = tstat;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
for(temp=firstactive;temp;temp=temp->nextactive)
|
|
{if ((temp->tilex == startx) && (temp->tiley == starty))
|
|
{temp->x += ((destx - temp->tilex) << TILESHIFT);
|
|
temp->y += ((desty - temp->tiley) << TILESHIFT);
|
|
temp->tilex = temp->x >> TILESHIFT;
|
|
temp->tiley = temp->y >> TILESHIFT;
|
|
if (temp->obclass!=inertobj)
|
|
{
|
|
RemoveFromArea (temp);
|
|
temp->areanumber = AREANUMBER(temp->tilex,temp->tiley);
|
|
MakeLastInArea (temp);
|
|
}
|
|
if (temp == player)
|
|
SHAKETICS = 10;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void OperateElevatorDoor(int dnum)
|
|
{
|
|
elevator_t*eptr;
|
|
doorobj_t *dptr,*door1,*door2;
|
|
|
|
dptr = doorobjlist[dnum];
|
|
eptr = &ELEVATOR[dptr->eindex];
|
|
door1 = doorobjlist[eptr->door1];
|
|
door2 = doorobjlist[eptr->door2];
|
|
|
|
switch(eptr->state)
|
|
{/*
|
|
case ev_mtd: // if already on the way to request,
|
|
// ignore; else, put request in
|
|
if (dnum == eptr->door1)
|
|
{eptr->nextaction = ev_mts;
|
|
//eptr->doortoopen = eptr->door1;
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nplayer at source requesting elev %d mtd",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case ev_mts:
|
|
if (dnum == eptr->door2)
|
|
{eptr->nextaction = ev_mtd;
|
|
//eptr->doortoopen = eptr->door2;
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nplayer at dest requesting elev %d mts",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
}
|
|
break;
|
|
*/
|
|
case ev_rad: // if ready at other place,
|
|
if ((dnum == eptr->door1) && (eptr->nextaction != ev_mts)) // process request, lock doors,
|
|
|
|
{
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nplayer at source requesting elev %d rad",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
// start moving to current loc;
|
|
SetNextAction(eptr,0); // if already there, do nothing
|
|
|
|
}
|
|
break;
|
|
|
|
case ev_ras:
|
|
if ((dnum == eptr->door2) && (eptr->nextaction != ev_mtd))
|
|
{
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nplayer at dest requesting elev %d ras",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
SetNextAction(eptr,1);
|
|
|
|
}
|
|
break;
|
|
|
|
case ev_doorclosing:
|
|
if (eptr->doorclosing == dnum) // if opening door at current loc,
|
|
// reset elev state to ready
|
|
{//if (eptr->door1 == dnum)
|
|
// eptr->nextaction = ev_ras;
|
|
//else
|
|
//eptr->nextaction = ev_rad;
|
|
}
|
|
else //else prepare for movement
|
|
{if ((eptr->door1 == dnum) && (eptr->nextaction != ev_mts))
|
|
{
|
|
#if ((DEVELOPMENT == 1))
|
|
#if ((ELEVATORTEST == 1))
|
|
Debug("\nplayer at source requesting elev %d dc",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
SetNextAction(eptr,0);
|
|
|
|
}
|
|
else if ((eptr->door2 == dnum) && (eptr->nextaction != ev_mtd))
|
|
{
|
|
#if ((DEVELOPMENT == 1))
|
|
#if ((ELEVATORTEST == 1))
|
|
Debug("\nplayer at dest requesting elev %d dc",dptr->eindex);
|
|
#endif
|
|
#endif
|
|
SetNextAction(eptr,1);
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
int SetNextAction(elevator_t*eptr,int action)
|
|
{int dn;
|
|
|
|
if (action)
|
|
{if (!DoorReadyToClose(eptr->door1))
|
|
return false;
|
|
|
|
eptr->nextaction = ev_mtd;
|
|
dn = eptr->door1;
|
|
}
|
|
else
|
|
{if (!DoorReadyToClose(eptr->door2))
|
|
return false;
|
|
|
|
eptr->nextaction = ev_mts;
|
|
dn = eptr->door2;
|
|
}
|
|
eptr->state = ev_doorclosing;
|
|
|
|
eptr->doorclosing = dn;
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nCloseDoor %d",dn);
|
|
#endif
|
|
#endif
|
|
if (doorobjlist[dn]->action != dr_closed)
|
|
CloseDoor(dn);
|
|
doorobjlist[dn]->flags |= DF_ELEVLOCKED;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void OperateElevatorSwitch(objtype*ob,int elevnum,int checkx,int checky)
|
|
{elevator_t*eptr;
|
|
doorobj_t *door1,*door2;
|
|
|
|
eptr = &ELEVATOR[elevnum];
|
|
|
|
if ((eptr->state == ev_mts) ||
|
|
(eptr->state == ev_mtd))
|
|
{
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nobj %d tried to use elevator %d switch while in use",ob->obclass,elevnum);
|
|
#endif
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
door1 = doorobjlist[eptr->door1];
|
|
door2 = doorobjlist[eptr->door2];
|
|
|
|
if ((abs(ob->tilex-door1->tilex)<=1) && //switch at source
|
|
(abs(ob->tiley-door1->tiley)<=1))
|
|
{if (!SetNextAction(eptr,1)) // set next to dest
|
|
return;
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nswitch at src %d flipped",elevnum);
|
|
#endif
|
|
#endif
|
|
eptr->ticcount = 0;
|
|
}
|
|
else //switch at dest
|
|
{if (!SetNextAction(eptr,0)) // set next to src
|
|
return;
|
|
#if (DEVELOPMENT == 1)
|
|
#if (ELEVATORTEST == 1)
|
|
Debug("\nswitch at dest %d flipped",elevnum);
|
|
#endif
|
|
#endif
|
|
eptr->ticcount = 0;
|
|
}
|
|
|
|
tilemap[checkx][checky] = (elevatorstart + 6) | 0x2000;
|
|
SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= MoveDoors
|
|
=
|
|
= Called from PlayLoop
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void MoveDoors (void)
|
|
{
|
|
int door;
|
|
|
|
for (door = 0 ; door < doornum ; door++)
|
|
switch (doorobjlist[door]->action)
|
|
{
|
|
case dr_open:
|
|
DoorOpen (door);
|
|
break;
|
|
|
|
case dr_opening:
|
|
DoorOpening(door);
|
|
SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
|
|
break;
|
|
|
|
case dr_closing:
|
|
DoorClosing(door);
|
|
SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================================
|
|
//
|
|
// PUSHWALLS
|
|
//
|
|
//===========================================================
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= GetAreaNumber
|
|
=
|
|
===============
|
|
*/
|
|
int GetAreaNumber ( int tilex, int tiley, int dir )
|
|
{
|
|
int up,dn,lt,rt;
|
|
|
|
up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
|
|
dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
|
|
lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
|
|
rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
|
|
if ((up<=0) || (up>NUMAREAS)) up=0;
|
|
if ((dn<=0) || (dn>NUMAREAS)) dn=0;
|
|
if ((lt<=0) || (lt>NUMAREAS)) lt=0;
|
|
if ((rt<=0) || (rt>NUMAREAS)) rt=0;
|
|
switch (dir)
|
|
{
|
|
case north:
|
|
if (up)
|
|
return up;
|
|
else if (dn)
|
|
return dn;
|
|
break;
|
|
case south:
|
|
if (dn)
|
|
return dn;
|
|
else if (up)
|
|
return up;
|
|
break;
|
|
case east:
|
|
if (rt)
|
|
return rt;
|
|
else if (lt)
|
|
return lt;
|
|
break;
|
|
case west:
|
|
if (lt)
|
|
return lt;
|
|
else if (rt)
|
|
return rt;
|
|
break;
|
|
}
|
|
if (up)
|
|
return up;
|
|
else if (dn)
|
|
return dn;
|
|
else if (lt)
|
|
return lt;
|
|
else if (rt)
|
|
return rt;
|
|
else
|
|
Error("Cannot find an area number for tile at x=%d y=%d\n",tilex,tiley);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= SpawnPushWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void SpawnPushWall (int tilex, int tiley, int lock, int texture, int dir, int type)
|
|
{
|
|
pwallobj_t * lastpwallobj;
|
|
|
|
if (pwallnum==MAXPWALLS)
|
|
Error ("MAXPWALLS on level!");
|
|
|
|
pwallobjlist[pwallnum]=(pwallobj_t*)Z_LevelMalloc(sizeof(pwallobj_t),PU_LEVELSTRUCT,NULL);
|
|
memset(pwallobjlist[pwallnum],0,sizeof(pwallobj_t));
|
|
lastpwallobj=pwallobjlist[pwallnum];
|
|
|
|
lastpwallobj->x = (tilex<<16)+0x8000;
|
|
lastpwallobj->y = (tiley<<16)+0x8000;
|
|
lastpwallobj->momentumx=0;
|
|
lastpwallobj->momentumy=0;
|
|
lastpwallobj->tilex = tilex;
|
|
lastpwallobj->tiley = tiley;
|
|
lastpwallobj->lock = lock;
|
|
lastpwallobj->action = pw_npushed;
|
|
lastpwallobj->which = PWALL;
|
|
lastpwallobj->dir = dir;
|
|
lastpwallobj->num = pwallnum;
|
|
actorat[tilex][tiley] = (pwallobj_t*)(lastpwallobj); // consider it a solid wall
|
|
|
|
if ( (MAPSPOT(tilex,tiley,0)==44) ||
|
|
(MAPSPOT(tilex,tiley,0)==233)
|
|
)
|
|
lastpwallobj->flags=PW_DAMAGE;
|
|
|
|
lastpwallobj->texture = texture;
|
|
if (!texture&0x1000)
|
|
PreCacheLump(texture,PU_CACHEWALLS,cache_pic_t);
|
|
lastpwallobj->areanumber = GetAreaNumber(tilex,tiley,lastpwallobj->dir);
|
|
|
|
MAPSPOT (tilex, tiley, 0)=(word)(lastpwallobj->areanumber+AREATILE);
|
|
|
|
switch(type)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 3:
|
|
lastpwallobj->speed = 2;
|
|
break;
|
|
case 2:
|
|
case 4:
|
|
lastpwallobj->speed = 4;
|
|
break;
|
|
default:
|
|
Error("Illegal PushWall type passed into SpawnPushWall\n");
|
|
break;
|
|
}
|
|
if (type>2)
|
|
{
|
|
tilemap[tilex][tiley] = 0;
|
|
ActivateMoveWall(pwallnum);
|
|
}
|
|
else
|
|
{
|
|
tilemap[tilex][tiley] = texture|0x800;
|
|
if ((loadedgame==false) && (type==0))
|
|
gamestate.secrettotal++;
|
|
}
|
|
|
|
pwallnum++;
|
|
lastpwallobj++;
|
|
|
|
SD_PreCacheSoundGroup(SD_PUSHWALLSND,SD_TURBOWALLSND);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= OperatePushWall
|
|
=
|
|
= The player wants to change the pushwall's direction
|
|
=
|
|
=====================
|
|
*/
|
|
void OperatePushWall (int pwall, int dir, boolean localplayer )
|
|
{
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
if (pw->lock)
|
|
{
|
|
if ( localplayer )
|
|
{
|
|
// Can't push
|
|
AddMessage("This push wall appears to be locked...",MSG_DOOR);
|
|
PlayNoWaySound();
|
|
}
|
|
return;
|
|
}
|
|
switch (pw->action)
|
|
{
|
|
case pw_npushed:
|
|
if ((dir!=pw->dir) && (pw->dir!=nodir))
|
|
{
|
|
// Can't push
|
|
if ( localplayer )
|
|
{
|
|
PlayNoWaySound();
|
|
}
|
|
return;
|
|
}
|
|
else if (localplayer && (gamestate.difficulty == gd_baby))
|
|
AddMessage("Push Wall Activated.",MSG_GAME);
|
|
|
|
pw->action=pw_pushing;
|
|
pw->dir=dir;
|
|
SD_PlaySoundRTP ( SD_TOUCHPLATESND, pw->x, pw->y );
|
|
ConnectPushWall(pwall);
|
|
SetupPushWall(pwall);
|
|
gamestate.secretcount++;
|
|
break;
|
|
default:
|
|
// Can't push
|
|
if ( localplayer )
|
|
{
|
|
PlayNoWaySound();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= ActivateAllPushWalls
|
|
=
|
|
= A Push wall has beeen activated by a touch plate
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void ActivateAllPushWalls(void)
|
|
{
|
|
int i;
|
|
|
|
for(i=0;i<pwallnum;i++)
|
|
{
|
|
if (pwallobjlist[i]->dir != nodir)
|
|
{
|
|
ActivatePushWall(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= ActivatePushWall
|
|
=
|
|
= A Push wall has beeen activated by a touch plate
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void ActivatePushWall (long pwall)
|
|
{
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
switch (pw->action)
|
|
{
|
|
case pw_npushed:
|
|
pw->action=pw_pushing;
|
|
ConnectPushWall(pwall);
|
|
SetupPushWall(pwall);
|
|
gamestate.secretcount++;
|
|
break;
|
|
default:
|
|
// Can't push
|
|
SD_Play( SD_BADTOUCHSND );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= ActivateMoveWall
|
|
=
|
|
= A Push wall has beeen activated by a touch plate
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void ActivateMoveWall (long pwall)
|
|
{
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
switch (pw->action)
|
|
{
|
|
case pw_npushed:
|
|
pw->action=pw_moving;
|
|
SetupPushWall(pwall);
|
|
break;
|
|
default:
|
|
SD_Play( SD_BADTOUCHSND );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= ConnectPushWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void ConnectPushWall (int pwall)
|
|
{
|
|
int checkx;
|
|
int checky;
|
|
int area1,area2;
|
|
int area3,area4;
|
|
word *map;
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
checkx=pw->tilex;
|
|
checky=pw->tiley;
|
|
tilemap[checkx][checky] = 0;
|
|
map = &MAPSPOT (checkx, checky, 0);
|
|
|
|
area1 = *(map-mapwidth);
|
|
area2 = *(map+mapwidth);
|
|
area3 = *(map+1);
|
|
area4 = *(map-1);
|
|
|
|
area1 -= AREATILE;
|
|
area2 -= AREATILE;
|
|
area3 -= AREATILE;
|
|
area4 -= AREATILE;
|
|
if (((area1>0) && (area1<NUMAREAS)) &&
|
|
((area2>0) && (area2<NUMAREAS)))
|
|
{
|
|
areaconnect[area1][area2]++;
|
|
areaconnect[area2][area1]++;
|
|
|
|
if ((insetupgame==false) && (loadedgame==false))
|
|
ConnectAreas ();
|
|
}
|
|
if (((area3>0) && (area3<NUMAREAS)) &&
|
|
((area4>0) && (area4<NUMAREAS)))
|
|
{
|
|
areaconnect[area3][area4]++;
|
|
areaconnect[area4][area3]++;
|
|
|
|
if ((insetupgame==false) && (loadedgame==false))
|
|
ConnectAreas ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= SetupPushWall
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void SetupPushWall (int pwall)
|
|
{
|
|
pwallobj_t * pw;
|
|
int speed;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
speed=pw->speed<<PUSHWALLSPEED;
|
|
switch (pw->dir)
|
|
{
|
|
case north:
|
|
pw->momentumx=0;
|
|
pw->momentumy=-speed;
|
|
break;
|
|
|
|
case east:
|
|
pw->momentumx=speed;
|
|
pw->momentumy=0;
|
|
break;
|
|
|
|
case northeast:
|
|
pw->momentumx=speed;
|
|
pw->momentumy=-speed;
|
|
break;
|
|
|
|
case southeast:
|
|
pw->momentumx=speed;
|
|
pw->momentumy=speed;
|
|
break;
|
|
|
|
case south:
|
|
pw->momentumx=0;
|
|
pw->momentumy=speed;
|
|
break;
|
|
|
|
case west:
|
|
pw->momentumx=-speed;
|
|
pw->momentumy=0;
|
|
break;
|
|
|
|
case northwest:
|
|
pw->momentumx=-speed;
|
|
pw->momentumy=-speed;
|
|
break;
|
|
|
|
case southwest:
|
|
pw->momentumx=-speed;
|
|
pw->momentumy=speed;
|
|
break;
|
|
}
|
|
if (pw->action==pw_pushing)
|
|
{
|
|
if (loadedgame==false)
|
|
pw->soundhandle=SD_PlaySoundRTP ( SD_PUSHWALLSND, pw->x, pw->y );
|
|
pw->state=(0x20000L/speed);
|
|
}
|
|
if (pw->action==pw_moving)
|
|
pw->state=(0x10000L/speed);
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= MovePWalls
|
|
=
|
|
= Called from PlayLoop
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void MovePWalls (void)
|
|
{
|
|
int pwall;
|
|
|
|
for (pwall = 0 ; pwall < pwallnum ; pwall++)
|
|
{
|
|
if (pwallobjlist[pwall]->action==pw_pushing)
|
|
{
|
|
WallPushing (pwall);
|
|
SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
|
|
}
|
|
if (pwallobjlist[pwall]->action==pw_moving)
|
|
{
|
|
WallMoving (pwall);
|
|
SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ClearActorat(pwallobj_t*pw)
|
|
{int txhigh,txlow,tyhigh,tylow;
|
|
int tryx,tryy,x,y;
|
|
int pwrad = 0x6fff;
|
|
|
|
|
|
tryx = pw->x;
|
|
tryy = pw->y;
|
|
txlow = (tryx - pwrad) >> 16;
|
|
txhigh = (tryx + pwrad) >> 16;
|
|
tylow = (tryy - pwrad) >> 16;
|
|
tyhigh = (tryy + pwrad) >> 16;
|
|
for(y=tylow;y<=tyhigh;y++)
|
|
for(x=txlow;x<=txhigh;x++)
|
|
{if (actorat[x][y] == pw)
|
|
actorat[x][y] = NULL;
|
|
}
|
|
}
|
|
|
|
void SetActorat(pwallobj_t*pw)
|
|
{int txhigh,txlow,tyhigh,tylow;
|
|
int tryx,tryy,x,y;
|
|
int pwrad = 0x6fff;
|
|
|
|
tryx = pw->x;
|
|
tryy = pw->y;
|
|
txlow = (tryx - pwrad) >> 16;
|
|
txhigh = (tryx + pwrad) >> 16;
|
|
tylow = (tryy - pwrad) >> 16;
|
|
tyhigh = (tryy + pwrad) >> 16;
|
|
|
|
for(y=tylow;y<=tyhigh;y++)
|
|
for(x=txlow;x<=txhigh;x++)
|
|
actorat[x][y] = pw;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= FinishPushWall
|
|
=
|
|
=================
|
|
*/
|
|
void FinishPushWall (pwallobj_t * pw)
|
|
{
|
|
pw->action = pw_pushed;
|
|
actorat[pw->tilex][pw->tiley] = (wall_t*)&walls[GetWallIndex(pw->texture)];
|
|
tilemap[pw->tilex][pw->tiley] = pw->texture;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= ResetPushWall
|
|
=
|
|
=================
|
|
*/
|
|
void ResetPushWall (pwallobj_t * pw)
|
|
{
|
|
SetActorat(pw);
|
|
tilemap[pw->tilex][pw->tiley] = pw->texture|0x800;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= WallPushing
|
|
=
|
|
=================
|
|
*/
|
|
void WallPushing (int pwall)
|
|
{
|
|
int checkx,checky;
|
|
int spot;
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
ClearActorat(pw);
|
|
|
|
PushWallMove(pwall);
|
|
pw->x+=pw->momentumx;
|
|
pw->y+=pw->momentumy;
|
|
|
|
pw->state--;
|
|
|
|
checkx=pw->tilex;
|
|
checky=pw->tiley;
|
|
|
|
pw->tilex=pw->x>>16;
|
|
pw->tiley=pw->y>>16;
|
|
|
|
if ((pw->tilex!=checkx) || (pw->tiley!=checky))
|
|
{
|
|
int x,y;
|
|
int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
|
|
|
|
if ((area<=0) || (area>NUMAREAS))
|
|
{
|
|
area=pw->areanumber;
|
|
MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
|
|
}
|
|
// block crossed into a new block
|
|
//
|
|
// the tile can now be walked into
|
|
//
|
|
mapseen[checkx][checky] = 0;
|
|
pw->areanumber = area;
|
|
if (pw->momentumx>0)
|
|
x=1;
|
|
else if (pw->momentumx<0)
|
|
x=-1;
|
|
else
|
|
x=0;
|
|
if (pw->momentumy>0)
|
|
y=1;
|
|
else if (pw->momentumy<0)
|
|
y=-1;
|
|
else
|
|
y=0;
|
|
if (tilemap[pw->tilex+x][pw->tiley+y])
|
|
{
|
|
pw->state=(0x8000L/(pw->speed<<PUSHWALLSPEED));
|
|
}
|
|
if (actorat[pw->tilex+x][pw->tiley+y])
|
|
ResolveDoorSpace(pw->tilex+x,pw->tiley+y);
|
|
}
|
|
|
|
|
|
if (pw->state==0)
|
|
{
|
|
pw->x=(pw->tilex<<16)+0x8000;
|
|
pw->y=(pw->tiley<<16)+0x8000;
|
|
spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
|
|
if ((spot >= 0) && (spot <= 7))
|
|
{
|
|
pw->action = pw_npushed;
|
|
pw->dir = spot;
|
|
ResetPushWall (pw);
|
|
if (pw->lock)
|
|
{
|
|
pw->action=pw_pushing;
|
|
ConnectPushWall(pwall);
|
|
SetupPushWall(pwall);
|
|
}
|
|
else
|
|
{
|
|
gamestate.secrettotal++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FinishPushWall (pw);
|
|
}
|
|
}
|
|
else
|
|
SetActorat(pw);
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= WallMoving
|
|
=
|
|
=================
|
|
*/
|
|
void WallMoving (int pwall)
|
|
{
|
|
int checkx,checky;
|
|
int spot;
|
|
pwallobj_t * pw;
|
|
|
|
pw=pwallobjlist[pwall];
|
|
|
|
ClearActorat(pw);
|
|
|
|
PushWallMove(pwall);
|
|
pw->x+=pw->momentumx;
|
|
pw->y+=pw->momentumy;
|
|
|
|
pw->state--;
|
|
|
|
checkx=pw->tilex;
|
|
checky=pw->tiley;
|
|
|
|
pw->tilex=pw->x>>16;
|
|
pw->tiley=pw->y>>16;
|
|
|
|
if ((pw->tilex!=checkx) || (pw->tiley!=checky))
|
|
{
|
|
int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
|
|
|
|
if ((area<=0) || (area>NUMAREAS))
|
|
{
|
|
area=pw->areanumber;
|
|
MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
|
|
}
|
|
// block crossed into a new block
|
|
//
|
|
// the tile can now be walked into
|
|
//
|
|
if (areabyplayer[area])
|
|
{
|
|
if (pw->speed==2)
|
|
pw->soundhandle=SD_PlaySoundRTP ( SD_GOWALLSND, pw->x, pw->y );
|
|
else
|
|
pw->soundhandle=SD_PlaySoundRTP ( SD_TURBOWALLSND, pw->x, pw->y );
|
|
}
|
|
|
|
if (actorat[pw->tilex][pw->tilex])
|
|
ResolveDoorSpace(pw->tilex,pw->tiley);
|
|
mapseen[checkx][checky] = 0;
|
|
pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
|
|
//actorat[pw->tilex][pw->tiley]=pw;
|
|
if ( (pw->tilex==0) || (pw->tilex==127) ||
|
|
(pw->tiley==0) || (pw->tiley==127) )
|
|
{
|
|
if (W_CheckNumForName("imfree")>=0)
|
|
{
|
|
lbm_t *LBM;
|
|
|
|
LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("imfree"), PU_CACHE, Cvt_lbm_t, 1);
|
|
VL_DecompressLBM (LBM,true);
|
|
VW_UpdateScreen ();
|
|
I_Delay (2000);
|
|
}
|
|
Error ("PushWall Attempting to escape off the edge of the map\nIt is located at x=%d y=%d\nI'm Free!!!!\n",
|
|
pw->tilex, pw->tiley);
|
|
}
|
|
}
|
|
if (pw->state==0)
|
|
{
|
|
pw->x=(pw->tilex<<16)+0x8000;
|
|
pw->y=(pw->tiley<<16)+0x8000;
|
|
spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
|
|
if ((spot >= 0) && (spot <= 7))
|
|
{
|
|
int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
|
|
|
|
if ((area<=0) || (area>NUMAREAS))
|
|
{
|
|
area=pw->areanumber;
|
|
MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
|
|
}
|
|
|
|
if (areabyplayer[area] && (abs(spot-pw->dir)==4))
|
|
SD_PlaySoundRTP ( SD_PUSHWALLHITSND, pw->x, pw->y );
|
|
pw->dir = spot;
|
|
}
|
|
SetupPushWall(pwall);
|
|
}
|
|
else
|
|
SetActorat(pw);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= SavePushWalls
|
|
=
|
|
=================
|
|
*/
|
|
void SavePushWalls(byte ** buf, int * sz)
|
|
{
|
|
int unitsize;
|
|
pwallobj_t * pw;
|
|
byte * bufptr;
|
|
int i;
|
|
int size;
|
|
|
|
if (pwallnum==0)
|
|
{
|
|
*sz=0;
|
|
*buf=SafeMalloc(16);
|
|
return;
|
|
}
|
|
pw=pwallobjlist[0];
|
|
unitsize=0;
|
|
unitsize+=sizeof(pw->state);
|
|
unitsize+=sizeof(pw->x);
|
|
unitsize+=sizeof(pw->y);
|
|
unitsize+=sizeof(pw->dir);
|
|
unitsize+=sizeof(pw->speed);
|
|
unitsize+=sizeof(pw->action);
|
|
|
|
*sz=pwallnum*unitsize;
|
|
|
|
*buf=SafeMalloc(*sz);
|
|
bufptr=*buf;
|
|
|
|
for (i=0;i<pwallnum;i++)
|
|
{
|
|
pw=pwallobjlist[i];
|
|
size=sizeof(pw->state);
|
|
memcpy(bufptr,&(pw->state),size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(pw->x);
|
|
memcpy(bufptr,&(pw->x),size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(pw->y);
|
|
memcpy(bufptr,&(pw->y),size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(pw->dir);
|
|
memcpy(bufptr,&(pw->dir),size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(pw->speed);
|
|
memcpy(bufptr,&(pw->speed),size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(pw->action);
|
|
memcpy(bufptr,&(pw->action),size);
|
|
bufptr+=size;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= LoadPushWalls
|
|
=
|
|
=================
|
|
*/
|
|
void LoadPushWalls(byte * bufptr, int sz)
|
|
{
|
|
int unitsize;
|
|
pwallobj_t * pw;
|
|
pwallobj_t new;
|
|
int i;
|
|
int num;
|
|
int size;
|
|
int area;
|
|
|
|
if (sz==0)
|
|
return;
|
|
SetupPushWalls();
|
|
pw=pwallobjlist[0];
|
|
unitsize=0;
|
|
unitsize+=sizeof(pw->state);
|
|
unitsize+=sizeof(pw->x);
|
|
unitsize+=sizeof(pw->y);
|
|
unitsize+=sizeof(pw->dir);
|
|
unitsize+=sizeof(pw->speed);
|
|
unitsize+=sizeof(pw->action);
|
|
|
|
num=sz/unitsize;
|
|
if (pwallnum!=num)
|
|
Error("Different number of Push Walls when trying to load a game\npwallnum=%d num=%d",pwallnum,num);
|
|
|
|
for (i=0;i<pwallnum;i++)
|
|
{
|
|
pw=pwallobjlist[i];
|
|
|
|
size=sizeof(new.state);
|
|
memcpy(&(new.state),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(new.x);
|
|
memcpy(&(new.x),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(new.y);
|
|
memcpy(&(new.y),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(new.dir);
|
|
memcpy(&(new.dir),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(new.speed);
|
|
memcpy(&(new.speed),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
size=sizeof(new.action);
|
|
memcpy(&(new.action),bufptr,size);
|
|
bufptr+=size;
|
|
|
|
actorat[pw->tilex][pw->tiley] = 0;
|
|
mapseen[pw->tilex][pw->tiley] = 0;
|
|
|
|
new.tilex=new.x>>16;
|
|
new.tiley=new.y>>16;
|
|
|
|
if ((new.tilex!=pw->tilex) || (new.tiley!=pw->tiley))
|
|
{
|
|
ClearActorat(pw);
|
|
tilemap[pw->tilex][pw->tiley] = 0;
|
|
if (pw->state!=pw_moving)
|
|
{
|
|
#if 0
|
|
if (pw->dir==nodir)
|
|
{
|
|
if (tilemap[pw->tilex+1][pw->tiley]==0)
|
|
pw->dir=east;
|
|
else if (tilemap[pw->tilex-1][pw->tiley]==0)
|
|
pw->dir=west;
|
|
else if (tilemap[pw->tilex][pw->tiley+1]==0)
|
|
pw->dir=south;
|
|
else
|
|
pw->dir=north;
|
|
}
|
|
#endif
|
|
ConnectPushWall(i);
|
|
}
|
|
}
|
|
|
|
// fixup area if needed
|
|
|
|
area = MAPSPOT(new.tilex,new.tiley,0)-AREATILE;
|
|
if ((area<=0) || (area>NUMAREAS))
|
|
{
|
|
MAPSPOT (new.tilex, new.tiley, 0)=(word)(pw->areanumber+AREATILE);
|
|
}
|
|
|
|
pw->tilex=new.tilex;
|
|
pw->tiley=new.tiley;
|
|
pw->x=new.x;
|
|
pw->y=new.y;
|
|
pw->action=new.action;
|
|
pw->dir=new.dir;
|
|
pw->speed=new.speed;
|
|
SetupPushWall(i);
|
|
pw->state=new.state;
|
|
|
|
pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
|
|
|
|
if (pw->action==pw_pushed)
|
|
{
|
|
FinishPushWall (pw);
|
|
}
|
|
else if (pw->action==pw_npushed)
|
|
{
|
|
ResetPushWall (pw);
|
|
}
|
|
else
|
|
{
|
|
SetActorat(pw);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= SaveMaskedWalls
|
|
=
|
|
=================
|
|
*/
|
|
void SaveMaskedWalls(byte ** buf, int * size)
|
|
{
|
|
int unitsize;
|
|
maskedwallobj_t * mw;
|
|
byte * bufptr;
|
|
int i;
|
|
int sz;
|
|
|
|
if (maskednum==0)
|
|
{
|
|
*size=0;
|
|
*buf=SafeMalloc(16);
|
|
return;
|
|
}
|
|
mw=maskobjlist[0];
|
|
unitsize=0;
|
|
unitsize+=sizeof(mw->flags);
|
|
|
|
*size=maskednum*unitsize;
|
|
|
|
*buf=SafeMalloc(*size);
|
|
bufptr=*buf;
|
|
|
|
for (i=0;i<maskednum;i++)
|
|
{
|
|
mw=maskobjlist[i];
|
|
sz=sizeof(mw->flags);
|
|
memcpy(bufptr,&(mw->flags),sz);
|
|
bufptr+=sz;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= LoadMaskedWalls
|
|
=
|
|
=================
|
|
*/
|
|
void LoadMaskedWalls(byte * bufptr, int sz)
|
|
{
|
|
int unitsize;
|
|
maskedwallobj_t * mw;
|
|
int i;
|
|
int size;
|
|
int num;
|
|
|
|
if (sz==0)
|
|
return;
|
|
|
|
SetupMaskedWalls();
|
|
FixMaskedWallAreaNumbers();
|
|
|
|
mw=maskobjlist[0];
|
|
unitsize=0;
|
|
unitsize+=sizeof(mw->flags);
|
|
|
|
num=sz/unitsize;
|
|
if (maskednum!=num)
|
|
Error("Different number of Masked Walls when trying to load a game\nmaskednum=%d num=%d",maskednum,num);
|
|
|
|
for (i=0;i<maskednum;i++)
|
|
{
|
|
word flags; // Endianness fix thanks to DrLex - DDOI
|
|
|
|
mw=maskobjlist[i];
|
|
size=sizeof(mw->flags);
|
|
memcpy(&flags,bufptr,size);
|
|
bufptr+=size;
|
|
if ((flags&0xff)!=mw->flags) // Preserves original behavior
|
|
UpdateMaskedWall(i);
|
|
if (mw->flags&MW_SWITCHON)
|
|
mw->toptexture--;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= SaveDoors
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void SaveDoors (byte ** buf, int * size)
|
|
{
|
|
int door;
|
|
int doorsave;
|
|
byte doorflag;
|
|
byte doorlocked;
|
|
signed char dooreindex;
|
|
short int doortime;
|
|
int unitsize;
|
|
byte *ptr;
|
|
|
|
if (doornum==0)
|
|
{
|
|
*size=0;
|
|
*buf=SafeMalloc(16);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Size = (int + byte + byte) * numdoors
|
|
//
|
|
|
|
unitsize=0;
|
|
unitsize+=sizeof(doorsave);
|
|
unitsize+=sizeof(doorflag);
|
|
unitsize+=sizeof(doorlocked);
|
|
unitsize+=sizeof(doortime);
|
|
unitsize+=sizeof(dooreindex);
|
|
|
|
*size = unitsize*doornum;
|
|
*buf = (byte *) SafeMalloc (*size);
|
|
|
|
ptr = *buf;
|
|
|
|
for (door = 0; door < doornum ; door++)
|
|
{
|
|
doorsave = doorobjlist[door]->position & ~3;
|
|
doorsave |= doorobjlist[door]->action;
|
|
doorflag = doorobjlist[door]->flags;
|
|
doorlocked = doorobjlist[door]->lock;
|
|
doortime = doorobjlist[door]->ticcount;
|
|
dooreindex = doorobjlist[door]->eindex;
|
|
|
|
memcpy (ptr, &doorsave, sizeof (doorsave));
|
|
ptr += sizeof (doorsave);
|
|
memcpy (ptr, &doorflag, sizeof (doorflag));
|
|
ptr += sizeof (doorflag);
|
|
memcpy (ptr, &doorlocked, sizeof (doorlocked));
|
|
ptr += sizeof (doorlocked);
|
|
memcpy (ptr, &doortime, sizeof (doortime));
|
|
ptr += sizeof (doortime);
|
|
memcpy (ptr, &dooreindex, sizeof (dooreindex));
|
|
ptr += sizeof (dooreindex);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= LoadDoors
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void LoadDoors (byte * buf, int size)
|
|
{
|
|
int door;
|
|
int doorsave;
|
|
byte doorflag;
|
|
byte doorlocked;
|
|
signed char dooreindex;
|
|
short int doortime;
|
|
byte *ptr;
|
|
int unitsize;
|
|
int num;
|
|
|
|
SetupDoors ();
|
|
FixDoorAreaNumbers();
|
|
ptr = buf;
|
|
|
|
unitsize=0;
|
|
unitsize+=sizeof(doorsave);
|
|
unitsize+=sizeof(doorflag);
|
|
unitsize+=sizeof(doorlocked);
|
|
unitsize+=sizeof(doortime);
|
|
unitsize+=sizeof(dooreindex);
|
|
|
|
num=size/unitsize;
|
|
if (doornum!=num)
|
|
Error("Different number of Doors when trying to load a game\ndoornum=%d num=%d",doornum,num);
|
|
|
|
for (door = 0; door < doornum; door++)
|
|
{
|
|
memcpy (&doorsave, ptr, sizeof (doorsave));
|
|
ptr += sizeof (doorsave);
|
|
memcpy (&doorflag, ptr, sizeof (doorflag));
|
|
ptr += sizeof (doorflag);
|
|
memcpy (&doorlocked, ptr, sizeof (doorlocked));
|
|
ptr += sizeof (doorlocked);
|
|
memcpy (&doortime, ptr, sizeof (doortime));
|
|
ptr += sizeof (doortime);
|
|
memcpy (&dooreindex, ptr, sizeof (dooreindex));
|
|
ptr += sizeof (dooreindex);
|
|
|
|
doorobjlist[door]->action = doorsave & 3;
|
|
|
|
// Update Areas
|
|
|
|
if (doorobjlist[door]->action != dr_closed)
|
|
DoorOpening(door);
|
|
|
|
doorobjlist[door]->action = doorsave & 3;
|
|
doorobjlist[door]->position = doorsave;
|
|
doorobjlist[door]->flags = doorflag;
|
|
doorobjlist[door]->lock = doorlocked;
|
|
doorobjlist[door]->ticcount = doortime;
|
|
doorobjlist[door]->eindex = dooreindex;
|
|
|
|
if (doorobjlist[door]->action == dr_open)
|
|
doorobjlist[door]->position = 0xFFFF;
|
|
|
|
else if (doorobjlist[door]->action == dr_closed)
|
|
doorobjlist[door]->position = 0;
|
|
|
|
if (
|
|
(doorobjlist[door]->action == dr_closing) ||
|
|
(doorobjlist[door]->action == dr_closed)
|
|
)
|
|
{
|
|
actorat[doorobjlist[door]->tilex][doorobjlist[door]->tiley] = doorobjlist[door];
|
|
}
|
|
doorobjlist[door]->texture = doorobjlist[door]->basetexture +
|
|
((doorobjlist[door]->position+1)>>13);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= SaveElevators
|
|
=
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void SaveElevators(byte ** buffer,int *size)
|
|
{int i;
|
|
byte * tptr;
|
|
|
|
*size = _numelevators*sizeof(elevator_t);
|
|
|
|
*buffer = (byte *)SafeMalloc(*size);
|
|
tptr = *buffer;
|
|
|
|
for(i=0;i<_numelevators;i++)
|
|
{memcpy(tptr,&ELEVATOR[i],sizeof(elevator_t));
|
|
tptr += sizeof(elevator_t);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= LoadElevators
|
|
=
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void LoadElevators(byte * buffer,int size)
|
|
{int i;
|
|
|
|
_numelevators = size/sizeof(elevator_t);
|
|
|
|
|
|
for(i=0;i<_numelevators;i++)
|
|
{memcpy(&ELEVATOR[i],buffer,sizeof(elevator_t));
|
|
buffer += sizeof(elevator_t);
|
|
}
|
|
}
|
|
|