mirror of
https://github.com/odamex/odamex
synced 2026-08-19 02:23:09 -04:00
378 lines
7.1 KiB
C++
378 lines
7.1 KiB
C++
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id$
|
|
//
|
|
// 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:
|
|
// [RH] new file to deal with general things
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#include "odamex.h"
|
|
|
|
|
|
#include "p_local.h"
|
|
#include "c_effect.h"
|
|
#include "p_mobj.h"
|
|
#include "info.h"
|
|
#include "s_sound.h"
|
|
#include "tables.h"
|
|
#include "m_random.h"
|
|
#include "c_console.h"
|
|
#include "gi.h"
|
|
|
|
EXTERN_CVAR(sv_nomonsters)
|
|
|
|
// List of spawnable things for the Thing_Spawn and Thing_Projectile specials.
|
|
// TODO: support SpawnNums mapinfo blocks for modifying this array
|
|
std::array<int, 155> SpawnableThings = {
|
|
0,
|
|
MT_SHOTGUY,
|
|
MT_CHAINGUY,
|
|
MT_BRUISER,
|
|
MT_POSSESSED,
|
|
MT_TROOP,
|
|
MT_BABY,
|
|
MT_SPIDER,
|
|
MT_SERGEANT,
|
|
MT_SHADOWS,
|
|
MT_TROOPSHOT,
|
|
MT_CLIP,
|
|
MT_MISC22, // Shells
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_HEAD,
|
|
MT_UNDEAD,
|
|
MT_BRIDGE,
|
|
MT_MISC3, // Armor bonus
|
|
MT_MISC10, // Stim pack
|
|
MT_MISC11, // Medkit
|
|
MT_MISC12, // Soul sphere
|
|
0,
|
|
MT_SHOTGUN,
|
|
MT_CHAINGUN,
|
|
MT_MISC27, // Rocket launcher
|
|
MT_MISC28, // Plasma gun
|
|
MT_MISC25, // BFG
|
|
MT_MISC26, // Chainsaw
|
|
MT_SUPERSHOTGUN,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // T_MORPHBLAST
|
|
0, // T_ROCK1
|
|
0, // T_ROCK2
|
|
0, // T_ROCK3
|
|
0, // T_DIRT1
|
|
0, // T_DIRT2
|
|
0, // T_DIRT3
|
|
0, // T_DIRT4
|
|
0, // T_DIRT5
|
|
0, // T_DIRT6
|
|
MT_PLASMA,
|
|
0, // T_POISONDART
|
|
MT_TRACER,
|
|
0, // T_STAINEDGLASS1
|
|
0, // T_STAINEDGLASS2
|
|
0, // T_STAINEDGLASS3
|
|
0, // T_STAINEDGLASS4
|
|
0, // T_STAINEDGLASS5
|
|
0, // T_STAINEDGLASS6
|
|
0, // T_STAINEDGLASS7
|
|
0, // T_STAINEDGLASS8
|
|
0, // T_STAINEDGLASS9
|
|
0, // T_STAINEDGLASS0
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_MISC0, // Green armor
|
|
MT_MISC1, // Blue armor
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_MISC20, // Energy cell
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_MISC4, // Blue key card
|
|
MT_MISC5, // Red key card
|
|
MT_MISC6, // Yellow key card
|
|
MT_MISC7, // Yellow skull key
|
|
MT_MISC8, // Red skull key
|
|
MT_MISC9, // Blue skull key
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_FIRE,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_SKULL,
|
|
MT_VILE,
|
|
MT_FATSO,
|
|
MT_KNIGHT,
|
|
MT_CYBORG,
|
|
MT_PAIN,
|
|
MT_WOLFSS,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
MT_BARREL,
|
|
MT_HEADSHOT,
|
|
MT_ROCKET,
|
|
MT_BFG,
|
|
MT_ARACHPLAZ,
|
|
MT_BLOOD,
|
|
MT_PUFF,
|
|
MT_MEGA, // Mega sphere
|
|
MT_INV,
|
|
MT_MISC13, // Berserk
|
|
MT_INS, // Blur sphere
|
|
MT_MISC14, // Rad suit
|
|
MT_MISC15, // Computer map
|
|
MT_MISC16, // Light amp
|
|
MT_MISC17, // Box of ammo
|
|
MT_MISC18, // Rocket
|
|
MT_MISC19, // Box of rockets
|
|
MT_MISC21, // Battery pack
|
|
MT_MISC23, // Box of shells
|
|
MT_MISC24, // Backpack
|
|
MT_MISC68, // Guts
|
|
MT_MISC71, // Blood pool
|
|
MT_MISC84, // Pool o' blood 1
|
|
MT_MISC85, // Pool o' blood 2
|
|
MT_MISC77, // Flaming barrel
|
|
MT_MISC86, // Brains
|
|
0,
|
|
MT_MISC2, // Health bonus
|
|
MT_FATSHOT, // Mancubus fireball
|
|
MT_BRUISERSHOT,// Baron projectile
|
|
};
|
|
|
|
bool P_Thing_Spawn (int tid, int type, std::optional<angle_t> angle, bool fog, std::optional<int> newtid)
|
|
{
|
|
// type is doomednum
|
|
// kind is the mobjtype
|
|
|
|
if (static_cast<size_t>(type) >= SpawnableThings.size())
|
|
return false;
|
|
|
|
const int kind = SpawnableThings[type];
|
|
if (kind == 0)
|
|
return false;
|
|
|
|
if ((mobjinfo[kind].flags & MF_COUNTKILL) && sv_nomonsters == 1)
|
|
return false;
|
|
|
|
AActor* spot = nullptr;
|
|
int rtn = 0;
|
|
while ( (spot = AActor::FindByTID (spot, tid)) )
|
|
{
|
|
fixed_t z;
|
|
if (mobjinfo[kind].flags2 & MF2_FLOATBOB)
|
|
z = spot->z - spot->floorz;
|
|
else
|
|
z = spot->z;
|
|
|
|
auto mobj = new AActor(spot->x, spot->y, z, (mobjtype_t)kind);
|
|
|
|
if (mobj)
|
|
{
|
|
if (P_TestMobjLocation (mobj))
|
|
{
|
|
rtn++;
|
|
mobj->angle = angle.value_or(spot->angle);
|
|
if (fog)
|
|
S_Sound (new AActor (spot->x, spot->y, spot->z + INT2FIXED(gameinfo.telefogHeight), MT_TFOG),
|
|
CHAN_VOICE, "misc/teleport", 1, ATTN_NORM);
|
|
mobj->flags |= MF_DROPPED; // Don't respawn
|
|
if (mobj->flags2 & MF2_FLOATBOB)
|
|
{
|
|
mobj->special1 = mobj->z - mobj->floorz;
|
|
}
|
|
mobj->tid = newtid.value_or(0);
|
|
}
|
|
else
|
|
{
|
|
mobj->Destroy ();
|
|
rtn = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rtn != 0;
|
|
}
|
|
|
|
bool P_Thing_Projectile (int tid, int type, angle_t angle,
|
|
fixed_t speed, fixed_t vspeed, bool gravity, std::optional<int> newtid)
|
|
{
|
|
if (static_cast<size_t>(type) >= SpawnableThings.size())
|
|
return false;
|
|
|
|
const int kind = SpawnableThings[type];
|
|
if (kind == 0)
|
|
return false;
|
|
|
|
if ((mobjinfo[kind].flags & MF_COUNTKILL) && sv_nomonsters)
|
|
return false;
|
|
|
|
bool rtn = false;
|
|
AActor* spot = nullptr;
|
|
while ( (spot = AActor::FindByTID (spot, tid)) )
|
|
{
|
|
if (spot->type != MT_MAPSPOT && spot->type != MT_MAPSPOTGRAVITY)
|
|
continue;
|
|
|
|
auto mobj = new AActor (spot->x, spot->y, spot->z, (mobjtype_t)kind);
|
|
|
|
if (mobj)
|
|
{
|
|
if (mobj->info->seesound)
|
|
S_Sound (mobj, CHAN_VOICE, mobj->info->seesound, 1, ATTN_NORM);
|
|
if (gravity)
|
|
{
|
|
mobj->flags &= ~MF_NOGRAVITY;
|
|
if (!(mobj->flags & MF_COUNTKILL))
|
|
mobj->flags2 |= MF2_LOGRAV;
|
|
}
|
|
else
|
|
mobj->flags |= MF_NOGRAVITY;
|
|
mobj->target = spot->ptr();
|
|
mobj->angle = angle;
|
|
mobj->momx = FixedMul (speed, finecosine[angle>>ANGLETOFINESHIFT]);
|
|
mobj->momy = FixedMul (speed, finesine[angle>>ANGLETOFINESHIFT]);
|
|
mobj->momz = vspeed;
|
|
mobj->flags |= MF_DROPPED;
|
|
mobj->tid = newtid.value_or(0);
|
|
if (mobj->flags & MF_MISSILE)
|
|
rtn = P_CheckMissileSpawn (mobj);
|
|
else if (!P_TestMobjLocation (mobj))
|
|
mobj->Destroy ();
|
|
}
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
bool P_ActivateMobj (AActor *mobj, AActor *activator)
|
|
{
|
|
if (mobj->flags & MF_COUNTKILL)
|
|
{
|
|
mobj->flags2 &= ~(MF2_DORMANT | MF2_INVULNERABLE);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
switch (mobj->type)
|
|
{
|
|
case MT_SPARK:
|
|
{
|
|
int count = mobj->args[0];
|
|
char sound[16];
|
|
|
|
if (count == 0)
|
|
count = 32;
|
|
|
|
P_DrawSplash (count, mobj->x, mobj->y, mobj->z, mobj->angle, 1);
|
|
snprintf (sound, 16, "world/spark%d", 1+(M_Random() % 3));
|
|
S_Sound (mobj, CHAN_AUTO, sound, 1, ATTN_STATIC);
|
|
break;
|
|
}
|
|
|
|
case MT_FOUNTAIN:
|
|
mobj->effects &= ~FX_FOUNTAINMASK;
|
|
mobj->effects |= mobj->args[0] << FX_FOUNTAINSHIFT;
|
|
break;
|
|
|
|
case MT_SECRETTRIGGER:
|
|
if (activator->player->mo == consoleplayer().camera)
|
|
{
|
|
if (mobj->args[0] <= 1)
|
|
{
|
|
C_MidPrint ("A secret is revealed!");
|
|
}
|
|
if (mobj->args[0] == 0 || mobj->args[0] == 2)
|
|
{
|
|
S_Sound (activator, CHAN_AUTO, "misc/secret", 1, ATTN_NORM);
|
|
}
|
|
}
|
|
level.found_secrets++;
|
|
mobj->Destroy ();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool P_DeactivateMobj (AActor *mobj)
|
|
{
|
|
if (mobj->flags & MF_COUNTKILL)
|
|
{
|
|
mobj->flags2 |= MF2_DORMANT | MF2_INVULNERABLE;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
switch (mobj->type)
|
|
{
|
|
case MT_FOUNTAIN:
|
|
mobj->effects &= ~FX_FOUNTAINMASK;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
VERSION_CONTROL (p_things_cpp, "$Id$")
|