ref: 1c9458bd4fb64dcc74c08041c59a5088ccee9dd8
dir: /p_things.c/
//**************************************************************************
//**
//** p_things.c : Heretic 2 : Raven Software, Corp.
//**
//** $Revision: 373 $
//** $Date: 2009-05-19 21:14:28 +0300 (Tue, 19 May 2009) $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2stdinc.h"
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static boolean ActivateThing(mobj_t *mobj);
static boolean DeactivateThing(mobj_t *mobj);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
mobjtype_t TranslateThingType[] =
{
MT_MAPSPOT, /* T_NONE */
MT_CENTAUR, /* T_CENTAUR */
MT_CENTAURLEADER, /* T_CENTAURLEADER */
MT_DEMON, /* T_DEMON */
MT_ETTIN, /* T_ETTIN */
MT_FIREDEMON, /* T_FIREGARGOYLE */
MT_SERPENT, /* T_WATERLURKER */
MT_SERPENTLEADER, /* T_WATERLURKERLEADER */
MT_WRAITH, /* T_WRAITH */
MT_WRAITHB, /* T_WRAITHBURIED */
MT_FIREBALL1, /* T_FIREBALL1 */
MT_MANA1, /* T_MANA1 */
MT_MANA2, /* T_MANA2 */
MT_SPEEDBOOTS, /* T_ITEMBOOTS */
MT_ARTIEGG, /* T_ITEMEGG */
MT_ARTIFLY, /* T_ITEMFLIGHT */
MT_SUMMONMAULATOR, /* T_ITEMSUMMON */
MT_TELEPORTOTHER, /* T_ITEMTPORTOTHER */
MT_ARTITELEPORT, /* T_ITEMTELEPORT */
MT_BISHOP, /* T_BISHOP */
MT_ICEGUY, /* T_ICEGOLEM */
MT_BRIDGE, /* T_BRIDGE */
MT_BOOSTARMOR, /* T_DRAGONSKINBRACERS */
MT_HEALINGBOTTLE, /* T_ITEMHEALTHPOTION */
MT_HEALTHFLASK, /* T_ITEMHEALTHFLASK */
MT_ARTISUPERHEAL, /* T_ITEMHEALTHFULL */
MT_BOOSTMANA, /* T_ITEMBOOSTMANA */
MT_FW_AXE, /* T_FIGHTERAXE */
MT_FW_HAMMER, /* T_FIGHTERHAMMER */
MT_FW_SWORD1, /* T_FIGHTERSWORD1 */
MT_FW_SWORD2, /* T_FIGHTERSWORD2 */
MT_FW_SWORD3, /* T_FIGHTERSWORD3 */
MT_CW_SERPSTAFF, /* T_CLERICSTAFF */
MT_CW_HOLY1, /* T_CLERICHOLY1 */
MT_CW_HOLY2, /* T_CLERICHOLY2 */
MT_CW_HOLY3, /* T_CLERICHOLY3 */
MT_MW_CONE, /* T_MAGESHARDS */
MT_MW_STAFF1, /* T_MAGESTAFF1 */
MT_MW_STAFF2, /* T_MAGESTAFF2 */
MT_MW_STAFF3, /* T_MAGESTAFF3 */
MT_EGGFX, /* T_MORPHBLAST */
MT_ROCK1, /* T_ROCK1 */
MT_ROCK2, /* T_ROCK2 */
MT_ROCK3, /* T_ROCK3 */
MT_DIRT1, /* T_DIRT1 */
MT_DIRT2, /* T_DIRT2 */
MT_DIRT3, /* T_DIRT3 */
MT_DIRT4, /* T_DIRT4 */
MT_DIRT5, /* T_DIRT5 */
MT_DIRT6, /* T_DIRT6 */
MT_ARROW, /* T_ARROW */
MT_DART, /* T_DART */
MT_POISONDART, /* T_POISONDART */
MT_RIPPERBALL, /* T_RIPPERBALL */
MT_SGSHARD1, /* T_STAINEDGLASS1 */
MT_SGSHARD2, /* T_STAINEDGLASS2 */
MT_SGSHARD3, /* T_STAINEDGLASS3 */
MT_SGSHARD4, /* T_STAINEDGLASS4 */
MT_SGSHARD5, /* T_STAINEDGLASS5 */
MT_SGSHARD6, /* T_STAINEDGLASS6 */
MT_SGSHARD7, /* T_STAINEDGLASS7 */
MT_SGSHARD8, /* T_STAINEDGLASS8 */
MT_SGSHARD9, /* T_STAINEDGLASS9 */
MT_SGSHARD0, /* T_STAINEDGLASS0 */
MT_PROJECTILE_BLADE, /* T_BLADE */
MT_ICESHARD, /* T_ICESHARD */
MT_FLAME_SMALL, /* T_FLAME_SMALL */
MT_FLAME_LARGE, /* T_FLAME_LARGE */
MT_ARMOR_1, /* T_MESHARMOR */
MT_ARMOR_2, /* T_FALCONSHIELD */
MT_ARMOR_3, /* T_PLATINUMHELM */
MT_ARMOR_4, /* T_AMULETOFWARDING */
MT_ARTIPOISONBAG, /* T_ITEMFLECHETTE */
MT_ARTITORCH, /* T_ITEMTORCH */
MT_BLASTRADIUS, /* T_ITEMREPULSION */
MT_MANA3, /* T_MANA3 */
MT_ARTIPUZZSKULL, /* T_PUZZSKULL */
MT_ARTIPUZZGEMBIG, /* T_PUZZGEMBIG */
MT_ARTIPUZZGEMRED, /* T_PUZZGEMRED */
MT_ARTIPUZZGEMGREEN1, /* T_PUZZGEMGREEN1 */
MT_ARTIPUZZGEMGREEN2, /* T_PUZZGEMGREEN2 */
MT_ARTIPUZZGEMBLUE1, /* T_PUZZGEMBLUE1 */
MT_ARTIPUZZGEMBLUE2, /* T_PUZZGEMBLUE2 */
MT_ARTIPUZZBOOK1, /* T_PUZZBOOK1 */
MT_ARTIPUZZBOOK2, /* T_PUZZBOOK2 */
MT_KEY1, /* T_METALKEY */
MT_KEY2, /* T_SMALLMETALKEY */
MT_KEY3, /* T_AXEKEY */
MT_KEY4, /* T_FIREKEY */
MT_KEY5, /* T_GREENKEY */
MT_KEY6, /* T_MACEKEY */
MT_KEY7, /* T_SILVERKEY */
MT_KEY8, /* T_RUSTYKEY */
MT_KEY9, /* T_HORNKEY */
MT_KEYA, /* T_SERPENTKEY */
MT_WATER_DRIP, /* T_WATERDRIP */
MT_FLAME_SMALL_TEMP, /* T_TEMPSMALLFLAME */
MT_FLAME_SMALL, /* T_PERMSMALLFLAME */
MT_FLAME_LARGE_TEMP, /* T_TEMPLARGEFLAME */
MT_FLAME_LARGE, /* T_PERMLARGEFLAME */
MT_DEMON_MASH, /* T_DEMON_MASH */
MT_DEMON2_MASH, /* T_DEMON2_MASH */
MT_ETTIN_MASH, /* T_ETTIN_MASH */
MT_CENTAUR_MASH, /* T_CENTAUR_MASH */
MT_THRUSTFLOOR_UP, /* T_THRUSTSPIKEUP */
MT_THRUSTFLOOR_DOWN, /* T_THRUSTSPIKEDOWN */
MT_WRAITHFX4, /* T_FLESH_DRIP1 */
MT_WRAITHFX5, /* T_FLESH_DRIP2 */
MT_WRAITHFX2 /* T_SPARK_DRIP */
};
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// EV_ThingProjectile
//
//==========================================================================
boolean EV_ThingProjectile(byte *args, boolean gravity)
{
int tid;
angle_t angle;
int fineAngle;
fixed_t speed;
fixed_t vspeed;
mobjtype_t moType;
mobj_t *mobj;
mobj_t *newMobj;
int searcher;
boolean success;
success = false;
searcher = -1;
tid = args[0];
moType = TranslateThingType[args[1]];
if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
{ // Don't spawn monsters if -nomonsters
return false;
}
angle = (int)args[2]<<24;
fineAngle = angle>>ANGLETOFINESHIFT;
speed = (int)args[3]<<13;
vspeed = (int)args[4]<<13;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType);
if (newMobj->info->seesound)
{
S_StartSound(newMobj, newMobj->info->seesound);
}
newMobj->target = mobj; // Originator
newMobj->angle = angle;
newMobj->momx = FixedMul(speed, finecosine[fineAngle]);
newMobj->momy = FixedMul(speed, finesine[fineAngle]);
newMobj->momz = vspeed;
newMobj->flags2 |= MF2_DROPPED; // Don't respawn
if (gravity == true)
{
newMobj->flags &= ~MF_NOGRAVITY;
newMobj->flags2 |= MF2_LOGRAV;
}
if (P_CheckMissileSpawn(newMobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingSpawn
//
//==========================================================================
boolean EV_ThingSpawn(byte *args, boolean fog)
{
int tid;
angle_t angle;
mobj_t *mobj;
mobj_t *newMobj;
mobj_t *fogMobj;
mobjtype_t moType;
int searcher;
boolean success;
fixed_t z;
success = false;
searcher = -1;
tid = args[0];
moType = TranslateThingType[args[1]];
if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
{ // Don't spawn monsters if -nomonsters
return false;
}
angle = (int)args[2]<<24;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (mobjinfo[moType].flags2 & MF2_FLOATBOB)
{
z = mobj->z - mobj->floorz;
}
else
{
z = mobj->z;
}
newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType);
if (P_TestMobjLocation(newMobj) == false)
{ // Didn't fit
P_RemoveMobj(newMobj);
}
else
{
newMobj->angle = angle;
if (fog == true)
{
fogMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, MT_TFOG);
S_StartSound(fogMobj, SFX_TELEPORT);
}
newMobj->flags2 |= MF2_DROPPED; // Don't respawn
if (newMobj->flags2 & MF2_FLOATBOB)
{
newMobj->special1 = newMobj->z - newMobj->floorz;
}
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingActivate
//
//==========================================================================
boolean EV_ThingActivate(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (ActivateThing(mobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingDeactivate
//
//==========================================================================
boolean EV_ThingDeactivate(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (DeactivateThing(mobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingRemove
//
//==========================================================================
boolean EV_ThingRemove(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (mobj->type == MT_BRIDGE)
{
A_BridgeRemove(mobj);
return true;
}
P_RemoveMobj(mobj);
success = true;
}
return success;
}
//==========================================================================
//
// EV_ThingDestroy
//
//==========================================================================
boolean EV_ThingDestroy(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (mobj->flags & MF_SHOOTABLE)
{
P_DamageMobj(mobj, NULL, NULL, 10000);
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingMove
//
// arg[0] = tid
// arg[1] = speed
// arg[2] = angle (255 = use mobj angle)
// arg[3] = distance (pixels>>2)
//
//==========================================================================
/*
boolean EV_ThingMove(byte *args)
{
return false;
}
*/
//==========================================================================
//
// ActivateThing
//
//==========================================================================
static boolean ActivateThing(mobj_t *mobj)
{
if (mobj->flags & MF_COUNTKILL)
{ // Monster
if (mobj->flags2 & MF2_DORMANT)
{
mobj->flags2 &= ~MF2_DORMANT;
mobj->tics = 1;
return true;
}
return false;
}
switch (mobj->type)
{
case MT_ZTWINEDTORCH:
case MT_ZTWINEDTORCH_UNLIT:
P_SetMobjState(mobj, S_ZTWINEDTORCH_1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZWALLTORCH:
case MT_ZWALLTORCH_UNLIT:
P_SetMobjState(mobj, S_ZWALLTORCH1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZGEMPEDESTAL:
P_SetMobjState(mobj, S_ZGEMPEDESTAL2);
break;
case MT_ZWINGEDSTATUENOSKULL:
P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2);
break;
case MT_THRUSTFLOOR_UP:
case MT_THRUSTFLOOR_DOWN:
if (mobj->args[0] == 0)
{
S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER);
mobj->flags2 &= ~MF2_DONTDRAW;
if (mobj->args[1])
P_SetMobjState(mobj, S_BTHRUSTRAISE1);
else
P_SetMobjState(mobj, S_THRUSTRAISE1);
}
break;
case MT_ZFIREBULL:
case MT_ZFIREBULL_UNLIT:
P_SetMobjState(mobj, S_ZFIREBULL_BIRTH);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZBELL:
if (mobj->health > 0)
{
P_DamageMobj(mobj, NULL, NULL, 10); // 'ring' the bell
}
break;
case MT_ZCAULDRON:
case MT_ZCAULDRON_UNLIT:
P_SetMobjState(mobj, S_ZCAULDRON1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_FLAME_SMALL:
S_StartSound(mobj, SFX_IGNITE);
P_SetMobjState(mobj, S_FLAME_SMALL1);
break;
case MT_FLAME_LARGE:
S_StartSound(mobj, SFX_IGNITE);
P_SetMobjState(mobj, S_FLAME_LARGE1);
break;
case MT_BAT_SPAWNER:
P_SetMobjState(mobj, S_SPAWNBATS1);
break;
default:
return false;
}
return true;
}
//==========================================================================
//
// DeactivateThing
//
//==========================================================================
static boolean DeactivateThing(mobj_t *mobj)
{
if (mobj->flags & MF_COUNTKILL)
{ // Monster
if (!(mobj->flags2 & MF2_DORMANT))
{
mobj->flags2 |= MF2_DORMANT;
mobj->tics = -1;
return true;
}
return false;
}
switch (mobj->type)
{
case MT_ZTWINEDTORCH:
case MT_ZTWINEDTORCH_UNLIT:
P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT);
break;
case MT_ZWALLTORCH:
case MT_ZWALLTORCH_UNLIT:
P_SetMobjState(mobj, S_ZWALLTORCH_U);
break;
case MT_THRUSTFLOOR_UP:
case MT_THRUSTFLOOR_DOWN:
if (mobj->args[0] == 1)
{
S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE);
if (mobj->args[1])
P_SetMobjState(mobj, S_BTHRUSTLOWER);
else
P_SetMobjState(mobj, S_THRUSTLOWER);
}
break;
case MT_ZFIREBULL:
case MT_ZFIREBULL_UNLIT:
P_SetMobjState(mobj, S_ZFIREBULL_DEATH);
break;
case MT_ZCAULDRON:
case MT_ZCAULDRON_UNLIT:
P_SetMobjState(mobj, S_ZCAULDRON_U);
break;
case MT_FLAME_SMALL:
P_SetMobjState(mobj, S_FLAME_SDORM1);
break;
case MT_FLAME_LARGE:
P_SetMobjState(mobj, S_FLAME_LDORM1);
break;
case MT_BAT_SPAWNER:
P_SetMobjState(mobj, S_SPAWNBATS_OFF);
break;
default:
return false;
}
return true;
}