534 lines
13 KiB
C
534 lines
13 KiB
C
|
|
//**************************************************************************
|
|
//**
|
|
//** p_things.c : Heretic 2 : Raven Software, Corp.
|
|
//**
|
|
//** $RCSfile: p_things.c,v $
|
|
//** $Revision: 1.36 $
|
|
//** $Date: 96/02/08 15:16:13 $
|
|
//** $Author: bgokey $
|
|
//**
|
|
//**************************************************************************
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
#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;
|
|
break;
|
|
}
|
|
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;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|