diff --git a/src/info.c b/src/info.c index f57295fb6..834dcf0a1 100644 --- a/src/info.c +++ b/src/info.c @@ -14525,8 +14525,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 12*FRACUNIT, // radius - 20*FRACUNIT, // height + 10*FRACUNIT, // radius + 21*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage diff --git a/src/k_kart.c b/src/k_kart.c index 28f58d897..c6065cf62 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2008,32 +2008,16 @@ void K_DriftDustHandling(mobj_t *spawner) } } -static mobj_t *K_FindLastTrailMobj(player_t *player) +static mobj_t *K_FindLastTrailMobj(player_t *player) // YUCK, i hate this! { - thinker_t *th; - mobj_t *mo; - mobj_t *trail = NULL; + mobj_t *trail = player->mo->hnext; - if (!player) + if (!player || !trail) return NULL; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + while (trail->hnext && !P_MobjWasRemoved(trail->hnext)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - - if (mo->type != MT_BANANA_SHIELD - && mo->type != MT_FAKESHIELD - && mo->type != MT_SSMINE_SHIELD) - continue; - - if (!mo->target || !mo->target->player || mo->target->player != player) - continue; - - if (trail == NULL || (mo->lastlook > trail->lastlook)) - trail = mo; + trail = trail->hnext; } return trail; @@ -2381,6 +2365,27 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed) S_StartSound(mo, sfx_kc2f); } +void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) +{ + if (banana->hnext) + K_KillBananaChain(banana->hnext, inflictor, source); + + if (banana->health) + { + if (banana->eflags & MFE_VERTICALFLIP) + banana->z -= banana->height; + else + banana->z += banana->height; + + S_StartSound(banana, banana->info->deathsound); + P_KillMobj(banana, inflictor, source); + + P_SetObjectMomZ(banana, 8*FRACUNIT, false); + if (inflictor) + P_InstaThrust(banana, R_PointToAngle2(inflictor->x, inflictor->y, banana->x, banana->y)+ANGLE_90, 16*FRACUNIT); + } +} + /** \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 @@ -3030,48 +3035,38 @@ void K_MoveKartPlayer(player_t *player, boolean onground) angle_t newangle; fixed_t newx; fixed_t newy; - mobj_t *master; + INT32 moloop; + mobj_t *mo; + mobj_t *prev = NULL; - player->kartstuff[k_itemheld] = 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); - master = P_SpawnMobj(newx, newy, player->mo->z, MT_BANANA_SHIELD); - master->threshold = 10; - master->movecount = player->kartstuff[k_itemamount]-1; - master->lastlook = 1; - - if (master) + if (player->kartstuff[k_itemamount] > 1) { - P_SetTarget(&master->target, player->mo); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemheld] = 2; + } + else + player->kartstuff[k_itemheld] = 1; + player->pflags |= PF_ATTACKDOWN; - if (master->movecount > 0) // Banana x3/x10 held + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + newangle = player->mo->angle; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); + mo = P_SpawnMobj(newx, newy, player->mo->z, MT_BANANA_SHIELD); + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + if (moloop > 0) { - INT32 moloop; - K_PlayTauntSound(player->mo); - player->kartstuff[k_itemheld] = 2; - - for (moloop = 0; moloop < master->movecount; moloop++) - { - if (moloop >= 10) // maxed out mobjtable - break; - - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, mobjinfo[MT_BANANA_SHIELD].radius); - master->mobjtable[moloop] = P_SpawnMobj(newx, newy, player->mo->z, MT_BANANA_SHIELD); - - if (master->mobjtable[moloop]) - { - master->mobjtable[moloop]->threshold = 10; - master->mobjtable[moloop]->lastlook = moloop+2; - P_SetTarget(&master->mobjtable[moloop]->target, player->mo); - P_SetTarget(&master->mobjtable[moloop]->tracer, master); - master->mobjtable[moloop]->angle = newangle; - } - } + P_SetTarget(&mo->hprev, prev); + if (prev != NULL) + P_SetTarget(&prev->hnext, mo); } + else + P_SetTarget(&player->mo->hnext, mo); + prev = mo; } } else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_itemheld] == 1) @@ -3111,6 +3106,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) mo->scale = FRACUNIT/2; mo->threshold = 10; P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); } } break; @@ -3269,7 +3265,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) mo = P_SpawnMobj(newx, newy, player->mo->z, MT_SSMINE_SHIELD); mo->threshold = 10; if (mo) + { P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } } else if (!(cmd->buttons & BT_ATTACK) && HOLDING_ITEM) { diff --git a/src/k_kart.h b/src/k_kart.h index be455b0f7..32dbbbd61 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -34,6 +34,7 @@ void K_SpawnSparkleTrail(mobj_t *mo); 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); 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 30f1feb25..930feb55b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2132,6 +2132,22 @@ static int lib_kDoPogoSpring(lua_State *L) return 0; } +static int lib_kKillBananaChain(lua_State *L) +{ + mobj_t *banana = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!banana) + return LUA_ErrInvalid(L, "mobj_t"); + if (!inflictor) + return LUA_ErrInvalid(L, "mobj_t"); + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_KillBananaChain(banana, inflictor, source); + return 0; +} + static int lib_kMomentumToFacing(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2359,6 +2375,7 @@ static luaL_Reg lib[] = { {"K_DriftDustHandling",lib_kDriftDustHandling}, {"K_DoSneaker",lib_kDoSneaker}, {"K_DoPogoSpring",lib_kDoPogoSpring}, + {"K_KillBananaChain",lib_kKillBananaChain}, {"K_MomentumToFacing",lib_kMomentumToFacing}, {"K_GetKartSpeed",lib_kGetKartSpeed}, {"K_GetKartAccel",lib_kGetKartAccel}, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 16aa63c11..814bb3259 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -81,8 +81,7 @@ enum mobj_e { mobj_extravalue2, mobj_cusval, mobj_cvmem, - mobj_colorized, - mobj_mobjtable + mobj_colorized }; static const char *const mobj_opt[] = { @@ -143,7 +142,6 @@ static const char *const mobj_opt[] = { "cusval", "cvmem", "colorized", - "mobjtable", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -350,9 +348,6 @@ static int mobj_get(lua_State *L) case mobj_colorized: lua_pushboolean(L, mo->colorized); break; - case mobj_mobjtable: - // No idea how to do a table like this :V - return UNIMPLEMENTED; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -535,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. { @@ -651,8 +658,6 @@ static int mobj_set(lua_State *L) case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; - case mobj_mobjtable: - return UNIMPLEMENTED; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_inter.c b/src/p_inter.c index 202dcdddd..fd6264c32 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2109,27 +2109,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if ((target->type == MT_BANANA_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_BANANA) || (target->type == MT_SSMINE_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_MINE)) { - if (target->lastlook == 1) + if (target->lastlook != 0 && target->lastlook < target->target->player->kartstuff[k_itemamount]) { - INT32 i; - for (i = 0; i < 10; i++) - { - if (target->mobjtable[i] && target->mobjtable[i]->health) - P_KillMobj(target->mobjtable[i], inflictor, source); - } + if (target->target->hnext) + K_KillBananaChain(target->target->hnext, inflictor, source); target->target->player->kartstuff[k_itemamount] = 0; } - else if (target->lastlook > 1) - { - if (target->lastlook < target->target->player->kartstuff[k_itemamount]) - { - if (target->tracer && target->tracer->health) - P_KillMobj(target->tracer, inflictor, source); - target->target->player->kartstuff[k_itemamount] = 0; - } - else - target->target->player->kartstuff[k_itemamount]--; - } else target->target->player->kartstuff[k_itemamount]--; } diff --git a/src/p_mobj.c b/src/p_mobj.c index f7418f2ca..2880bd1c7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6431,6 +6431,11 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->target, NULL); if (mobj->tracer && P_MobjWasRemoved(mobj->tracer)) P_SetTarget(&mobj->tracer, NULL); + // hnext/hprev changes suggested by toaster + if (mobj->hnext && P_MobjWasRemoved(mobj->hnext)) + P_SetTarget(&mobj->hnext, NULL); + if (mobj->hprev && P_MobjWasRemoved(mobj->hprev)) + P_SetTarget(&mobj->hprev, NULL); mobj->flags2 &= ~MF2_PUSHED; mobj->eflags &= ~(MFE_SPRUNG|MFE_JUSTBOUNCEDWALL); @@ -6774,55 +6779,42 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->lastlook == 1) { const fixed_t spacing = FixedMul(mobj->info->radius, mobj->target->scale); - angle_t ang = mobj->target->angle; - fixed_t targx = mobj->target->x + P_ReturnThrustX(mobj, ang + ANGLE_180, spacing); - fixed_t targy = mobj->target->y + P_ReturnThrustY(mobj, ang + ANGLE_180, spacing); - fixed_t targz = mobj->target->z; - fixed_t speed = FixedMul(R_PointToDist2(mobj->x, mobj->y, targx, targy), FRACUNIT/2); - INT32 i; - INT32 previ = -1; + mobj_t *cur = mobj; + mobj_t *targ = mobj->target; - if (P_IsObjectOnGround(mobj->target)) - targz = mobj->floorz; - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, targx, targy); - - if (speed > spacing/2) - P_InstaThrust(mobj, mobj->angle, speed-spacing/2); - P_SetObjectMomZ(mobj, FixedMul(targz - mobj->z, FRACUNIT/2), false); - if (R_PointToDist2(mobj->x, mobj->y, targx, targy) > 768*FRACUNIT) - P_TeleportMove(mobj, targx, targy, mobj->z); - - if (mobj->movecount > 0) // Now, for chaser bananas. + while (cur && !P_MobjWasRemoved(cur)) { - for (i = 0; i < mobj->movecount; i++) - { - mobj_t *targ; + angle_t ang; + fixed_t targx; + fixed_t targy; + fixed_t targz; + fixed_t speed; - if (!mobj->mobjtable[i]) - continue; + if (cur != mobj) + targ = cur->hprev; - targ = mobj; - if (previ >= 0 && mobj->mobjtable[previ]) - targ = mobj->mobjtable[previ]; + if (!targ || P_MobjWasRemoved(targ)) + continue; - ang = targ->angle; - targx = targ->x + P_ReturnThrustX(mobj->mobjtable[i], ang + ANGLE_180, spacing); - targy = targ->y + P_ReturnThrustY(mobj->mobjtable[i], ang + ANGLE_180, spacing); - targz = targ->z; - speed = FixedMul(R_PointToDist2(mobj->mobjtable[i]->x, mobj->mobjtable[i]->y, targx, targy), FRACUNIT/2); - if (P_IsObjectOnGround(targ)) - targz = mobj->mobjtable[i]->floorz; + ang = targ->angle; + targx = targ->x + P_ReturnThrustX(cur, ang + ANGLE_180, spacing); + targy = targ->y + P_ReturnThrustY(cur, ang + ANGLE_180, spacing); + targz = targ->z; + speed = FixedMul(R_PointToDist2(cur->x, cur->y, targx, targy), FRACUNIT/2); + if (P_IsObjectOnGround(targ)) + targz = cur->floorz; - mobj->mobjtable[i]->angle = R_PointToAngle2(mobj->mobjtable[i]->x, mobj->mobjtable[i]->y, targx, targy); + cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy); - if (speed > spacing/2) - P_InstaThrust(mobj->mobjtable[i], mobj->mobjtable[i]->angle, speed-(spacing/2)); - P_SetObjectMomZ(mobj->mobjtable[i], FixedMul(targz - mobj->mobjtable[i]->z, FRACUNIT/2), false); - if (R_PointToDist2(mobj->mobjtable[i]->x, mobj->mobjtable[i]->y, targx, targy) > 768*FRACUNIT) - P_TeleportMove(mobj->mobjtable[i], targx, targy, mobj->mobjtable[i]->z); + if (speed > spacing/2) + P_InstaThrust(cur, cur->angle, speed-(spacing/2)); - previ = i; - } + P_SetObjectMomZ(cur, FixedMul(targz - cur->z, FRACUNIT/2), false); + + if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) + P_TeleportMove(cur, targx, targy, cur->z); + + cur = cur->hnext; } } @@ -9308,6 +9300,7 @@ void P_RemoveMobj(mobj_t *mobj) // // Remove any references to other mobjs. P_SetTarget(&mobj->target, P_SetTarget(&mobj->tracer, NULL)); + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. diff --git a/src/p_mobj.h b/src/p_mobj.h index 93cdbf0c2..096c7762b 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -367,7 +367,6 @@ typedef struct mobj_s #endif boolean colorized; // Whether the mobj uses the rainbow colormap - struct mobj_s *mobjtable[10]; // Table of 10 mobj pointers // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 9ce7708b9..cfbeccc97 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -947,11 +947,9 @@ typedef enum MD2_HPREV = 1<<8, #ifdef ESLOPE MD2_SLOPE = 1<<9, - MD2_COLORIZED = 1<<10, - MD2_MOBJTABLE = 1<<11 + MD2_COLORIZED = 1<<10 #else - MD2_COLORIZED = 1<<9, - MD2_MOBJTABLE = 1<<10 + MD2_COLORIZED = 1<<9 #endif } mobj_diff2_t; @@ -1031,7 +1029,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; UINT16 diff2; - UINT16 difft; UINT8 i; // Ignore stationary hoops - these will be respawned from mapthings. @@ -1062,7 +1059,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) else diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch - diff2 = difft = 0; + diff2 = 0; // not the default but the most probable if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0) @@ -1150,14 +1147,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (mobj->colorized) diff2 |= MD2_COLORIZED; - for (i = 0; i < 10; i++) - { - if (mobj->mobjtable[i]) - { - diff2 |= MD2_MOBJTABLE; - difft |= ((i > 0) ? (1<colorized); - if (diff2 & MD2_MOBJTABLE) - { - for (i = 0; i < 10; i++) - { - if (difft & ((i > 0) ? (1<mobjtable[i]->mobjnum); - } - } WRITEUINT32(save_p, mobj->mobjnum); } @@ -1959,7 +1938,6 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj_t *mobj; UINT32 diff; UINT16 diff2; - UINT16 difft; INT32 i; fixed_t z, floorz, ceilingz; @@ -1968,10 +1946,6 @@ static void LoadMobjThinker(actionf_p1 thinker) diff2 = READUINT16(save_p); else diff2 = 0; - if (diff2 & MD2_MOBJTABLE) - difft = READUINT16(save_p); - else - difft = 0; next = (void *)(size_t)READUINT32(save_p); @@ -2165,14 +2139,6 @@ static void LoadMobjThinker(actionf_p1 thinker) #endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); - if (diff2 & MD2_MOBJTABLE) - { - for (i = 0; i < 10; i++) - { - if (difft & ((i > 0) ? (1<mobjtable[i] = (mobj_t *)(size_t)READUINT32(save_p); - } - } if (diff & MD_REDFLAG) {