diff --git a/src/k_kart.c b/src/k_kart.c index 776b30b7..72447698 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2083,7 +2083,7 @@ void K_DriftDustHandling(mobj_t *spawner) } } -static mobj_t *K_FindLastTrailMobj(player_t *player) // YUCK, i hate this! +static mobj_t *K_FindLastTrailMobj(player_t *player) { mobj_t *trail = player->mo->hnext; @@ -2473,6 +2473,165 @@ void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) } } +void K_RepairOrbitChain(mobj_t *orbit) +{ + mobj_t *cachenext = orbit->hnext; + + // First, repair the chain + if (orbit->hnext && !P_MobjWasRemoved(orbit->hnext)) + { + P_SetTarget(&orbit->hnext->hprev, orbit->hprev); + P_SetTarget(&orbit->hnext, NULL); + } + + if (orbit->hprev && !P_MobjWasRemoved(orbit->hprev)) + { + P_SetTarget(&orbit->hprev->hnext, cachenext); + P_SetTarget(&orbit->hprev, NULL); + } + + // Then recount to make sure item amount is correct + if (orbit->target && orbit->target->player) + { + mobj_t *cur = NULL; + mobj_t *prev = NULL; + INT32 num = 0; + + if (orbit->target->hnext) + cur = orbit->target->hnext; + + while (cur && !P_MobjWasRemoved(cur) && cur != orbit->target->player->mo) + { + num++; + prev = cur; + cur = cur->hnext; + if (num > orbit->target->player->kartstuff[k_itemamount]) + P_RemoveMobj(prev); + } + + if (orbit->target->player->kartstuff[k_itemamount] != num) + orbit->target->player->kartstuff[k_itemamount] = num; + } +} + +static void K_MoveHeldObjects(player_t *player) +{ + if (!player->mo) + return; + + if (!player->mo->hnext) + return; + + switch (player->mo->hnext->type) + { + case MT_GREENSHIELD: // Kart orbit items + case MT_JAWZ_SHIELD: + { + mobj_t *cur = player->mo->hnext; + + while (cur && !P_MobjWasRemoved(cur) && cur != player->mo) + { + const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius); // mobj's distance from its Target, or Radius. + fixed_t z; + + cur->angle -= ANGLE_90; + cur->angle += FixedAngle(cur->info->speed); + + // If the player is on the ceiling, then flip your items as well. + if (player && player->mo->eflags & MFE_VERTICALFLIP) + cur->eflags |= MFE_VERTICALFLIP; + else + cur->eflags &= ~MFE_VERTICALFLIP; + + // Shrink your items if the player shrunk too. + cur->scale = player->mo->scale; + + if (P_MobjFlip(cur) > 0) + z = player->mo->z; + else + z = player->mo->z + player->mo->height - cur->height; + + cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player + P_TeleportMove(cur, player->mo->x, player->mo->y, z); + cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), radius); + cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), radius); + cur->flags &= ~MF_NOCLIPTHING; + if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) + P_SlideMove(cur, true); + if (P_IsObjectOnGround(player->mo)) + { + if (P_MobjFlip(cur) > 0) + { + if (cur->floorz > player->mo->z - cur->height) + z = cur->floorz; + } + else + { + if (cur->ceilingz < player->mo->z + player->mo->height + cur->height) + z = cur->ceilingz - cur->height; + } + } + cur->z = z; + cur->momx = cur->momy = 0; + cur->angle += ANGLE_90; + + cur = cur->hnext; + } + } + break; + case MT_BANANA_SHIELD: // Kart trailing items + case MT_SSMINE_SHIELD: + case MT_FAKESHIELD: + { + mobj_t *cur = player->mo->hnext; + mobj_t *targ = player->mo; + + while (cur && !P_MobjWasRemoved(cur) && cur != player->mo) + { + const fixed_t spacing = FixedMul(3*cur->info->radius/2, player->mo->scale); + angle_t ang; + fixed_t targx; + fixed_t targy; + fixed_t targz; + fixed_t speed; + fixed_t dist = spacing; + + if (cur != player->mo->hnext) + { + targ = cur->hprev; + dist = spacing/2; + } + + if (!targ || P_MobjWasRemoved(targ)) + continue; + + ang = targ->angle; + targx = targ->x + P_ReturnThrustX(cur, ang + ANGLE_180, dist); + targy = targ->y + P_ReturnThrustY(cur, ang + ANGLE_180, dist); + targz = targ->z; + speed = FixedMul(R_PointToDist2(cur->x, cur->y, targx, targy), 3*FRACUNIT/4); + if (P_IsObjectOnGround(targ)) + targz = cur->floorz; + + cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy); + + if (speed > dist) + P_InstaThrust(cur, cur->angle, speed-dist); + + P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 3*FRACUNIT/4) - gravity, false); + + if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) + P_TeleportMove(cur, targx, targy, cur->z); + + cur = cur->hnext; + } + } + break; + default: + break; + } +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -2675,6 +2834,9 @@ void K_KartPlayerAfterThink(player_t *player) if (!(player->mo->state->frame & FF_FULLBRIGHT)) player->mo->frame &= ~FF_FULLBRIGHT; } + + // Move held objects (Bananas, Orbinaut, etc) + K_MoveHeldObjects(player); } // Returns false if this player being placed here causes them to collide with any other player @@ -3187,31 +3349,40 @@ void K_MoveKartPlayer(player_t *player, boolean onground) case KITEM_ORBINAUT: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { + angle_t newangle; + fixed_t newx; + fixed_t newy; INT32 moloop; + mobj_t *mo; + mobj_t *prev = NULL; + //K_PlayTauntSound(player->mo); player->kartstuff[k_itemheld] = 1; player->pflags |= PF_ATTACKDOWN; - //K_PlayTauntSound(player->mo); S_StartSound(player->mo, sfx_s3k3a); for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); + newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); mo = P_SpawnMobj(newx, newy, player->mo->z, MT_GREENSHIELD); - if (mo) + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + if (moloop > 0) { - mo->threshold = 10; - mo->lastlook = moloop+1; - P_SetTarget(&mo->target, player->mo); - mo->angle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + P_SetTarget(&mo->hprev, prev); + if (prev != NULL) + P_SetTarget(&prev->hnext, mo); } + else + P_SetTarget(&player->mo->hnext, mo); + if (moloop == player->kartstuff[k_itemamount]-1) // Complete loop for orbit items + P_SetTarget(&mo->hnext, player->mo); + prev = mo; } } else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown @@ -3228,31 +3399,40 @@ void K_MoveKartPlayer(player_t *player, boolean onground) case KITEM_JAWZ: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { + angle_t newangle; + fixed_t newx; + fixed_t newy; INT32 moloop; + mobj_t *mo; + mobj_t *prev = NULL; + //K_PlayTauntSound(player->mo); player->kartstuff[k_itemheld] = 1; player->pflags |= PF_ATTACKDOWN; - //K_PlayTauntSound(player->mo); S_StartSound(player->mo, sfx_s3k3a); for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); + newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); mo = P_SpawnMobj(newx, newy, player->mo->z, MT_JAWZ_SHIELD); - if (mo) + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + if (moloop > 0) { - mo->threshold = 10; - mo->lastlook = moloop+1; - P_SetTarget(&mo->target, player->mo); - mo->angle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + P_SetTarget(&mo->hprev, prev); + if (prev != NULL) + P_SetTarget(&prev->hnext, mo); } + else + P_SetTarget(&player->mo->hnext, mo); + if (moloop == player->kartstuff[k_itemamount]-1) // Complete loop for orbit items + P_SetTarget(&mo->hnext, player->mo); + prev = mo; } } else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown diff --git a/src/k_kart.h b/src/k_kart.h index cb7dce21..f046652a 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -36,6 +36,7 @@ void K_DriftDustHandling(mobj_t *spawner); void K_DoSneaker(player_t *player, boolean doPFlag); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); +void K_RepairOrbitChain(mobj_t *orbit); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); void K_StripItems(player_t *player); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1ec57030..9a47bf9d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2149,6 +2149,16 @@ static int lib_kKillBananaChain(lua_State *L) return 0; } +static int lib_kRepairOrbitChain(lua_State *L) +{ + mobj_t *orbit = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!orbit) + return LUA_ErrInvalid(L, "mobj_t"); + K_RepairOrbitChain(orbit); + return 0; +} + static int lib_kMomentumToFacing(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2377,6 +2387,7 @@ static luaL_Reg lib[] = { {"K_DoSneaker",lib_kDoSneaker}, {"K_DoPogoSpring",lib_kDoPogoSpring}, {"K_KillBananaChain",lib_kKillBananaChain}, + {"K_RepairOrbitChain",lib_kRepairOrbitChain}, {"K_MomentumToFacing",lib_kMomentumToFacing}, {"K_GetKartSpeed",lib_kGetKartSpeed}, {"K_GetKartAccel",lib_kGetKartAccel}, diff --git a/src/p_inter.c b/src/p_inter.c index 117c2459..e7b5fcb7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2122,7 +2122,13 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) } else if ((target->type == MT_GREENSHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) // orbit items || (target->type == MT_JAWZ_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_JAWZ)) + { target->target->player->kartstuff[k_itemamount]--; + if (target->lastlook != 0) + { + K_RepairOrbitChain(target); + } + } if (target->target->player->kartstuff[k_itemamount] < 0) target->target->player->kartstuff[k_itemamount] = 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index 23fa23bf..44683b64 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6697,63 +6697,6 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - fixed_t z; - const fixed_t radius = FixedHypot(mobj->target->radius, mobj->target->radius) + FixedHypot(mobj->radius, mobj->radius); // mobj's distance from its Target, or Radius. - - mobj->angle -= ANGLE_90; - mobj->angle += FixedAngle(mobj->info->speed); - - // If the player is on the ceiling, then flip your items as well. - if (mobj->target->player && mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - } - else - { - mobj->eflags &= ~MFE_VERTICALFLIP; - } - - // Shrink your items if the player shrunk too. - if (mobj->target->player) - mobj->scale = mobj->target->scale; - - if (P_MobjFlip(mobj) > 0) - { - z = mobj->target->z; - } - else - { - z = mobj->target->z + mobj->target->height - mobj->height; - } - - mobj->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, z); - mobj->momx = FixedMul(FINECOSINE(mobj->angle>>ANGLETOFINESHIFT),radius); - mobj->momy = FixedMul(FINESINE(mobj->angle>>ANGLETOFINESHIFT), radius); - mobj->flags &= ~MF_NOCLIPTHING; - if (!P_TryMove(mobj, mobj->target->x + mobj->momx, mobj->target->y + mobj->momy, true)) - P_SlideMove(mobj, true); - if (P_IsObjectOnGround(mobj->target)) - { - if (P_MobjFlip(mobj) > 0) - { - if (mobj->floorz > mobj->target->z - mobj->height) - { - z = mobj->floorz; - } - } - else - { - if (mobj->ceilingz < mobj->target->z + mobj->target->height + mobj->height) - { - z = mobj->ceilingz - mobj->height; - } - } - } - mobj->z = z; - mobj->momx = mobj->momy = 0; - mobj->angle += ANGLE_90; - // Was this so hard? if ((mobj->type == MT_GREENSHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_ORBINAUT) || (mobj->type == MT_JAWZ_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_JAWZ) @@ -6779,52 +6722,6 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - if (mobj->lastlook == 1) - { - const fixed_t spacing = FixedMul(3*mobj->info->radius/2, mobj->target->scale); - mobj_t *cur = mobj; - mobj_t *targ = mobj->target; - - while (cur && !P_MobjWasRemoved(cur)) - { - angle_t ang; - fixed_t targx; - fixed_t targy; - fixed_t targz; - fixed_t speed; - fixed_t dist = spacing; - - if (cur != mobj) - { - targ = cur->hprev; - dist = spacing/2; - } - - if (!targ || P_MobjWasRemoved(targ)) - continue; - - ang = targ->angle; - targx = targ->x + P_ReturnThrustX(cur, ang + ANGLE_180, dist); - targy = targ->y + P_ReturnThrustY(cur, ang + ANGLE_180, dist); - targz = targ->z; - speed = FixedMul(R_PointToDist2(cur->x, cur->y, targx, targy), 3*FRACUNIT/4); - if (P_IsObjectOnGround(targ)) - targz = cur->floorz; - - cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy); - - if (speed > dist) - P_InstaThrust(cur, cur->angle, speed-dist); - - P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 3*FRACUNIT/4) - gravity, false); - - if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) - P_TeleportMove(cur, targx, targy, cur->z); - - cur = cur->hnext; - } - } - // Was this so hard? if ((mobj->type == MT_BANANA_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_BANANA) || (mobj->type == MT_SSMINE_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_MINE)