Revert Rewrite mines

As much as this pains me, this might be needed for lua compat.

This reverts commit 1381a56077.
This commit is contained in:
NepDisk 2025-04-29 18:02:58 -04:00
parent c5eb38bd0e
commit 9584982685
13 changed files with 318 additions and 235 deletions

View file

@ -1472,7 +1472,7 @@ struct int_const_s const INT_CONST[] = {
{"PRECIPFX_THUNDER",PRECIPFX_THUNDER},
{"PRECIPFX_LIGHTNING",PRECIPFX_LIGHTNING},
{"PRECIPFX_WATERPARTICLES",PRECIPFX_WATERPARTICLES},
// followermode_t
{"FOLLOWERMODE_FLOAT",FOLLOWERMODE_FLOAT},
{"FOLLOWERMODE_GROUND",FOLLOWERMODE_GROUND},

View file

@ -102,6 +102,7 @@ extern "C" {
#endif
#define NOMD5
#define NOFILEHASH
// Uncheck this to compile debugging code
//#define RANGECHECK

View file

@ -191,8 +191,6 @@ _(A_FlickyHeightCheck, FLICKYHEIGHTCHECK)
_(A_FlickyFlutter, FLICKYFLUTTER)
_(A_FlameParticle, FLAMEPARTICLE)
_(A_FadeOverlay, FADEOVERLAY)
_(A_MineExplode, MINEEXPLODE)
_(A_MineRange, MINERANGE)
_(A_ConnectToGround, CONNECTTOGROUND)
_(A_SpawnParticleRelative, SPAWNPARTICLERELATIVE)
_(A_ParticleSpawn, PARTICLESPAWN)
@ -212,6 +210,8 @@ _(A_JawzExplode, JAWZEXPLODE)
_(A_SPBChase, SPBCHASE)
_(A_SSMineSearch, SSMINESEARCH)
_(A_SSMineExplode, SSMINEEXPLODE)
_(A_SSMineSearch, GRENADERING)
_(A_SSMineExplode, MINEEXPLODE)
_(A_LandMineExplode, LANDMINEEXPLODE)
_(A_BallhogExplode, BALLHOGEXPLODE)
_(A_LightningFollowPlayer, LIGHTNINGFOLLOWPLAYER)

View file

@ -595,8 +595,8 @@ _(PLAYERRETICULE) // Jawz reticule
_(SSMINE) // Mine stuff
_(SSMINE_SHIELD)
_(MINEEXPLOSION) // to keep compatmode scripts happy
_(MINEEXPLOSION)
_(MINEEXPLOSIONSOUND)
_(SMOLDERING) // New explosion
_(BOOMEXPLODE)

View file

@ -2784,7 +2784,9 @@ _(SSMINE_DEPLOY11)
_(SSMINE_DEPLOY12)
_(SSMINE_DEPLOY13)
_(SSMINE_EXPLODE)
_(SSMINE_EXPLODE2)
_(MINEEXPLOSION1)
_(MINEEXPLOSION2)
// New explosion
_(QUICKBOOM1)
@ -3476,7 +3478,6 @@ _(EBARREL15)
_(EBARREL16)
_(EBARREL17)
_(EBARREL18)
_(EBARREL19)
_(MERRYHORSE)

View file

@ -286,115 +286,6 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
return true;
}
static mobj_t *grenade;
static fixed_t explodedist;
static boolean explodespin;
static inline boolean PIT_SSMineChecks(mobj_t *thing)
{
if (thing == grenade) // Don't explode yourself! Endless loop!
return true;
if (thing->health <= 0)
return true;
if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY))
return true;
if (thing->player && thing->player->spectator)
return true;
if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), thing->z - grenade->z) > explodedist)
return true; // Too far away
if (P_CheckSight(grenade, thing) == false)
return true; // Not in sight
return false;
}
static inline BlockItReturn_t PIT_SSMineSearch(mobj_t *thing)
{
if (grenade == NULL || P_MobjWasRemoved(grenade))
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return BMIT_ABORT;
if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player.
return BMIT_CONTINUE;
if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner instantly.
return BMIT_CONTINUE;
if (PIT_SSMineChecks(thing) == true)
return BMIT_CONTINUE;
// Explode!
P_SetMobjState(grenade, grenade->info->deathstate);
return BMIT_ABORT;
}
void K_DoMineSearch(mobj_t *actor, fixed_t size)
{
INT32 bx, by, xl, xh, yl, yh;
explodedist = FixedMul(size, actor->scale);
grenade = actor;
yh = (unsigned)(actor->y + (explodedist + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(actor->y - (explodedist + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(actor->x + (explodedist + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(actor->x - (explodedist + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT;
BMBOUNDFIX (xl, xh, yl, yh);
for (by = yl; by <= yh; by++)
for (bx = xl; bx <= xh; bx++)
P_BlockThingsIterator(bx, by, PIT_SSMineSearch);
}
static inline BlockItReturn_t PIT_SSMineExplode(mobj_t *thing)
{
if (grenade == NULL || P_MobjWasRemoved(grenade))
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
#if 0
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return BMIT_ABORT;
#endif
if (PIT_SSMineChecks(thing) == true)
return BMIT_CONTINUE;
P_DamageMobj(thing, grenade, grenade->target, 1, (explodespin ? DMG_NORMAL : DMG_EXPLODE));
return BMIT_CONTINUE;
}
void K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin)
{
INT32 bx, by, xl, xh, yl, yh;
explodespin = spin;
explodedist = FixedMul(size, actor->scale);
grenade = actor;
// Use blockmap to check for nearby shootables
yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT;
BMBOUNDFIX (xl, xh, yl, yh);
for (by = yl; by <= yh; by++)
for (bx = xl; bx <= xh; bx++)
P_BlockThingsIterator(bx, by, PIT_SSMineExplode);
// Set this flag to ensure that the inital action won't be triggered twice.
actor->flags2 |= MF2_DEBRIS;
}
boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
{
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
@ -410,7 +301,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
// Bomb punting
if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4])
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_EXPLODE2]))
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13]))
{
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}
@ -445,6 +336,31 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
return true;
}
boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2)
{
if (t2->player)
{
if (t2->player->flashing > 0)
return true;
if (t1->state == &states[S_MINEEXPLOSION1])
{
P_DamageMobj(t2, t1, t1->target, 1, DMG_EXPLODE);
}
else
{
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
}
}
else if (t2->flags & MF_SHOOTABLE)
{
// Shootable damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
}
return true;
}
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
{
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))

View file

@ -9,31 +9,22 @@ extern "C" {
#endif
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2);
boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2);
boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2);
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2);
void K_DoMineSearch(mobj_t *actor, fixed_t size);
void K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin);
boolean K_MineCollide(mobj_t *t1, mobj_t *t2);
boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2);
void K_ThunderShieldAttack(mobj_t *actor, fixed_t size);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2);
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2);
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2);
boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2);
boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2);
#ifdef __cplusplus

View file

@ -4257,6 +4257,90 @@ void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
K_HandleBumperChanges(victim, oldVictimBumpers);
}
// source is the mobj that originally threw the bomb that exploded etc.
// Spawns the sphere around the explosion that handles spinout
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source)
{
mobj_t *mobj;
mobj_t *ghost = NULL;
INT32 i;
TVector v;
TVector *res;
fixed_t finalx, finaly, finalz, dist;
//mobj_t hoopcenter;
angle_t degrees, fa, closestangle;
fixed_t mobjx, mobjy, mobjz;
//hoopcenter.x = x;
//hoopcenter.y = y;
//hoopcenter.z = z;
//hoopcenter.z = z - mobjinfo[type].height/2;
degrees = FINEANGLES/number;
closestangle = 0;
// Create the hoop!
for (i = 0; i < number; i++)
{
fa = (i*degrees);
v[0] = FixedMul(FINECOSINE(fa),radius);
v[1] = 0;
v[2] = FixedMul(FINESINE(fa),radius);
v[3] = FRACUNIT;
res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle));
M_Memcpy(&v, res, sizeof (v));
res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle));
M_Memcpy(&v, res, sizeof (v));
finalx = x + v[0];
finaly = y + v[1];
finalz = z + v[2];
mobj = P_SpawnMobj(finalx, finaly, finalz, type);
mobj->z -= mobj->height>>1;
// change angle
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y);
// change slope
dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z);
if (dist < 1)
dist = 1;
mobjx = mobj->x;
mobjy = mobj->y;
mobjz = mobj->z;
if (ghostit)
{
ghost = P_SpawnGhostMobj(mobj);
P_SetMobjState(mobj, S_NULL);
mobj = ghost;
}
if (spawncenter)
{
mobj->x = x;
mobj->y = y;
mobj->z = z;
}
mobj->momx = FixedMul(FixedDiv(mobjx - x, dist), FixedDiv(dist, 6*FRACUNIT));
mobj->momy = FixedMul(FixedDiv(mobjy - y, dist), FixedDiv(dist, 6*FRACUNIT));
mobj->momz = FixedMul(FixedDiv(mobjz - z, dist), FixedDiv(dist, 6*FRACUNIT));
if (source && !P_MobjWasRemoved(source))
P_SetTarget(&mobj->target, source);
}
}
#define MINEQUAKEDIST 4096
// Spawns the purely visual explosion
void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
{
@ -4271,8 +4355,6 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
radius = source->radius>>FRACBITS;
height = source->height>>FRACBITS;
S_StartSound(smoldering, sfx_s3k4e);
if (!color)
color = SKINCOLOR_KETCHUP;

View file

@ -154,6 +154,7 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);
void K_DestroyBumpers(player_t *player, UINT8 amount);
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
void K_SpawnBoostTrail(player_t *player);

View file

@ -3692,6 +3692,25 @@ static int lib_kTakeBumpersFromPlayer(lua_State *L)
return 0;
}
static int lib_kSpawnKartExplosion(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
fixed_t radius = (fixed_t)luaL_optinteger(L, 4, 32*FRACUNIT);
INT32 number = (INT32)luaL_optinteger(L, 5, 32);
mobjtype_t type = luaL_optinteger(L, 6, MT_MINEEXPLOSION);
angle_t rotangle = luaL_optinteger(L, 7, 0);
boolean spawncenter = lua_opttrueboolean(L, 8);
boolean ghostit = lua_optboolean(L, 9);
mobj_t *source = NULL;
NOHUD
if (!lua_isnone(L, 10) && lua_isuserdata(L, 10))
source = *((mobj_t **)luaL_checkudata(L, 10, META_MOBJ));
K_SpawnKartExplosion(x, y, z, radius, number, type, rotangle, spawncenter, ghostit, source);
return 0;
}
static int lib_kSpawnMineExplosion(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -4467,6 +4486,7 @@ static luaL_Reg lib[] = {
{"K_SpinPlayer",lib_kSpinPlayer},
{"K_ExplodePlayer",lib_kExplodePlayer},
{"K_TakeBumpersFromPlayer",lib_kTakeBumpersFromPlayer},
{"K_SpawnKartExplosion",lib_kSpawnKartExplosion},
{"K_SpawnMineExplosion",lib_kSpawnMineExplosion},
{"K_SpawnBoostTrail",lib_kSpawnBoostTrail},
{"K_SpawnSparkleTrail",lib_kSpawnSparkleTrail},

View file

@ -26,9 +26,7 @@
#include "i_video.h"
#include "z_zone.h"
#include "lua_hook.h"
// SRB2kart
#include "k_kart.h"
#include "k_kart.h" // SRB2kart
#include "k_waypoint.h"
#include "k_battle.h"
#include "k_collide.h"
@ -10149,84 +10147,6 @@ void A_FadeOverlay(mobj_t *actor)
P_SetTarget(&actor->tracer, fade);
}
// Function: A_MineExplode
// Description: Handles the explosion of a DSZ mine.
//
// var1 = unused
// var2 = unused
//
void A_MineExplode(mobj_t *actor)
{
// INT32 locvar1 = var1;
// INT32 locvar2 = var2;
if (LUA_CallAction(A_MINEEXPLODE, actor))
return;
A_Scream(actor);
actor->flags = MF_NOGRAVITY|MF_NOCLIP;
/*
quake.epicenter = NULL;
quake.radius = 512*FRACUNIT;
quake.intensity = 8*FRACUNIT;
quake.time = TICRATE/3;
*/
P_StartQuake(8<<FRACBITS, TICRATE/3);
P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, 0, true);
P_MobjCheckWater(actor);
{
#define dist 64
UINT8 i;
mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_SONIC3KBOSSEXPLODE);
S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e));
P_SpawnMobj(actor->x, actor->y, actor->z, type);
for (i = 0; i < 16; i++)
{
mobj_t *b = P_SpawnMobj(actor->x+P_RandomRange(-dist, dist)*FRACUNIT,
actor->y+P_RandomRange(-dist, dist)*FRACUNIT,
actor->z+P_RandomRange(((actor->eflags & MFE_UNDERWATER) ? -dist : 0), dist)*FRACUNIT,
type);
fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z;
fixed_t dm = P_AproxDistance(dz, P_AproxDistance(dy, dx));
b->momx = FixedDiv(dx, dm)*3;
b->momy = FixedDiv(dy, dm)*3;
b->momz = FixedDiv(dz, dm)*3;
if ((actor->watertop == INT32_MAX) || (b->z + b->height > actor->watertop))
b->flags &= ~MF_NOGRAVITY;
}
#undef dist
if (actor->watertop != INT32_MAX)
P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH);
}
}
// Function: A_MineRange
// Description: If the target gets too close, change the state to meleestate.
//
// var1 = Distance to alert at
// var2 = unused
//
void A_MineRange(mobj_t *actor)
{
fixed_t dm;
INT32 locvar1 = var1;
// INT32 locvar2 = var2;
if (LUA_CallAction(A_MINERANGE, actor))
return;
if (!actor->target)
return;
dm = P_AproxDistance(actor->z - actor->target->z, P_AproxDistance(actor->y - actor->target->y, actor->x - actor->target->x));
if ((dm>>FRACBITS) < locvar1)
P_SetMobjState(actor, actor->info->meleestate);
}
// Function: A_ConnectToGround
// Description: Create a palm tree trunk/mine chain.
//
@ -11081,9 +11001,55 @@ void A_SPBChase(mobj_t *actor)
return;
}
static mobj_t *grenade;
static fixed_t explodedist;
static inline BlockItReturn_t PIT_SSMineSearch(mobj_t *thing)
{
if (!grenade)
return BMIT_ABORT;
if (grenade->flags2 & MF2_DEBRIS)
return BMIT_ABORT;
if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player.
return BMIT_CONTINUE;
if (!(thing->flags & MF_SHOOTABLE))
{
// didn't do any damage
return BMIT_CONTINUE;
}
if (netgame && thing->player && thing->player->spectator)
return BMIT_CONTINUE;
if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner.
return BMIT_CONTINUE;
if (thing->player && (thing->player->hyudorotimer
|| ((gametyperules & GTR_BUMPERS) && thing->player && thing->player->bumper <= 0 && thing->player->karmadelay)))
return BMIT_CONTINUE;
// see if it went over / under
if (grenade->z - explodedist > thing->z + thing->height)
return BMIT_CONTINUE; // overhead
if (grenade->z + grenade->height + explodedist < thing->z)
return BMIT_CONTINUE; // underneath
if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y),
thing->z - grenade->z) > explodedist)
return BMIT_CONTINUE; // Too far away
// Explode!
P_SetMobjState(grenade, grenade->info->deathstate);
return BMIT_ABORT;
}
void A_SSMineSearch(mobj_t *actor)
{
fixed_t dis = INT32_MAX;
INT32 bx, by, xl, xh, yl, yh;
explodedist = FixedMul(actor->info->painchance, mapobjectscale);
if (LUA_CallAction(A_SSMINESEARCH, actor))
return;
@ -11091,19 +11057,66 @@ void A_SSMineSearch(mobj_t *actor)
if (actor->flags2 & MF2_DEBRIS)
return;
if (actor->state == &states[S_SSMINE_DEPLOY8])
explodedist = (3*explodedist)/2;
if (leveltime % 35 == 0)
S_StartSound(actor, actor->info->activesound);
dis = actor->info->painchance;
if (actor->state == &states[S_SSMINE_DEPLOY8])
dis = (3*dis)>>1;
// Use blockmap to check for nearby shootables
yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT;
K_DoMineSearch(actor, dis);
grenade = actor;
for (by = yl; by <= yh; by++)
for (bx = xl; bx <= xh; bx++)
P_BlockThingsIterator(bx, by, PIT_SSMineSearch);
}
static inline BlockItReturn_t PIT_MineExplode(mobj_t *thing)
{
if (!grenade || P_MobjWasRemoved(grenade))
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return BMIT_ABORT;
if (thing == grenade || thing->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop!
return BMIT_CONTINUE;
if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY))
return BMIT_CONTINUE;
if (netgame && thing->player && thing->player->spectator)
return BMIT_CONTINUE;
if ((gametyperules & GTR_BUMPERS) && grenade->target && grenade->target->player && grenade->target->player->bumper <= 0 && thing == grenade->target)
return BMIT_CONTINUE;
// see if it went over / under
if (grenade->z - explodedist > thing->z + thing->height)
return BMIT_CONTINUE; // overhead
if (grenade->z + grenade->height + explodedist < thing->z)
return BMIT_CONTINUE; // underneath
if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y),
thing->z - grenade->z) > explodedist)
return BMIT_CONTINUE; // Too far away
P_DamageMobj(thing, grenade, grenade->target, 1, DMG_EXPLODE);
return BMIT_CONTINUE;
}
void A_SSMineExplode(mobj_t *actor)
{
INT32 bx, by, xl, xh, yl, yh;
INT32 d;
INT32 locvar1 = var1;
mobjtype_t type;
explodedist = FixedMul((3*actor->info->painchance)/2, actor->scale);
if (LUA_CallAction(A_SSMINEEXPLODE, actor))
return;
@ -11111,13 +11124,33 @@ void A_SSMineExplode(mobj_t *actor)
if (actor->flags2 & MF2_DEBRIS)
return;
K_MineExplodeAttack(actor, (3*actor->info->painchance)>>1, (boolean)locvar1);
type = (mobjtype_t)locvar1;
skincolornum_t color = SKINCOLOR_KETCHUP;
if (!P_MobjWasRemoved(actor->target) && actor->target->player)
color = actor->target->player->skincolor;
// Use blockmap to check for nearby shootables
yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT;
K_SpawnMineExplosion(actor, color);
BMBOUNDFIX (xl, xh, yl, yh);
grenade = actor;
for (by = yl; by <= yh; by++)
for (bx = xl; bx <= xh; bx++)
P_BlockThingsIterator(bx, by, PIT_MineExplode);
for (d = 0; d < 16; d++)
K_SpawnKartExplosion(actor->x, actor->y, actor->z, explodedist + 32*mapobjectscale, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64
if (actor->target && actor->target->player)
K_SpawnMineExplosion(actor, actor->target->player->skincolor);
else
K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP);
P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND);
actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame.
}
void A_LandMineExplode(mobj_t *actor)

View file

@ -812,6 +812,27 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return K_MineCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
if (g_tm.thing->type == MT_MINEEXPLOSION)
{
// see if it went over / under
if (g_tm.thing->z > thing->z + thing->height)
return true; // overhead
if (g_tm.thing->z + g_tm.thing->height < thing->z)
return true; // underneath
return K_MineExplosionCollide(g_tm.thing, thing);
}
else if (thing->type == MT_MINEEXPLOSION)
{
// see if it went over / under
if (g_tm.thing->z > thing->z + thing->height)
return true; // overhead
if (g_tm.thing->z + g_tm.thing->height < thing->z)
return true; // underneath
return K_MineExplosionCollide(thing, g_tm.thing);
}
if (g_tm.thing->type == MT_LANDMINE)
{
// see if it went over / under

View file

@ -7833,6 +7833,9 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
return false;
}
break;
case MT_MINEEXPLOSIONSOUND:
P_RemoveMobj(mobj);
return false;
case MT_CDUFO:
if (mobj->fuse > TICRATE)
mobj->renderflags ^= RF_DONTDRAW; // only by good fortune does this end with it having RF_DONTDRAW... don't touch!
@ -8624,6 +8627,34 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
case MT_SPBEXPLOSION:
mobj->health--;
break;
case MT_MINEEXPLOSION:
if ((mobj->z < mobj->floorz - mobj->height) || (mobj->z > mobj->ceilingz + mobj->height))
{
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
break;
}
if (mobj->tics != -1)
{
mobj->tics--;
// you can cycle through multiple states in a tic
if (!mobj->tics)
if (!P_SetMobjState(mobj, mobj->state->nextstate))
return false; // freed itself
}
P_UnsetThingPosition(mobj);
mobj->x += mobj->momx;
mobj->y += mobj->momy;
mobj->z += mobj->momz;
P_SetThingPosition(mobj);
return false;
case MT_MINEEXPLOSIONSOUND:
if (mobj->health == 100)
S_StartSound(mobj, sfx_s3k4e);
mobj->health--;
break;
case MT_BOOSTFLAME:
if (!mobj->target || !mobj->target->health)
{
@ -9987,17 +10018,6 @@ static void P_FiringThink(mobj_t *mobj)
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
}
static void K_MineExplodeThink(mobj_t *mobj)
{
if (mobj->state->action.acp1 == (actionf_p1)A_SSMineExplode)
{
if (mobj->state->tics > 1)
{
K_MineExplodeAttack(mobj, mobj->info->painchance, (boolean)mobj->state->var1);
}
}
}
static void P_MonitorFuseThink(mobj_t *mobj)
{
mobj_t *newmobj;
@ -10302,9 +10322,6 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->flags2 & MF2_FIRING)
P_FiringThink(mobj);
if (mobj->flags2 & MF2_DEBRIS)
K_MineExplodeThink(mobj);
if (mobj->flags & MF_AMBIENT)
{
if (leveltime % mobj->health)