mirror of
https://github.com/odamex/odamex
synced 2026-08-19 02:23:09 -04:00
505 lines
No EOL
10 KiB
C++
505 lines
No EOL
10 KiB
C++
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id$
|
|
//
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
// Copyright (C) 2006-2026 by The Odamex Team.
|
|
//
|
|
// 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.
|
|
//
|
|
// DESCRIPTION:
|
|
// Determine map format and handle it accordingly.
|
|
// (Props to DSDA-Doom for the inspiration.)
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#include "odamex.h"
|
|
|
|
#include "p_mapformat.h"
|
|
|
|
MapFormat map_format;
|
|
|
|
enum door_type_t
|
|
{
|
|
door_type_none = -1,
|
|
door_type_red,
|
|
door_type_blue,
|
|
door_type_yellow,
|
|
door_type_unknown = door_type_yellow,
|
|
door_type_multiple
|
|
};
|
|
|
|
enum triggertype
|
|
{
|
|
WalkOnce,
|
|
WalkMany,
|
|
SwitchOnce,
|
|
SwitchMany,
|
|
GunOnce,
|
|
GunMany,
|
|
PushOnce,
|
|
PushMany
|
|
};
|
|
|
|
// Migrate some non-hexen data to hexen format, and other misc flags.
|
|
void P_MigrateActorInfo(void)
|
|
{
|
|
static bool migrated = false;
|
|
|
|
// Set MF2_PASSMOBJ on dehacked monsters
|
|
// because we don't expose ZDoom's Bits2 BEX extension (yet...)
|
|
// which is the normal way MF2_PASSMOBJ gets set.
|
|
for (auto&& [_, m] : mobjinfo)
|
|
{
|
|
if (m.flags & MF_COUNTKILL)
|
|
{
|
|
if (P_AllowPassover())
|
|
{
|
|
if (m.flags & MF_COUNTKILL)
|
|
m.flags2 |= MF2_PASSMOBJ;
|
|
}
|
|
else
|
|
{
|
|
if (m.flags & MF_COUNTKILL)
|
|
m.flags2 &= ~MF2_PASSMOBJ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't forget about lost souls!
|
|
if (P_AllowPassover())
|
|
{
|
|
mobjinfo[MT_SKULL].flags2 |= MF2_PASSMOBJ;
|
|
}
|
|
else
|
|
{
|
|
mobjinfo[MT_SKULL].flags2 &= ~MF2_PASSMOBJ;
|
|
}
|
|
|
|
if (map_format.getZDoom() && !migrated)
|
|
{
|
|
migrated = true;
|
|
|
|
for (auto&& [_, m] : mobjinfo)
|
|
{
|
|
if (m.flags & MF_COUNTKILL)
|
|
m.flags2 |= MF2_MCROSS | MF2_PUSHWALL;
|
|
|
|
if (m.flags & MF_MISSILE)
|
|
m.flags2 |= MF2_PCROSS | MF2_IMPACT;
|
|
}
|
|
|
|
mobjinfo[MT_SKULL].flags2 |= MF2_MCROSS | MF2_PUSHWALL;
|
|
mobjinfo[MT_PLAYER].flags2 |= MF2_WINDTHRUST | MF2_PUSHWALL;
|
|
}
|
|
else if (!map_format.getZDoom() && migrated)
|
|
{
|
|
migrated = false;
|
|
|
|
for (auto&& [idx, m] : mobjinfo)
|
|
{
|
|
if (m.flags & MF_COUNTKILL)
|
|
m.flags2 &= ~(MF2_MCROSS | MF2_PUSHWALL);
|
|
|
|
if (m.flags & MF_MISSILE)
|
|
m.flags2 &= ~(MF2_PCROSS | MF2_IMPACT);
|
|
}
|
|
|
|
mobjinfo[MT_SKULL].flags2 &= ~(MF2_MCROSS | MF2_PUSHWALL);
|
|
mobjinfo[MT_PLAYER].flags2 &= ~(MF2_WINDTHRUST | MF2_PUSHWALL);
|
|
}
|
|
}
|
|
|
|
void MapFormat::init_sector_special(sector_t* sector)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_SpawnZDoomSectorSpecial(sector);
|
|
else
|
|
P_SpawnCompatibleSectorSpecial(sector);
|
|
}
|
|
|
|
void MapFormat::player_in_special_sector(player_t& player)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_PlayerInZDoomSector(player);
|
|
else
|
|
P_PlayerInCompatibleSector(player);
|
|
}
|
|
|
|
bool MapFormat::actor_in_special_sector(AActor* actor)
|
|
{
|
|
if (map_format.zdoom)
|
|
return P_ActorInZDoomSector(actor);
|
|
else
|
|
return P_ActorInCompatibleSector(actor);
|
|
}
|
|
|
|
void MapFormat::spawn_scroller(line_t* line, int i)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_SpawnZDoomScroller(line, i);
|
|
else
|
|
P_SpawnCompatibleScroller(line, i);
|
|
}
|
|
|
|
void MapFormat::spawn_friction(line_t* line)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_SpawnZDoomFriction(line);
|
|
else
|
|
P_SpawnCompatibleFriction(line);
|
|
}
|
|
|
|
void MapFormat::spawn_pusher(line_t* line)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_SpawnZDoomPusher(line);
|
|
else
|
|
P_SpawnCompatiblePusher(line);
|
|
}
|
|
|
|
void MapFormat::spawn_extra(int i)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_SpawnZDoomExtra(i);
|
|
else
|
|
P_SpawnCompatibleExtra(i);
|
|
}
|
|
|
|
bool MapFormat::cross_special_line(line_t* line, int side, AActor* thing,
|
|
bool bossaction)
|
|
{
|
|
if (map_format.zdoom)
|
|
return P_CrossZDoomSpecialLine(line, side, thing, bossaction);
|
|
else
|
|
return P_CrossCompatibleSpecialLine(line, side, thing, bossaction);
|
|
}
|
|
|
|
void MapFormat::post_process_sidedef_special(side_t* sd, mapsidedef_t* msd,
|
|
sector_t* sec, int i)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_PostProcessZDoomSidedefSpecial(sd, msd, sec, i);
|
|
else
|
|
P_PostProcessCompatibleSidedefSpecial(sd, msd, sec, i);
|
|
}
|
|
|
|
void MapFormat::post_process_linedef_special(line_t* line)
|
|
{
|
|
if (map_format.zdoom)
|
|
P_PostProcessZDoomLinedefSpecial(line);
|
|
else
|
|
P_PostProcessCompatibleLinedefSpecial(line);
|
|
}
|
|
|
|
void MapFormat::P_ApplyZDoomMapFormat(void)
|
|
{
|
|
map_format.zdoom = true;
|
|
map_format.hexen = true;
|
|
map_format.generalized_mask = ~0xff;
|
|
|
|
P_MigrateActorInfo();
|
|
}
|
|
|
|
void MapFormat::P_ApplyDefaultMapFormat(void)
|
|
{
|
|
map_format.zdoom = false;
|
|
map_format.hexen = false;
|
|
map_format.generalized_mask = ~31;
|
|
|
|
P_MigrateActorInfo();
|
|
}
|
|
|
|
bool MapFormat::getZDoom(void)
|
|
{
|
|
return map_format.zdoom;
|
|
}
|
|
|
|
bool MapFormat::getHexen(void)
|
|
{
|
|
return map_format.hexen;
|
|
}
|
|
|
|
short MapFormat::getGeneralizedMask(void)
|
|
{
|
|
return map_format.generalized_mask;
|
|
}
|
|
|
|
bool P_IsSpecialBoomRepeatable(const short special)
|
|
{
|
|
switch (special)
|
|
{
|
|
case 1:
|
|
case 26:
|
|
case 27:
|
|
case 28:
|
|
case 42:
|
|
case 43:
|
|
case 45:
|
|
case 46:
|
|
case 60:
|
|
case 61:
|
|
case 62:
|
|
case 63:
|
|
case 64:
|
|
case 65:
|
|
case 66:
|
|
case 67:
|
|
case 68:
|
|
case 69:
|
|
case 70:
|
|
case 72:
|
|
case 73:
|
|
case 74:
|
|
case 75:
|
|
case 76:
|
|
case 77:
|
|
case 78:
|
|
case 79:
|
|
case 80:
|
|
case 81:
|
|
case 82:
|
|
case 83:
|
|
case 84:
|
|
case 86:
|
|
case 87:
|
|
case 88:
|
|
case 89:
|
|
case 90:
|
|
case 91:
|
|
case 92:
|
|
case 93:
|
|
case 94:
|
|
case 95:
|
|
case 96:
|
|
case 97:
|
|
case 98:
|
|
case 99:
|
|
case 105:
|
|
case 106:
|
|
case 107:
|
|
case 114:
|
|
case 115:
|
|
case 116:
|
|
case 117:
|
|
case 120:
|
|
case 123:
|
|
case 126:
|
|
case 128:
|
|
case 129:
|
|
case 132:
|
|
case 134:
|
|
case 136:
|
|
case 138:
|
|
case 139:
|
|
case 147:
|
|
case 148:
|
|
case 149:
|
|
case 150:
|
|
case 151:
|
|
case 152:
|
|
case 154:
|
|
case 155:
|
|
case 156:
|
|
case 157:
|
|
case 176:
|
|
case 177:
|
|
case 178:
|
|
case 179:
|
|
case 180:
|
|
case 181:
|
|
case 182:
|
|
case 183:
|
|
case 184:
|
|
case 185:
|
|
case 186:
|
|
case 187:
|
|
case 188:
|
|
case 190:
|
|
case 191:
|
|
case 192:
|
|
case 193:
|
|
case 194:
|
|
case 195:
|
|
case 196:
|
|
case 201:
|
|
case 202:
|
|
case 205:
|
|
case 206:
|
|
case 208:
|
|
case 210:
|
|
case 211:
|
|
case 212:
|
|
case 220:
|
|
case 222:
|
|
case 228:
|
|
case 230:
|
|
case 232:
|
|
case 234:
|
|
case 236:
|
|
case 238:
|
|
case 240:
|
|
case 244:
|
|
case 256:
|
|
case 257:
|
|
case 258:
|
|
case 259:
|
|
case 263:
|
|
case 265:
|
|
case 267:
|
|
case 269:
|
|
return true;
|
|
break;
|
|
}
|
|
|
|
if (special >= GenCrusherBase)
|
|
{
|
|
switch ((special & TriggerType) >> TriggerTypeShift)
|
|
{
|
|
case PushOnce:
|
|
case SwitchOnce:
|
|
case WalkOnce:
|
|
case GunOnce:
|
|
return false;
|
|
case PushMany:
|
|
case SwitchMany:
|
|
case WalkMany:
|
|
case GunMany:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool P_IsExitLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return special == 74 || special == 75 || special == 244 || special == 243;
|
|
|
|
return special == 11 || special == 52 || special == 197 || special == 51 ||
|
|
special == 124 || special == 198 || (2069 <= special && special <= 2074);
|
|
}
|
|
|
|
bool P_IsTeleportLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return special == 70 || special == 71 || special == 154 || special == 215;
|
|
|
|
return special == 39 || special == 97 || special == 125 || special == 126 ||
|
|
special == 174 || special == 195 || special == 207 || special == 208 ||
|
|
special == 209 || special == 210 || special == 243 || special == 244 ||
|
|
(262 <= special && special <= 269);
|
|
}
|
|
|
|
bool P_IsThingTeleportLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
return special == 39 || special == 97 || special == 125 || special == 126 ||
|
|
special == 174 || special == 195 || special == 207 || special == 208 ||
|
|
special == 209 || special == 210 || special == 268 || special == 269;
|
|
}
|
|
|
|
bool P_IsThingNoFogTeleportLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
return special == 207 || special == 208 || special == 209 || special == 210 ||
|
|
special == 268 || special == 269;
|
|
}
|
|
|
|
bool P_IsGenLockedDoorLine(const short special)
|
|
{
|
|
return special >= GenLockedBase && special < GenDoorBase;
|
|
}
|
|
|
|
bool P_IsCompatibleLockedDoorLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
if (P_IsGenLockedDoorLine(special))
|
|
return true;
|
|
|
|
return special == 26 || special == 27 || special == 28 || special == 32 ||
|
|
special == 33 || special == 34 || special == 99 || special == 133 ||
|
|
special == 134 || special == 135 || special == 136 || special == 137;
|
|
}
|
|
|
|
bool P_IsCompatibleMultiKeyDoorLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
if (!P_IsGenLockedDoorLine(special))
|
|
return false;
|
|
|
|
const int lock = (special & LockedKey) >> LockedKeyShift;
|
|
|
|
return lock == 0 || lock == 7;
|
|
}
|
|
|
|
bool P_IsCompatibleBlueDoorLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
const int lock = (special & LockedKey) >> LockedKeyShift;
|
|
const bool genericlock = P_IsGenLockedDoorLine(special) && (lock == BCard || lock == BSkull);
|
|
|
|
return special == 26 || special == 32 || special == 99 || special == 133 || genericlock;
|
|
}
|
|
|
|
bool P_IsCompatibleRedDoorLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
const int lock = (special & LockedKey) >> LockedKeyShift;
|
|
const bool genericlock = P_IsGenLockedDoorLine(special) && (lock == RCard || lock == RSkull);
|
|
|
|
return special == 28 || special == 33 || special == 134 || special == 135 || genericlock;
|
|
}
|
|
|
|
bool P_IsCompatibleYellowDoorLine(const short special)
|
|
{
|
|
if (map_format.getZDoom())
|
|
return false;
|
|
|
|
const int lock = (special & LockedKey) >> LockedKeyShift;
|
|
const bool genericlock = P_IsGenLockedDoorLine(special) && (lock == YCard || lock == YSkull);
|
|
|
|
return special == 27 || special == 34 || special == 136 || special == 137 || genericlock;
|
|
}
|
|
|
|
bool P_IsLightTagDoorType(const short special)
|
|
{
|
|
switch (special)
|
|
{
|
|
case 1: // Vertical Door
|
|
case 26: // Blue Door/Locked
|
|
case 27: // Yellow Door /Locked
|
|
case 28: // Red Door /Locked
|
|
|
|
case 31: // Manual door open
|
|
case 32: // Blue locked door open
|
|
case 33: // Red locked door open
|
|
case 34: // Yellow locked door open
|
|
|
|
case 117: // Blazing door raise
|
|
case 118: // Blazing door open
|
|
return true;
|
|
}
|
|
return false;
|
|
} |