Merge branch 'delag_maces' into 'master'

Delag Maces

See merge request STJr/SRB2Internal!141
This commit is contained in:
toaster 2018-04-07 18:11:31 -04:00
commit 5f79a2f1df
10 changed files with 363 additions and 210 deletions

View File

@ -6554,7 +6554,6 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
"MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL
};

View File

@ -9046,7 +9046,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9073,7 +9073,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9100,7 +9100,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9127,7 +9127,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9154,7 +9154,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9181,7 +9181,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
200, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9208,7 +9208,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
200, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9230,7 +9230,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
24*FRACUNIT, // speed
24*FRACUNIT, // radius
48*FRACUNIT, // height
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage

View File

@ -768,6 +768,19 @@ static int lib_pCanRunOnWater(lua_State *L)
return 1;
}
static int lib_pMaceRotate(lua_State *L)
{
mobj_t *center = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
INT32 baserot = luaL_checkinteger(L, 2);
INT32 baseprevrot = luaL_checkinteger(L, 3);
NOHUD
INLEVEL
if (!center)
return LUA_ErrInvalid(L, "mobj_t");
P_MaceRotate(center, baserot, baseprevrot);
return 0;
}
// P_USER
////////////
@ -2517,6 +2530,7 @@ static luaL_Reg lib[] = {
{"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
{"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate},
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},

View File

@ -530,10 +530,22 @@ static int mobj_set(lua_State *L)
case mobj_bprev:
return UNIMPLEMENTED;
case mobj_hnext:
mo->hnext = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hnext, NULL);
else
{
mobj_t *hnext = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hnext, hnext);
}
break;
case mobj_hprev:
mo->hprev = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hprev, NULL);
else
{
mobj_t *hprev = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hprev, hprev);
}
break;
case mobj_type: // yeah sure, we'll let you change the mobj's type.
{

View File

@ -4910,6 +4910,7 @@ void A_SlingAppear(mobj_t *actor)
boolean firsttime = true;
UINT8 mlength = 4;
mobj_t *spawnee;
mobj_t *hprev = actor;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SlingAppear", actor))
return;
@ -4920,7 +4921,6 @@ void A_SlingAppear(mobj_t *actor)
P_SetThingPosition(actor);
actor->lastlook = 128;
actor->movecount = actor->lastlook;
actor->health = actor->angle>>ANGLETOFINESHIFT;
actor->threshold = 0;
actor->movefactor = actor->threshold;
actor->friction = 128;
@ -4929,10 +4929,13 @@ void A_SlingAppear(mobj_t *actor)
{
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
P_SetTarget(&spawnee->target, actor);
P_SetTarget(&spawnee->tracer, actor);
P_SetTarget(&spawnee->hprev, hprev);
P_SetTarget(&hprev->hnext, spawnee);
hprev = spawnee;
spawnee->threshold = 0;
spawnee->reactiontime = mlength;
spawnee->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT;
spawnee->movecount = mlength;
if (firsttime)
{

View File

@ -1505,10 +1505,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->powers[pw_flashing])
return;
if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270)
if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270)
{ // I don't expect you to understand this, Mr Bond...
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold;
if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270))
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle;
if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270))
ang += ANGLE_180;
if (ang < ANGLE_180)
return; // I expect you to die.

View File

@ -280,6 +280,8 @@ mobj_t *P_GetClosestAxis(mobj_t *source);
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover);
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot);
void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration);
#define PAL_WHITE 1
#define PAL_MIXUP 2

View File

@ -6176,124 +6176,217 @@ static void P_NightsItemChase(mobj_t *thing)
//
// P_MaceRotate
// Spins an object around its target, or, swings it from side to side.
// Spins a hnext-chain of objects around its centerpoint, side to side or periodically.
//
static void P_MaceRotate(mobj_t *mobj)
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
{
TVector v;
TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
TVector *res;
fixed_t radius, dist;
fixed_t radius, dist, zstore;
angle_t fa;
INT32 prevswing;
boolean donetwice = false;
boolean dosound = false;
mobj_t *mobj = center->hnext, *hnext = NULL;
// Tracer was removed.
if (!mobj->health)
return;
else if (!mobj->tracer)
INT32 rot = (baserot &= FINEMASK);
INT32 prevrot = (baseprevrot &= FINEMASK);
INT32 lastthreshold = FINEMASK; // needs to never be equal at start of loop
fixed_t lastfriction = INT32_MIN; // ditto; almost certainly never, but...
dist = pos_sideways[0] = pos_sideways[1] = pos_sideways[2] = pos_sideways[3] = unit_sideways[3] = pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
while (mobj)
{
P_KillMobj(mobj, NULL, NULL, 0);
return;
}
if (!mobj->health)
{
mobj = mobj->hnext;
continue;
}
mobj->momx = mobj->momy = mobj->momz = 0;
mobj->momx = mobj->momy = mobj->momz = 0;
prevswing = mobj->threshold;
mobj->threshold += mobj->tracer->lastlook;
mobj->threshold &= FINEMASK;
if (mobj->threshold != lastthreshold
|| mobj->friction != lastfriction)
{
rot = (baserot + mobj->threshold) & FINEMASK;
prevrot = (baseprevrot + mobj->threshold) & FINEMASK;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
// Radius of the link's rotation.
radius = FixedMul(dist * mobj->movecount, mobj->tracer->scale) + mobj->tracer->extravalue1;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale));
maceretry:
fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
radius = FixedMul(dist, FINECOSINE(fa));
unit_lengthways[1] = -FixedMul(dist, FINESINE(fa));
unit_lengthways[3] = FRACUNIT;
fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
radius = FixedMul(FINECOSINE(fa), radius);
v[1] = -FixedMul(FINESINE(fa), radius)
+ FixedMul(dist * mobj->movefactor, mobj->tracer->scale);
v[3] = FRACUNIT;
// Swinging Chain.
if (center->flags2 & MF2_STRONGBOX)
{
fixed_t swingmag = FixedMul(FINECOSINE(rot), center->lastlook << FRACBITS);
fixed_t prevswingmag = FINECOSINE(prevrot);
// Swinging Chain.
if (mobj->tracer->flags2 & MF2_STRONGBOX)
{
fixed_t swingmagnitude = FixedMul(FINECOSINE(mobj->threshold), mobj->tracer->lastlook << FRACBITS);
prevswing = FINECOSINE(prevswing);
if ((prevswingmag > 0) != (swingmag > 0)) // just passed its lowest point
dosound = true;
if (!donetwice
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
&& ((prevswing > 0) != (swingmagnitude > 0))) // just passed its lowest point
fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
unit_lengthways[0] = FixedMul(FINESINE(fa), -radius);
unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius);
}
// Rotating Chain.
else
{
angle_t prevfa = (prevrot + mobj->friction) & FINEMASK;
fa = (rot + mobj->friction) & FINEMASK;
if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing
dosound = true;
unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius);
unit_lengthways[2] = FixedMul(FINESINE(fa), radius);
}
// Calculate the angle matrixes for the link.
res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle));
M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
lastthreshold = mobj->threshold;
lastfriction = mobj->friction;
}
if (dosound && (mobj->flags2 & MF2_BOSSNOTRAP))
{
S_StartSound(mobj, mobj->info->activesound);
dosound = false;
}
fa = ((FixedAngle(swingmagnitude) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
if (pos_sideways[3] != mobj->movefactor)
{
if (!unit_sideways[3])
{
unit_sideways[1] = dist;
unit_sideways[0] = unit_sideways[2] = 0;
unit_sideways[3] = FRACUNIT;
v[0] = FixedMul(FINESINE(fa), -radius);
v[2] = FixedMul(FINECOSINE(fa), -radius);
res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle));
M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
}
if (pos_sideways[3] > mobj->movefactor)
{
do
{
pos_sideways[0] -= unit_sideways[0];
pos_sideways[1] -= unit_sideways[1];
pos_sideways[2] -= unit_sideways[2];
}
while ((--pos_sideways[3]) != mobj->movefactor);
}
else
{
do
{
pos_sideways[0] += unit_sideways[0];
pos_sideways[1] += unit_sideways[1];
pos_sideways[2] += unit_sideways[2];
}
while ((++pos_sideways[3]) != mobj->movefactor);
}
}
hnext = mobj->hnext; // just in case the mobj is removed
if (pos_lengthways[3] > mobj->movecount)
{
do
{
pos_lengthways[0] -= unit_lengthways[0];
pos_lengthways[1] -= unit_lengthways[1];
pos_lengthways[2] -= unit_lengthways[2];
}
while ((--pos_lengthways[3]) != mobj->movecount);
}
else if (pos_lengthways[3] < mobj->movecount)
{
do
{
pos_lengthways[0] += unit_lengthways[0];
pos_lengthways[1] += unit_lengthways[1];
pos_lengthways[2] += unit_lengthways[2];
}
while ((++pos_lengthways[3]) != mobj->movecount);
}
P_UnsetThingPosition(mobj);
mobj->x = center->x;
mobj->y = center->y;
mobj->z = center->z;
// Add on the appropriate distances to the center's co-ordinates.
if (pos_lengthways[3])
{
mobj->x += pos_lengthways[0];
mobj->y += pos_lengthways[1];
zstore = pos_lengthways[2] + pos_sideways[2];
}
else
zstore = pos_sideways[2];
mobj->x += pos_sideways[0];
mobj->y += pos_sideways[1];
// Cut the height to align the link with the axis.
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
zstore -= P_MobjFlip(mobj)*mobj->height/4;
else
zstore -= P_MobjFlip(mobj)*mobj->height/2;
mobj->z += zstore;
#if 0 // toaster's testing flashie!
if (!(mobj->movecount & 1) && !(leveltime & TICRATE)) // I had a brainfart and the flashing isn't exactly what I expected it to be, but it's actually much more useful.
mobj->flags2 ^= MF2_DONTDRAW;
#endif
P_SetThingPosition(mobj);
#if 0 // toaster's height-clipping dealie!
if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT))
goto cont;
if ((fa = ((center->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
goto cont;
if (mobj->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
if (mobj->floorz > mobj->z)
zstore = (mobj->floorz - zstore);
else if (mobj->ceilingz < mobj->z)
zstore = (mobj->ceilingz - mobj->height - zstore);
else
goto cont;
zstore = FixedDiv(zstore, dist); // Still needs work... scaling factor is wrong!
P_UnsetThingPosition(mobj);
mobj->x -= FixedMul(unit_lengthways[0], zstore);
mobj->y -= FixedMul(unit_lengthways[1], zstore);
P_SetThingPosition(mobj);
cont:
#endif
mobj = hnext;
}
// Rotating Chain.
else
{
prevswing = (prevswing + mobj->friction) & FINEMASK;
fa = (mobj->threshold + mobj->friction) & FINEMASK;
if (!donetwice
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
&& (!(prevswing > (FINEMASK/2)) && (fa > (FINEMASK/2)))) // completed a full swing
S_StartSound(mobj, mobj->info->activesound);
v[0] = FixedMul(FINECOSINE(fa), radius);
v[2] = FixedMul(FINESINE(fa), radius);
}
// Calculate the angle matrixes for the link.
res = VectorMatrixMultiply(v, *RotateXMatrix(mobj->tracer->threshold << ANGLETOFINESHIFT));
M_Memcpy(&v, res, sizeof(v));
res = VectorMatrixMultiply(v, *RotateZMatrix(mobj->tracer->health << ANGLETOFINESHIFT));
M_Memcpy(&v, res, sizeof(v));
// Cut the height to align the link with the axis.
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
v[2] -= P_MobjFlip(mobj)*mobj->height/4;
else
v[2] -= P_MobjFlip(mobj)*mobj->height/2;
P_UnsetThingPosition(mobj);
// Add on the appropriate distances to the center's co-ordinates.
mobj->x = mobj->tracer->x + v[0];
mobj->y = mobj->tracer->y + v[1];
mobj->z = mobj->tracer->z + v[2];
P_SetThingPosition(mobj);
if (donetwice || P_MobjWasRemoved(mobj))
return;
if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT))
return;
if ((fa = ((mobj->tracer->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
return;
if (mobj->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
// Variable reuse
if (mobj->floorz > mobj->z)
dist = (mobj->floorz - mobj->tracer->z);
else if (mobj->ceilingz < mobj->z)
dist = (mobj->ceilingz - mobj->tracer->z);
else
return;
if ((dist = FixedDiv(dist, v[2])) > FRACUNIT)
return;
radius = FixedMul(radius, dist);
donetwice = true;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
goto maceretry;
}
static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
@ -6664,13 +6757,6 @@ void P_MobjThinker(mobj_t *mobj)
}
}
if (mobj->flags2 & MF2_MACEROTATE)
{
P_MaceRotate(mobj);
if (P_MobjWasRemoved(mobj))
return;
}
// Special thinker for scenery objects
if (mobj->flags & MF_SCENERY)
{
@ -6687,6 +6773,18 @@ void P_MobjThinker(mobj_t *mobj)
switch (mobj->type)
{
case MT_MACEPOINT:
case MT_CHAINMACEPOINT:
case MT_SPRINGBALLPOINT:
case MT_CHAINPOINT:
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
case MT_HIDDEN_SLING:
// The following was pretty good, but liked breaking whenever mobj->lastlook changed.
//P_MaceRotate(mobj, ((leveltime + 1) * mobj->lastlook), (leveltime * mobj->lastlook));
P_MaceRotate(mobj, mobj->movedir + mobj->lastlook, mobj->movedir);
mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK;
break;
case MT_HOOP:
if (mobj->fuse > 1)
P_MoveHoop(mobj);
@ -7337,19 +7435,6 @@ void P_MobjThinker(mobj_t *mobj)
}
}
break;
case MT_CHAINPOINT:
case MT_CHAINMACEPOINT:
if (leveltime & 1)
{
if (mobj->lastlook > mobj->movecount)
mobj->lastlook--;
/*
if (mobj->threshold > mobj->movefactor)
mobj->threshold -= FRACUNIT;
else if (mobj->threshold < mobj->movefactor)
mobj->threshold += FRACUNIT;*/
}
break;
case MT_EGGCAPSULE:
if (!mobj->reactiontime)
{
@ -8615,6 +8700,13 @@ void P_RemoveMobj(mobj_t *mobj)
// Remove any references to other mobjs.
P_SetTarget(&mobj->target, P_SetTarget(&mobj->tracer, NULL));
if (mobj->hnext && !P_MobjWasRemoved(mobj->hnext))
P_SetTarget(&mobj->hnext->hprev, mobj->hprev);
if (mobj->hprev && !P_MobjWasRemoved(mobj->hprev))
P_SetTarget(&mobj->hprev->hnext, mobj->hnext);
P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL));
// free block
// DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error.
if (mobj->flags & MF_NOTHINK && !mobj->thinker.next)
@ -9301,6 +9393,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj_t *mobj;
fixed_t x, y, z;
subsector_t *ss;
boolean doangle = true;
if (!mthing->type)
return; // Ignore type-0 things as NOPs
@ -9706,11 +9799,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
{
fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor;
fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor;
angle_t mspokeangle;
mobjtype_t chainlink, macetype, firsttype, linktype;
boolean mdoall = true;
mobj_t *spawnee;
boolean mdosound, mdocenter;
mobj_t *spawnee = NULL, *hprev = mobj;
mobjflag_t mflagsapply;
mobjflag2_t mflags2apply;
mobjeflag_t meflagsapply;
@ -9747,8 +9840,10 @@ ML_EFFECT4 : Don't clip inside the ground
mlength = abs(lines[line].dx >> FRACBITS);
mspeed = abs(lines[line].dy >> (FRACBITS - 4));
mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360;
if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed)
mmaxspeed = mspeed << 1;
if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset>>FRACBITS) < 0)
mminlength = 0;
else if (mminlength > mlength-1)
mminlength = mlength-1;
mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360;
myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360;
@ -9767,30 +9862,29 @@ ML_EFFECT4 : Don't clip inside the ground
mpinch = mroll = mnumnospokes = mwidth = 0;
CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n"
"Length is %d\n"
"Length is %d (minus %d)\n"
"Speed is %d\n"
"Phase is %d\n"
"Yaw is %d\n"
"Pitch is %d\n"
"Max. speed is %d\n"
"No. of spokes is %d\n"
"No. of spokes is %d (%d antispokes)\n"
"Pinch is %d\n"
"Roll is %d\n"
"No. of antispokes is %d\n"
"Width is %d\n",
sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth);
sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth);
if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
mnumnospokes = mnumspokes/mnumnospokes;
else
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0);
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0);
mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook;
mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->angle = FixedAngle(myaw*FRACUNIT);
doangle = false;
mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->friction = mmaxspeed;
mobj->movefactor = mpinch;
mobj->movedir = 0;
// Mobjtype selection
switch(mobj->type)
@ -9828,7 +9922,7 @@ ML_EFFECT4 : Don't clip inside the ground
break;
}
if (!macetype)
if (!macetype && !chainlink)
break;
if (mobj->type != MT_CHAINPOINT)
@ -9857,7 +9951,7 @@ ML_EFFECT4 : Don't clip inside the ground
mmin = mnumspokes;
// Make the links the same type as the end - repeated below
if ((mobj->type != MT_CHAINPOINT) && ((lines[line].flags & ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or
if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or
{
linktype = macetype;
radiusfactor = 2; // Double the radius.
@ -9865,8 +9959,10 @@ ML_EFFECT4 : Don't clip inside the ground
else
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
widthfactor = ((firsttype == chainlink) ? 1 : 2);
mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT));
mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0));
mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0);
meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0);
msound = ((firsttype == chainlink) ? 0 : (mwidth & 1));
@ -9875,25 +9971,27 @@ ML_EFFECT4 : Don't clip inside the ground
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
P_SetTarget(&spawnee->tracer, mobj);\
spawnee->threshold = mphase;\
spawnee->friction = mroll;\
spawnee->movefactor = mwidth;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply
#define makemace(mobjtype, dist, moreflags2) {\
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
P_SetTarget(&spawnee->tracer, mobj);\
spawnee->threshold = mphase;\
spawnee->friction = mroll;\
spawnee->movefactor = mwidthset;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply;\
P_SetTarget(&hprev->hnext, spawnee);\
P_SetTarget(&spawnee->hprev, hprev);\
hprev = spawnee;\
}
domaceagain:
mnumspokesset = mnumspokes;
if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link
{ spawnee = makemace(macetype, 0, MF2_AMBUSH); }
mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL));
mdocenter = (macetype && (lines[line].flags & ML_EFFECT3));
// The actual spawning of spokes
while (mnumspokesset-- > 0)
while (mnumspokes-- > 0)
{
// Offsets
if (lines[line].flags & ML_EFFECT1) // Swinging
@ -9901,14 +9999,14 @@ domaceagain:
else // Spinning
mphase = (mphase - mspokeangle) & FINEMASK;
if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke
if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke
{
if (mobj->type != MT_CHAINMACEPOINT)
continue;
firsttype = linktype = chainlink;
mlengthset = 1 + (mlength - 1)*radiusfactor;
radiusfactor = 1;
mmaxlength = 1 + (mlength - 1)*radiusfactor;
radiusfactor = widthfactor = 1;
}
else
{
@ -9927,36 +10025,73 @@ domaceagain:
}
firsttype = macetype;
widthfactor = 2;
}
mlengthset = mlength;
mmaxlength = mlength;
}
mwidthset = mwidth;
mlengthset = mminlength;
if (mdocenter) // Innermost mace/link
makemace(macetype, 0, 0);
// Out from the center...
if (linktype)
{
while ((++mlengthset) < mmaxlength)
makemace(linktype, radiusfactor*mlengthset, 0);
}
else
mlengthset = mmaxlength;
// Outermost mace/link
spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
if (firsttype)
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
if (!mwidth)
{
if (mdosound && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
else
{
// Across the bar!
if (!firsttype)
mwidthset = -mwidth;
else if (mwidth > 0)
{
while ((mwidthset -= widthfactor) > -mwidth)
{
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
}
else
{
while ((mwidthset += widthfactor) < -mwidth)
{
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
}
mwidth = -mwidth;
if (!mdoall || !linktype)
continue;
// Outermost mace/link again!
if (firsttype)
makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
// The rest of the links
while (mlengthset > 0)
{ spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); }
}
// ...and then back into the center!
if (linktype)
while (mlengthset > mminlength)
makemace(linktype, radiusfactor*(mlengthset--), 0);
if (mwidth > 0)
{
mwidth *= -1;
goto domaceagain;
}
else if (mwidth != 0)
{
if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0)
break;
mdoall = false;
goto domaceagain;
if (mdocenter) // Innermost mace/link
makemace(macetype, 0, 0);
}
}
#undef makemace
@ -10261,16 +10396,16 @@ domaceagain:
}
}
if (doangle)
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
// ignore MTF_ flags and return early
if (i == MT_NIGHTSBUMPER)
{
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
mthing->mobj = mobj;
return;
}
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if ((mthing->options & MTF_AMBUSH)
&& (mthing->options & MTF_OBJECTSPECIAL)
&& (mobj->flags & MF_PUSHABLE))

View File

@ -194,7 +194,6 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
// free: to and including 1<<31
} mobjflag2_t;

View File

@ -10444,21 +10444,10 @@ void P_PlayerAfterThink(player_t *player)
player->secondjump = 0;
player->pflags &= ~PF_THOKKED;
if (cmd->forwardmove > 0)
{
if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction;
}
else if (cmd->forwardmove < 0)
{
if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount;
}
if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
&& !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode?
{
player->mo->tracer->tracer->health += cmd->sidemove;
player->mo->tracer->tracer->angle += cmd->sidemove<<ANGLETOFINESHIFT;
player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
if (!demoplayback || P_AnalogMove(player))