diff --git a/src/d_player.h b/src/d_player.h index 259a66f70..7d0f20058 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -270,6 +270,8 @@ typedef enum #define TRIPWIRETIME (15) +#define BALLHOGINCREMENT (7) + //} // for kickstartaccel @@ -486,9 +488,11 @@ typedef struct player_s UINT16 flamemeter; // Flame Shield dash meter left UINT8 flamelength; // Flame Shield dash meter, number of segments + UINT16 ballhogcharge; // Ballhog charge up -- the higher this value, the more projectiles + UINT16 hyudorotimer; // Duration of the Hyudoro offroad effect itself SINT8 stealingtimer; // if >0 you are stealing, if <0 you are being stolen from - mobj_t *hoverhyudoro; // First hyudoro hovering next to player + mobj_t *hoverhyudoro; // First hyudoro hovering next to player UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters) UINT8 numsneakers; // Number of stacked sneaker effects diff --git a/src/info.c b/src/info.c index 6774050b6..e80098499 100644 --- a/src/info.c +++ b/src/info.c @@ -23753,7 +23753,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_hogbom, // deathsound 80*FRACUNIT, // speed - 16*FRACUNIT, // radius + 26*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass diff --git a/src/k_hud.c b/src/k_hud.c index 9d9c4a418..96635584e 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1206,6 +1206,16 @@ static void K_drawKartItem(void) else localpatch = kp_nodraw; } + else if (stplyr->ballhogcharge > 0) + { + itembar = stplyr->ballhogcharge; + maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1); + + if (leveltime & 1) + localpatch = kp_ballhog[offset]; + else + localpatch = kp_nodraw; + } else if (stplyr->rocketsneakertimer > 1) { itembar = stplyr->rocketsneakertimer; diff --git a/src/k_kart.c b/src/k_kart.c index 11cafc46d..e14995d05 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -493,6 +493,10 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) player->itemtype = KITEM_JAWZ; player->itemamount = 2; break; + case KITEM_BALLHOG: // Ballhog x5 + player->itemtype = KITEM_BALLHOG; + player->itemamount = 5; + break; default: if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) { @@ -4227,7 +4231,6 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I if (source->player != NULL) { - if (source->player->itemscale == ITEMSCALE_SHRINK) { // Nerf the base item speed a bit. @@ -4340,6 +4343,11 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I S_StartSound(th, sfx_s3kbfl); S_StartSound(th, sfx_cdfm35); break; + case MT_BALLHOG: + // Contra spread shot scale up + th->destscale = th->destscale << 1; + th->scalespeed = abs(th->destscale - th->scale) / (2*TICRATE); + break; default: break; } @@ -5094,7 +5102,7 @@ static mobj_t *K_FindLastTrailMobj(player_t *player) return trail; } -mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow) +mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow, angle_t angleOffset) { mobj_t *mo; INT32 dir; @@ -5160,46 +5168,21 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (missile) // Shootables { - if (mapthing == MT_BALLHOG) // Messy + if (dir == -1 && mapthing != MT_SPB) { - mo = NULL; // can't return multiple projectiles - if (dir == -1) - { - // Shoot backward - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) - 0x06000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) - 0x03000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + 0x03000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + 0x06000000, 0, PROJSPEED/8); - } - else - { - // Shoot forward - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x06000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x03000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x03000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x06000000, 0, PROJSPEED); - } + // Shoot backward + mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED/8); } else { - if (dir == -1 && mapthing != MT_SPB) - { - // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/8); - } - else - { - // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); - } + // Shoot forward + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED); + } - if (mapthing == MT_DROPTARGET && mo) - { - mo->reactiontime = TICRATE/2; - P_SetMobjState(mo, mo->info->painstate); - } + if (mapthing == MT_DROPTARGET && mo) + { + mo->reactiontime = TICRATE/2; + P_SetMobjState(mo, mo->info->painstate); } } else @@ -6151,6 +6134,10 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 newType = KITEM_JAWZ; newAmount = 2; break; + case KITEM_BALLHOG: // Ballhog x5 + newType = KITEM_BALLHOG; + newAmount = 5; + break; default: newType = i; newAmount = 1; @@ -9011,7 +8998,7 @@ void K_StripItems(player_t *player) player->curshield = KSHIELD_NONE; player->bananadrag = 0; - + player->ballhogcharge = 0; player->sadtimer = 0; K_UpdateHnextList(player, true); @@ -9731,7 +9718,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (ATTACK_IS_DOWN) { - K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); + K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->pflags &= ~PF_EGGMANOUT; K_UpdateHnextList(player, true); @@ -9839,7 +9826,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Banana x3 thrown { - K_ThrowKartItem(player, false, MT_BANANA, -1, 0); + K_ThrowKartItem(player, false, MT_BANANA, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9902,7 +9889,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Orbinaut x3 thrown { - K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); + K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9944,9 +9931,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Jawz thrown { if (player->throwdir == 1 || player->throwdir == 0) - K_ThrowKartItem(player, true, MT_JAWZ, 1, 0); + K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); else if (player->throwdir == -1) // Throwing backward gives you a dud that doesn't home in - K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); + K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9972,7 +9959,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) { - K_ThrowKartItem(player, false, MT_SSMINE, 1, 1); + K_ThrowKartItem(player, false, MT_SSMINE, 1, 1, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; @@ -10007,7 +9994,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) { - K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0); + K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; @@ -10015,18 +10002,63 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } break; case KITEM_BALLHOG: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + if (!HOLDING_ITEM && NO_HYUDORO) { - player->itemamount--; - K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); - K_PlayAttackTaunt(player->mo); + INT32 ballhogmax = ((player->itemamount-1) * BALLHOGINCREMENT) + 1; + + if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) + && (player->ballhogcharge < ballhogmax)) + { + player->ballhogcharge++; + } + else + { + if (cmd->buttons & BT_ATTACK) + { + player->pflags &= ~PF_HOLDREADY; + } + else + { + player->pflags |= PF_HOLDREADY; + } + + if (player->ballhogcharge > 0) + { + INT32 numhogs = min((player->ballhogcharge / BALLHOGINCREMENT) + 1, player->itemamount); + + if (numhogs <= 1) + { + player->itemamount--; + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0, 0); + } + else + { + angle_t cone = 0x01800000 * (numhogs-1); + angle_t offsetAmt = (cone * 2) / (numhogs-1); + angle_t angleOffset = cone; + INT32 i; + + player->itemamount -= numhogs; + + for (i = 0; i < numhogs; i++) + { + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0, angleOffset); + angleOffset -= offsetAmt; + } + } + + player->ballhogcharge = 0; + K_PlayAttackTaunt(player->mo); + player->pflags &= ~PF_HOLDREADY; + } + } } break; case KITEM_SPB: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { player->itemamount--; - K_ThrowKartItem(player, true, MT_SPB, 1, 0); + K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0); K_PlayAttackTaunt(player->mo); } break; @@ -10128,7 +10160,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->bubbleblowup > bubbletime*2) { - K_ThrowKartItem(player, (player->throwdir > 0), MT_BUBBLESHIELDTRAP, -1, 0); + K_ThrowKartItem(player, (player->throwdir > 0), MT_BUBBLESHIELDTRAP, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->bubbleblowup = 0; player->bubblecool = 0; @@ -10278,7 +10310,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Sink thrown { - K_ThrowKartItem(player, false, MT_SINK, 1, 2); + K_ThrowKartItem(player, false, MT_SINK, 1, 2, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; diff --git a/src/k_kart.h b/src/k_kart.h index 4529b2611..7b1e0f6ae 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -90,7 +90,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo); void K_SpawnDraftDust(mobj_t *mo); void K_DriftDustHandling(mobj_t *spawner); void K_Squish(mobj_t *mo); -mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow); +mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow, angle_t angleOffset); void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_DoSneaker(player_t *player, INT32 type); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 7078b2258..cfab3696e 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -336,6 +336,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->flamemeter); else if (fastcmp(field,"flamelength")) lua_pushinteger(L, plr->flamelength); + else if (fastcmp(field,"ballhogcharge")) + lua_pushinteger(L, plr->ballhogcharge); else if (fastcmp(field,"hyudorotimer")) lua_pushinteger(L, plr->hyudorotimer); else if (fastcmp(field,"stealingtimer")) @@ -696,6 +698,8 @@ static int player_set(lua_State *L) plr->flamemeter = luaL_checkinteger(L, 3); else if (fastcmp(field,"flamelength")) plr->flamelength = luaL_checkinteger(L, 3); + else if (fastcmp(field,"ballhogcharge")) + plr->ballhogcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"hyudorotimer")) plr->hyudorotimer = luaL_checkinteger(L, 3); else if (fastcmp(field,"stealingtimer")) diff --git a/src/p_inter.c b/src/p_inter.c index 438909980..2c1810fb7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1416,7 +1416,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // special behavior for SPB capsules if (target->threshold == KITEM_SPB) { - K_ThrowKartItem(player, true, MT_SPB, 1, 0); + K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0); break; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 0505d6bda..8813a18b4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1563,7 +1563,10 @@ void P_XYMovement(mobj_t *mo) { mo->health--; if (mo->health == 0) + { + mo->scalespeed = mo->scale/12; mo->destscale = 0; + } } } //} diff --git a/src/p_saveg.c b/src/p_saveg.c index 5620178e1..da85dac77 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -320,6 +320,8 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].flamemeter); WRITEUINT8(save_p, players[i].flamelength); + WRITEUINT16(save_p, players[i].ballhogcharge); + WRITEUINT16(save_p, players[i].hyudorotimer); WRITESINT8(save_p, players[i].stealingtimer); @@ -609,6 +611,8 @@ static void P_NetUnArchivePlayers(void) players[i].flamemeter = READUINT16(save_p); players[i].flamelength = READUINT8(save_p); + players[i].ballhogcharge = READUINT16(save_p); + players[i].hyudorotimer = READUINT16(save_p); players[i].stealingtimer = READSINT8(save_p);