From 88578f0534d053adadaeffce42bccf5b83339d95 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 15 Sep 2019 23:36:55 -0400 Subject: [PATCH] Moving capsules --- src/k_battle.c | 88 +++++++++++++++++++++++++---- src/p_mobj.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 14 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index dafabf670..abf1d4540 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -233,6 +233,67 @@ void K_CheckBumpers(void) P_DoPlayerExit(&players[i]); } +static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) +{ + UINT8 sequence = mt->extrainfo-1; + fixed_t speed = (FRACUNIT >> 3) * mt->angle; + boolean backandforth = (mt->options & MTF_AMBUSH); + boolean reverse = (mt->options & MTF_OBJECTSPECIAL); + mobj_t *mo2; + mobj_t *target = NULL; + thinker_t *th; + + // Find the inital target + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (reverse) // Use the highest waypoint number as first + { + if (mo2->health != 0) + { + if (target == NULL) + target = mo2; + else if (mo2->health > target->health) + target = mo2; + } + } + else // Use the lowest waypoint number as first + { + if (mo2->health == 0) + target = mo2; + } + } + } + + if (!target) + { + CONS_Alert(CONS_WARNING, "No target waypoint found for moving capsule (seq: #%d)\n", sequence); + return; + } + + P_SetTarget(&mobj->target, target); + mobj->lastlook = sequence; + mobj->movecount = target->health; + mobj->movefactor = speed; + + if (backandforth) + mobj->cusval = 1; + + if (reverse) + mobj->cvmem = -1; + else + mobj->cvmem = 1; +} + void K_SpawnBattleCapsules(void) { mapthing_t *mt; @@ -269,6 +330,7 @@ void K_SpawnBattleCapsules(void) UINT8 numfloors = 1; mobj_t *mobj = NULL; boolean fly = true; + UINT8 j; mt->mobj = NULL; @@ -352,9 +414,9 @@ void K_SpawnBattleCapsules(void) mobj->flags2 |= MF2_OBJECTFLIP; } - for (i = 0; i < numfloors; i++) + for (j = 0; j < numfloors; j++) { - if (z == floorheights[i]) + if (z == floorheights[j]) { fly = false; break; @@ -368,6 +430,10 @@ void K_SpawnBattleCapsules(void) mobj->extravalue1 = 1; // Set extravalue1 for later reference } + // Moving capsules! + if (mt->extrainfo && mt->angle) + K_SetupMovingCapsule(mt, mobj); + // Moved from P_SpawnMobj due to order of operations mumbo jumbo { mobj_t *cur, *prev = mobj; @@ -392,16 +458,17 @@ void K_SpawnBattleCapsules(void) prev = cur; // Supports on the bottom - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = i; + cur->extravalue1 = j; - // TODO: use karma bomb wheels on grounded, moving capsules - if (mobj->extravalue1) + if (mobj->extravalue1) // Flying capsule, moving or not P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY); + else if (mobj->target && !P_MobjWasRemoved(mobj->target)) // Grounded, moving capsule + P_SetMobjState(cur, S_KARMAWHEEL); else - P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); + P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); // Grounded, stationary capsule P_SetTarget(&cur->target, mobj); P_SetTarget(&cur->hprev, prev); @@ -410,12 +477,12 @@ void K_SpawnBattleCapsules(void) } // Side paneling - for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) { cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = i; + cur->extravalue1 = j; - if (i & 1) + if (j & 1) P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2); else P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1); @@ -427,7 +494,6 @@ void K_SpawnBattleCapsules(void) } } - mobj->angle = FixedAngle(mt->angle * FRACUNIT); mt->mobj = mobj; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index d70c71e0f..4bab95137 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9130,7 +9130,147 @@ void P_MobjThinker(mobj_t *mobj) mobj->momz = sine/2; } - // TODO: insert moving capsule code here + // Moving capsules + if (mobj->target && !P_MobjWasRemoved(mobj->target)) + { + fixed_t speed = mobj->movefactor; + UINT8 sequence = mobj->lastlook; + UINT8 num = mobj->movecount; + boolean backandforth = mobj->cusval; + SINT8 direction = mobj->cvmem; + mobj_t *next = NULL; + thinker_t *th; + fixed_t dist, momx, momy, momz; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + if (speed <= dist) + { + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + mobj_t *mo2; + + speed -= dist; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + mobj->z = mobj->target->z; + P_SetThingPosition(mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + // Onto the next waypoint! + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + } + + // Are we at the end of the waypoint chain? + // If so, search again for the first/previous waypoint (depending on settings) + if (next == NULL) + { + if (backandforth) + { + mobj->cvmem = -mobj->cvmem; + direction = mobj->cvmem; + } + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (backandforth) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + else + { + if (direction < 0) + { + if (next == NULL || mo2->health > next->health) + next = mo2; + } + else + { + if (next == NULL || mo2->health < next->health) + next = mo2; + } + } + } + } + } + + if (next && !P_MobjWasRemoved(next)) + { + P_SetTarget(&mobj->target, next); + mobj->movecount = next->health; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + CONS_Alert(CONS_WARNING, "Moving capsule could not find next waypoint! (seq: %d)\n", sequence); + P_SetTarget(&mobj->target, NULL); + } + } + } if (flip == -1) bottom = mobj->z + mobj->height; @@ -9159,7 +9299,9 @@ void P_MobjThinker(mobj_t *mobj) newz += (80 * mobj->scale * flip); else if (state == S_BATTLECAPSULE_BUTTON) newz += (108 * mobj->scale * flip); - else if (state == S_BATTLECAPSULE_SUPPORT || state == S_BATTLECAPSULE_SUPPORTFLY) + else if (state == S_BATTLECAPSULE_SUPPORT + || state == S_BATTLECAPSULE_SUPPORTFLY + || state == S_KARMAWHEEL) { fixed_t offx = mobj->radius; fixed_t offy = mobj->radius; @@ -9173,7 +9315,8 @@ void P_MobjThinker(mobj_t *mobj) newx += offx; newy += offy; } - else if (state == S_BATTLECAPSULE_SIDE1 || state == S_BATTLECAPSULE_SIDE2) + else if (state == S_BATTLECAPSULE_SIDE1 + || state == S_BATTLECAPSULE_SIDE2) { fixed_t offset = 48 * mobj->scale; angle_t angle = (ANGLE_45 * cur->extravalue1);