* Optimise them even further... AGAIN! Using an offset-based system rather than a multiplication-based one...

* Again, tweak the spawning code to take maximum advantage of these gains.
* Fix potential crashes with MT_NULL mace/chain types supplied.
* #ifdef out the height-clipping code. It needs more TLC than I can give it right now, and the existing behaviour is less obviously broken (sadly enough).
* Fix chainmace points, which were apparently broken without anyone realising.
This commit is contained in:
toasterbabe 2018-04-03 01:10:10 +01:00
parent 4051ae8915
commit 156cc031ea

View file

@ -6180,11 +6180,11 @@ static void P_NightsItemChase(mobj_t *thing)
// //
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
{ {
TVector unit, baseuo, unitoffset; TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
TVector *res; TVector *res;
fixed_t radius, dist, mag, zstore; fixed_t radius, dist, zstore;
angle_t fa; angle_t fa;
boolean donetwice, dosound = false; boolean dosound = false;
mobj_t *mobj = center->hnext, *hnext = NULL; mobj_t *mobj = center->hnext, *hnext = NULL;
INT32 rot = (baserot &= FINEMASK); INT32 rot = (baserot &= FINEMASK);
@ -6193,7 +6193,7 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
INT32 lastthreshold = FINEMASK; // needs to never be equal at start of loop INT32 lastthreshold = FINEMASK; // needs to never be equal at start of loop
fixed_t lastfriction = INT32_MIN; // ditto; almost certainly never, but... fixed_t lastfriction = INT32_MIN; // ditto; almost certainly never, but...
fixed_t movefac = unitoffset[0] = unitoffset[1] = unitoffset[2] = baseuo[3] = 0; 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) while (mobj)
{ {
@ -6211,10 +6211,15 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
rot = (baserot + mobj->threshold) & FINEMASK; rot = (baserot + mobj->threshold) & FINEMASK;
prevrot = (baseprevrot + mobj->threshold) & FINEMASK; prevrot = (baseprevrot + mobj->threshold) & FINEMASK;
fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT); // mpinch pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
radius = FINECOSINE(fa);
unit[1] = -FixedMul(FINESINE(fa), radius); dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
unit[3] = center->scale; dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale));
fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
radius = FixedMul(dist, FINECOSINE(fa));
unit_lengthways[1] = -FixedMul(dist, FINESINE(fa));
unit_lengthways[3] = FRACUNIT;
// Swinging Chain. // Swinging Chain.
if (center->flags2 & MF2_STRONGBOX) if (center->flags2 & MF2_STRONGBOX)
@ -6224,12 +6229,11 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
if ((prevswingmag > 0) != (swingmag > 0)) // just passed its lowest point if ((prevswingmag > 0) != (swingmag > 0)) // just passed its lowest point
dosound = true; dosound = true;
//S_StartSound(mobj, mobj->info->activesound);
fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK; fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
unit[0] = FixedMul(FINESINE(fa), -radius); unit_lengthways[0] = FixedMul(FINESINE(fa), -radius);
unit[2] = FixedMul(FINECOSINE(fa), -radius); unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius);
} }
// Rotating Chain. // Rotating Chain.
else else
@ -6240,15 +6244,15 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing
dosound = true; dosound = true;
unit[0] = FixedMul(FINECOSINE(fa), radius); unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius);
unit[2] = FixedMul(FINESINE(fa), radius); unit_lengthways[2] = FixedMul(FINESINE(fa), radius);
} }
// Calculate the angle matrixes for the link. // Calculate the angle matrixes for the link.
res = VectorMatrixMultiply(unit, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&unit, res, sizeof(unit)); M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
res = VectorMatrixMultiply(unit, *RotateZMatrix(center->angle)); res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle));
M_Memcpy(&unit, res, sizeof(unit)); M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
lastthreshold = mobj->threshold; lastthreshold = mobj->threshold;
lastfriction = mobj->friction; lastfriction = mobj->friction;
@ -6260,40 +6264,65 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
dosound = false; dosound = false;
} }
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); if (pos_sideways[3] != mobj->movefactor)
if (dist*mobj->movefactor != movefac)
{ {
if (!baseuo[3]) if (!unit_sideways[3])
{ {
baseuo[1] = FRACUNIT; unit_sideways[1] = dist;
baseuo[0] = baseuo[2] = 0; unit_sideways[0] = unit_sideways[2] = 0;
baseuo[3] = center->scale; unit_sideways[3] = FRACUNIT;
res = VectorMatrixMultiply(baseuo, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&baseuo, res, sizeof(baseuo)); M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
res = VectorMatrixMultiply(baseuo, *RotateZMatrix(center->angle)); res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle));
M_Memcpy(&baseuo, res, sizeof(baseuo)); M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
} }
if (mobj->movefactor) if (pos_sideways[3] > mobj->movefactor)
{ {
movefac = dist*mobj->movefactor; do
unitoffset[0] = FixedMul(movefac, baseuo[0]); {
unitoffset[1] = FixedMul(movefac, baseuo[1]); pos_sideways[0] -= unit_sideways[0];
unitoffset[2] = FixedMul(movefac, baseuo[2]); pos_sideways[1] -= unit_sideways[1];
pos_sideways[2] -= unit_sideways[2];
}
while ((--pos_sideways[3]) != mobj->movefactor);
} }
else else
movefac = unitoffset[0] = unitoffset[1] = unitoffset[2] = 0; {
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 hnext = mobj->hnext; // just in case the mobj is removed
// Radius of the link's rotation. if (pos_lengthways[3] > mobj->movecount)
mag = (dist * mobj->movecount) + mobj->extravalue1; {
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);
}
donetwice = false;
maceretry:
P_UnsetThingPosition(mobj); P_UnsetThingPosition(mobj);
mobj->x = center->x; mobj->x = center->x;
@ -6301,17 +6330,17 @@ maceretry:
mobj->z = center->z; mobj->z = center->z;
// Add on the appropriate distances to the center's co-ordinates. // Add on the appropriate distances to the center's co-ordinates.
if (mag) if (pos_lengthways[3])
{ {
mobj->x += FixedMul(unit[0], mag); mobj->x += pos_lengthways[0];
mobj->y += FixedMul(unit[1], mag); mobj->y += pos_lengthways[1];
zstore = FixedMul(unit[2], mag) + unitoffset[2]; zstore = pos_lengthways[2] + pos_sideways[2];
} }
else else
zstore = unitoffset[2]; zstore = pos_sideways[2];
mobj->x += unitoffset[0]; mobj->x += pos_sideways[0];
mobj->y += unitoffset[1]; mobj->y += pos_sideways[1];
// Cut the height to align the link with the axis. // Cut the height to align the link with the axis.
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN) if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
@ -6322,41 +6351,40 @@ maceretry:
mobj->z += zstore; mobj->z += zstore;
#if 0 // toaster's testing flashie! #if 0 // toaster's testing flashie!
if (!donetwice && mobj->movefactor != -5 && !(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. 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; mobj->flags2 ^= MF2_DONTDRAW;
#endif #endif
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
if (!mag || donetwice || P_MobjWasRemoved(mobj)) #if 0 // toaster's height-clipping dealie!
if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT))
goto cont; goto cont;
if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) 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 ((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
goto cont; goto cont;
if (mobj->subsector->sector->ffloors) if (mobj->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2); P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
// Variable reuse
if (mobj->floorz > mobj->z) if (mobj->floorz > mobj->z)
dist = (mobj->floorz - mobj->tracer->z); zstore = (mobj->floorz - zstore);
else if (mobj->ceilingz < mobj->z) else if (mobj->ceilingz < mobj->z)
dist = (mobj->ceilingz - mobj->tracer->z); zstore = (mobj->ceilingz - mobj->height - zstore);
else else
goto cont; goto cont;
if ((dist = FixedDiv(dist, zstore)) > FRACUNIT) zstore = FixedDiv(zstore, dist); // Still needs work... scaling factor is wrong!
goto cont;
mag = FixedMul(mag, dist); P_UnsetThingPosition(mobj);
donetwice = true;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); mobj->x -= FixedMul(unit_lengthways[0], zstore);
goto maceretry; mobj->y -= FixedMul(unit_lengthways[1], zstore);
P_SetThingPosition(mobj);
cont: cont:
#endif
mobj = hnext; mobj = hnext;
} }
} }
@ -9771,7 +9799,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
case MT_FIREBARPOINT: case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT: case MT_CUSTOMMACEPOINT:
{ {
fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, 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; angle_t mspokeangle;
mobjtype_t chainlink, macetype, firsttype, linktype; mobjtype_t chainlink, macetype, firsttype, linktype;
boolean mdosound, mdocenter; boolean mdosound, mdocenter;
@ -9848,7 +9876,7 @@ ML_EFFECT4 : Don't clip inside the ground
if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
mnumnospokes = mnumspokes/mnumnospokes; mnumnospokes = mnumspokes/mnumnospokes;
else else
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0); mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0);
mobj->lastlook = mspeed; mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook; mobj->movecount = mobj->lastlook;
@ -9894,7 +9922,7 @@ ML_EFFECT4 : Don't clip inside the ground
break; break;
} }
if (!macetype) if (!macetype && !chainlink)
break; break;
if (mobj->type != MT_CHAINPOINT) if (mobj->type != MT_CHAINPOINT)
@ -9958,7 +9986,7 @@ ML_EFFECT4 : Don't clip inside the ground
} }
mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL));
mdocenter = (lines[line].flags & ML_EFFECT3); mdocenter = (macetype && (lines[line].flags & ML_EFFECT3));
// The actual spawning of spokes // The actual spawning of spokes
while (mnumspokes-- > 0) while (mnumspokes-- > 0)
@ -9999,6 +10027,7 @@ ML_EFFECT4 : Don't clip inside the ground
mmaxlength = mlength; mmaxlength = mlength;
} }
widthfactor = ((firsttype == chainlink) ? 1 : 2);
mwidthset = mwidth; mwidthset = mwidth;
//fixed_t base = 0; //fixed_t base = 0;
@ -10009,11 +10038,18 @@ ML_EFFECT4 : Don't clip inside the ground
//base = mlengthset*((mobjinfo[macetype].speed) ? mobjinfo[macetype].speed : mobjinfo[MT_SMALLMACECHAIN].speed); //base = mlengthset*((mobjinfo[macetype].speed) ? mobjinfo[macetype].speed : mobjinfo[MT_SMALLMACECHAIN].speed);
while ((++mlengthset) < mmaxlength) // Out from the center...
makemace(linktype, radiusfactor*mlengthset, 0); if (linktype)
{
while ((++mlengthset) < mmaxlength)
makemace(linktype, radiusfactor*mlengthset, 0);
}
else
mlengthset = mmaxlength;
// Outermost mace/link // Outermost mace/link
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); if (firsttype)
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (!mwidth) if (!mwidth)
{ {
@ -10022,18 +10058,37 @@ ML_EFFECT4 : Don't clip inside the ground
} }
else else
{ {
while ((mwidthset -= ((firsttype == chainlink) ? 1 : 2)) > -mwidth) // Across the bar!
if (!firsttype)
mwidthset = -mwidth;
else if (mwidth > 0)
{ {
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); while ((mwidthset -= widthfactor) > -mwidth)
if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? {
spawnee->flags2 |= MF2_BOSSNOTRAP; 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;
// Outermost mace/link again! // Outermost mace/link again!
makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); if (firsttype)
makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
while (mlengthset > mminlength) // ...and then back into the center!
makemace(linktype, radiusfactor*(mlengthset--), 0); if (linktype)
while (mlengthset > mminlength)
makemace(linktype, radiusfactor*(mlengthset--), 0);
if (mdocenter) // Innermost mace/link if (mdocenter) // Innermost mace/link
makemace(macetype, 0, 0); makemace(macetype, 0, 0);