// // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 1993-2008 Raven Software // Copyright(C) 2005-2014 Simon Howard // // 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. // // HEADER FILES ------------------------------------------------------------ #include "h2def.h" #include "p_local.h" #include "s_sound.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.i = 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; }