diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c9917a382..0dcc5f5b2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -349,6 +349,7 @@ consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR|CV_CHEAT, C consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_droptarget = CVAR_INIT ("droptarget", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 6612352ea..5dc3418b0 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -61,7 +61,7 @@ extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_res // SRB2kart items extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; -extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine, cv_landmine; +extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine, cv_landmine, cv_droptarget; extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield; extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink; diff --git a/src/d_player.h b/src/d_player.h index c67306431..55c2857d5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -151,7 +151,8 @@ Run this macro, then #undef FOREACH afterward FOREACH (HYUDORO, 17),\ FOREACH (POGOSPRING, 18),\ FOREACH (SUPERRING, 19),\ - FOREACH (KITCHENSINK, 20) + FOREACH (KITCHENSINK, 20),\ + FOREACH (DROPTARGET, 21) typedef enum { diff --git a/src/deh_tables.c b/src/deh_tables.c index cbc411ddd..109f44787 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3812,6 +3812,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_LANDMINE", "S_LANDMINE_EXPLODE", + // Drop Target + "S_DROPTARGET", + "S_DROPTARGET_SPIN", + // Ballhog "S_BALLHOG1", "S_BALLHOG2", @@ -5522,6 +5526,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_LANDMINE", // Land Mine + "MT_DROPTARGET", // Drop Target + "MT_DROPTARGET_SHIELD", + "MT_BALLHOG", // Ballhog "MT_BALLHOGBOOM", diff --git a/src/info.c b/src/info.c index bbe58d13f..ae59fadf7 100644 --- a/src/info.c +++ b/src/info.c @@ -557,6 +557,7 @@ char sprnames[NUMSPRITES + 1][5] = "SSMN", // SS Mine "KRBM", // SS Mine BOOM "LNDM", // Land Mine + "DTRG", // Drop Target "BHOG", // Ballhog "BHBM", // Ballhog BOOM "SPBM", // Self-Propelled Bomb @@ -4375,6 +4376,9 @@ state_t states[NUMSTATES] = {SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE {SPR_NULL, 0, 1, {A_LandMineExplode}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE + {SPR_DTRG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_DROPTARGET + {SPR_DTRG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DROPTARGET_SPIN + {SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1 {SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2 {SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3 @@ -24193,6 +24197,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DROPTARGET + -1, // doomednum + S_DROPTARGET, // spawnstate + 3, // spawnhealth + S_NULL, // seestate + sfx_tossed, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_DROPTARGET_SPIN, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_DROPTARGET_SPIN, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 128*FRACUNIT, // speed + 45*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_s3k96, // activesound + MF_SPECIAL|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + + { // MT_DROPTARGET_SHIELD + -1, // doomednum + S_DROPTARGET, // spawnstate + 3, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_DROPTARGET_SPIN, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_DROPTARGET_SPIN, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 45*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BALLHOG -1, // doomednum S_BALLHOG1, // spawnstate diff --git a/src/info.h b/src/info.h index dfb0d3c43..9178ed1dd 100644 --- a/src/info.h +++ b/src/info.h @@ -1101,6 +1101,7 @@ typedef enum sprite SPR_SSMN, // SS Mine SPR_KRBM, // SS Mine BOOM SPR_LNDM, // Land Mine + SPR_DTRG, // Drop Target SPR_BHOG, // Ballhog SPR_BHBM, // Ballhog BOOM SPR_SPBM, // Self-Propelled Bomb @@ -4789,6 +4790,10 @@ typedef enum state S_LANDMINE, S_LANDMINE_EXPLODE, + // Drop Target + S_DROPTARGET, + S_DROPTARGET_SPIN, + // Ballhog S_BALLHOG1, S_BALLHOG2, @@ -6536,6 +6541,9 @@ typedef enum mobj_type MT_LANDMINE, // Land Mine + MT_DROPTARGET, // Drop Target + MT_DROPTARGET_SHIELD, + MT_BALLHOG, // Ballhog MT_BALLHOGBOOM, diff --git a/src/k_botitem.c b/src/k_botitem.c index 90e3d8172..6f8e82034 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -882,6 +882,64 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) } } +/*-------------------------------------------------- + static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd) + + Item usage for Drop Target throwing. + + Input Arguments:- + player - Bot to do this for. + cmd - Bot's ticcmd to edit. + + Return:- + None +--------------------------------------------------*/ +static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd) +{ + const fixed_t topspeed = K_GetKartSpeed(player, false); + fixed_t radius = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); + SINT8 throwdir = -1; + boolean tryLookback = false; + UINT8 snipeMul = 2; + player_t *target = NULL; + + if (player->speed > topspeed) + { + radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! + } + + player->botvars.itemconfirm++; + + target = K_PlayerInCone(player, radius, 15, false); + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); + throwdir = 1; + } + else + { + target = K_PlayerInCone(player, radius, 15, true); + + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + throwdir = -1; + tryLookback = true; + } + } + + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 25*TICRATE) + { + K_BotGenericPressItem(player, cmd, throwdir); + } +} + /*-------------------------------------------------- static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) @@ -1287,6 +1345,16 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) case KITEM_LANDMINE: K_BotItemLandmine(player, cmd, turnamt); break; + case KITEM_DROPTARGET: + if (!(player->pflags & PF_ITEMOUT)) + { + K_BotItemGenericTrapShield(player, cmd, turnamt, false); + } + else + { + K_BotItemDropTarget(player, cmd); + } + break; case KITEM_THUNDERSHIELD: K_BotItemThunder(player, cmd); break; diff --git a/src/k_botsearch.c b/src/k_botsearch.c index a06eb55f1..6e256a9e5 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -418,6 +418,8 @@ static boolean K_FindObjectsForNudging(mobj_t *thing) case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_LANDMINE: + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: case MT_BALLHOG: case MT_SPB: case MT_BUBBLESHIELDTRAP: diff --git a/src/k_collide.c b/src/k_collide.c index c0f4a95e8..86e94c292 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -446,6 +446,180 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) return true; } +boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2) +{ + mobj_t *draggeddroptarget = (t1->type == MT_DROPTARGET_SHIELD) ? t1->target : NULL; + + if ((t1->threshold > 0 && (t2->hitlag > 0 || !draggeddroptarget)) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (t2->player && (t2->player->hyudorotimer || t2->player->justbumped)) + return true; + + // Intensify bumps if already spinning... + P_Thrust(t1, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y), + (t1->reactiontime && !draggeddroptarget) ? 35*FRACUNIT : 20*FRACUNIT); + + if (draggeddroptarget) + { + // "Pass through" the shock of the impact, part 1. + t1->momx = t1->target->momx; + t1->momy = t1->target->momy; + t1->momz = t1->target->momz; + } + + { + angle_t t2angle = R_PointToAngle2(t2->momx, t2->momy, 0, 0); + angle_t t2deflect; + fixed_t t1speed, t2speed; + K_KartBouncing(t1, t2); + t1speed = FixedHypot(t1->momx, t1->momy); + t2speed = FixedHypot(t2->momx, t2->momy); + + t2deflect = t2angle - R_PointToAngle2(0, 0, t2->momx, t2->momy); + if (t2deflect > ANGLE_180) + t2deflect = InvAngle(t2deflect); + if (t2deflect < ANG10) + P_InstaThrust(t2, t2angle, t2speed); + + P_InitAngle(t1, R_PointToAngle2(0, 0, t1->momx, t1->momy)); + + t1->reactiontime = 7*(t1speed+t2speed)/FRACUNIT; + if (t1->reactiontime < 10) + t1->reactiontime = 10; + t1->threshold = 10; + } + + t1->renderflags &= ~RF_FULLDARK; // brightest on the bump + + if (draggeddroptarget) + { + // "Pass through" the shock of the impact, part 2. + draggeddroptarget->momx = t1->momx; + draggeddroptarget->momy = t1->momy; + draggeddroptarget->momz = t1->momz; + + // Have the drop target travel between them. + t1->momx = (t1->momx + t2->momx)/2; + t1->momy = (t1->momy + t2->momy)/2; + t1->momz = (t1->momz + t2->momz)/2; + + K_AddHitLag(t1->target, 6, false); + } + + K_AddHitLag(t1, 6, true); + K_AddHitLag(t2, 6, false); + + { + mobj_t *ghost = P_SpawnGhostMobj(t1); + UINT8 i; + + P_SetScale(ghost, 3*ghost->destscale/2); + ghost->destscale = 15*ghost->destscale/2; + ghost->fuse = 10; + ghost->scalespeed = (ghost->destscale - ghost->scale)/ghost->fuse; + + for (i = 0; i < 2; i++) + { + mobj_t *blast = P_SpawnMobjFromMobj(t1, 0, 0, FixedDiv(t1->height, t1->scale), MT_BATTLEBUMPER_BLAST); + P_SetScale(blast, 5*blast->scale/2); + + blast->angle = R_PointToAngle2(0, 0, t1->momx, t1->momy) + ANGLE_45; + if (i & 1) + { + blast->angle += ANGLE_90; + } + P_InitAngle(blast, blast->angle); + + blast->destscale *= 10; + } + } + + t1->flags |= MF_SHOOTABLE; + // The following sets t1->target to t2, so draggeddroptarget keeps it persisting... + P_DamageMobj(t1, t2, (t2->target ? t2->target : t2), 1, DMG_NORMAL); + t1->color = (t1->health > 1) + ? SKINCOLOR_GOLD + : SKINCOLOR_CRIMSON; + t1->flags &= ~MF_SHOOTABLE; + + t1->spritexscale = 3*FRACUNIT; + t1->spriteyscale = 3*FRACUNIT/2; + + if (!t2->player) + { + t2->angle += ANGLE_180; + if (t2->type == MT_JAWZ) + P_SetTarget(&t2->tracer, t2->target); // Back to the source! + t2->threshold = 10; + } + + if (draggeddroptarget && draggeddroptarget->player) + { + // The following removes t1, be warned + // (its newly assigned properties are moved across) + K_DropHnextList(draggeddroptarget->player, true); + // Do NOT modify or reference t1 after this line + // I mean it! Do not even absentmindedly try it + } + + return true; +} + +boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) +{ + if (t2->type == MT_PLAYER) + { + // Counter desyncs + /*mobj_t *oldthing = thing; + mobj_t *oldtmthing = tmthing; + + P_Thrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), 4*thing->scale); + + thing = oldthing; + P_SetTarget(&tmthing, oldtmthing);*/ + + if (P_PlayerInPain(t2->player) + || t2->player->flashing || t2->player->hyudorotimer + || t2->player->justbumped || t2->scale > t1->scale + (mapobjectscale/8)) + return true; + + // Player Damage + P_DamageMobj(t2, ((t1->type == MT_BUBBLESHIELD) ? t1->target : t1), t1, 1, DMG_NORMAL|DMG_WOMBO); + S_StartSound(t1, sfx_s3k44); + } + else + { + if (!t2->threshold) + { + if (!t2->momx && !t2->momy) + { + t2->momz += (24*t2->scale) * P_MobjFlip(t2); + } + else + { + t2->momx = -4*t2->momx; + t2->momy = -4*t2->momy; + t2->momz = -4*t2->momz; + t2->angle += ANGLE_180; + } + if (t2->type == MT_JAWZ) + P_SetTarget(&t2->tracer, t2->target); // Back to the source! + t2->threshold = 10; + S_StartSound(t1, sfx_s3k44); + } + } + + // no interaction + return true; +} + boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) { if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) @@ -498,6 +672,7 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD || t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD || t2->type == MT_SSMINE || t2->type == MT_SSMINE_SHIELD + || t2->type == MT_DROPTARGET_SHIELD || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) return false; diff --git a/src/k_collide.h b/src/k_collide.h index 3be27c803..11af0502b 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -11,6 +11,8 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); boolean K_MineCollide(mobj_t *t1, mobj_t *t2); boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2); +boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2); +boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2); boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_hud.c b/src/k_hud.c index 0c607cc2e..2035a3a85 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -121,6 +121,7 @@ static patch_t *kp_orbinaut[5]; static patch_t *kp_jawz[2]; static patch_t *kp_mine[2]; static patch_t *kp_landmine[2]; +static patch_t *kp_droptarget[2]; static patch_t *kp_ballhog[2]; static patch_t *kp_selfpropelledbomb[2]; static patch_t *kp_grow[2]; @@ -410,6 +411,7 @@ void K_LoadKartHUDGraphics(void) kp_jawz[0] = W_CachePatchName("K_ITJAWZ", PU_HUDGFX); kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX); kp_landmine[0] = W_CachePatchName("K_ITLNDM", PU_HUDGFX); + kp_droptarget[0] = W_CachePatchName("K_ITDTRG", PU_HUDGFX); kp_ballhog[0] = W_CachePatchName("K_ITBHOG", PU_HUDGFX); kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX); kp_grow[0] = W_CachePatchName("K_ITGROW", PU_HUDGFX); @@ -460,6 +462,7 @@ void K_LoadKartHUDGraphics(void) kp_jawz[1] = W_CachePatchName("K_ISJAWZ", PU_HUDGFX); kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX); kp_landmine[1] = W_CachePatchName("K_ISLNDM", PU_HUDGFX); + kp_droptarget[1] = W_CachePatchName("K_ISDTRG", PU_HUDGFX); kp_ballhog[1] = W_CachePatchName("K_ISBHOG", PU_HUDGFX); kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX); kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX); @@ -1111,7 +1114,7 @@ static void K_drawKartItem(void) if (stplyr->skincolor) localcolor = stplyr->skincolor; - switch((stplyr->itemroulette % (15*3)) / 3) + switch((stplyr->itemroulette % (16*3)) / 3) { // Each case is handled in threes, to give three frames of in-game time to see the item on the roulette case 0: // Sneaker @@ -1178,6 +1181,10 @@ static void K_drawKartItem(void) localpatch = kp_landmine[offset]; //localcolor = SKINCOLOR_JET; break; + case 16: // Land Mine + localpatch = kp_droptarget[offset]; + //localcolor = SKINCOLOR_LIME; + break; /*case 15: // Pogo Spring localpatch = kp_pogospring[offset]; localcolor = SKINCOLOR_TANGERINE; @@ -1266,6 +1273,9 @@ static void K_drawKartItem(void) case KITEM_LANDMINE: localpatch = kp_landmine[offset]; break; + case KITEM_DROPTARGET: + localpatch = kp_droptarget[offset]; + break; case KITEM_BALLHOG: localpatch = kp_ballhog[offset]; break; @@ -4551,6 +4561,7 @@ static void K_drawDistributionDebugger(void) kp_jawz[1], kp_mine[1], kp_landmine[1], + kp_droptarget[1], kp_ballhog[1], kp_selfpropelledbomb[1], kp_grow[1], diff --git a/src/k_kart.c b/src/k_kart.c index 8e7eef45d..c93157b3b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -215,6 +215,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_jawz); CV_RegisterVar(&cv_mine); CV_RegisterVar(&cv_landmine); + CV_RegisterVar(&cv_droptarget); CV_RegisterVar(&cv_ballhog); CV_RegisterVar(&cv_selfpropelledbomb); CV_RegisterVar(&cv_grow); @@ -321,6 +322,7 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] = &cv_jawz, &cv_mine, &cv_landmine, + &cv_droptarget, &cv_ballhog, &cv_selfpropelledbomb, &cv_grow, @@ -350,12 +352,12 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility - /*Banana*/ { 5, 3, 1, 0, 0, 0, 0, 0 }, // Banana + /*Banana*/ { 4, 3, 1, 0, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 7, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut + /*Orbinaut*/ { 5, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine - /*Land Mine*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine + /*Land Mine*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow @@ -367,6 +369,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink + /*Drop Target*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target /*Sneaker x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2 /*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3 /*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 @@ -399,6 +402,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] = /*Pogo Spring*/ { 2, 0 }, // Pogo Spring /*Super Ring*/ { 0, 0 }, // Super Ring /*Kitchen Sink*/ { 0, 0 }, // Kitchen Sink + /*Drop Target*/ { 0, 0 }, // Drop Target /*Sneaker x2*/ { 0, 0 }, // Sneaker x2 /*Sneaker x3*/ { 1, 1 }, // Sneaker x3 /*Banana x3*/ { 1, 0 }, // Banana x3 @@ -674,6 +678,7 @@ INT32 K_KartGetItemOdds( case KITEM_ROCKETSNEAKER: case KITEM_JAWZ: case KITEM_LANDMINE: + case KITEM_DROPTARGET: case KITEM_BALLHOG: case KRITEM_TRIPLESNEAKER: case KRITEM_TRIPLEORBINAUT: @@ -1231,6 +1236,10 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) else weight += 3*FRACUNIT; break; + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + if (against->player) + weight = K_PlayerWeight(against, NULL); default: break; } @@ -1264,6 +1273,12 @@ static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2) { S_StartSound(mobj1, sfx_s3k44); } + else if (mobj1->type == MT_DROPTARGET || mobj1->type == MT_DROPTARGET_SHIELD) // no need to check the other way around + { + S_StartSound(mobj2, sfx_s258); + fx->colorized = true; + fx->color = mobj1->color; + } else { S_StartSound(mobj1, sfx_s3k49); @@ -1379,6 +1394,7 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) || (mobj2->player && mobj2->player->respawn.state != RESPAWNST_NONE)) return false; + if (mobj1->type != MT_DROPTARGET && mobj1->type != MT_DROPTARGET_SHIELD) { // Don't bump if you're flashing INT32 flash; @@ -4857,6 +4873,12 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, // Shoot forward mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); } + + if (mapthing == MT_DROPTARGET && mo) + { + mo->reactiontime = TICRATE/2; + P_SetMobjState(mo, mo->info->painstate); + } } } else @@ -4886,7 +4908,7 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (mo) { angle_t fa = player->mo->angle>>ANGLETOFINESHIFT; - fixed_t HEIGHT = ((20 + (dir*10)) * FRACUNIT) + (player->mo->momz*P_MobjFlip(player->mo)); // Also intentionally not player scale + fixed_t HEIGHT = ((20 + (dir*10)) * FRACUNIT) + (FixedDiv(player->mo->momz, mapobjectscale)*P_MobjFlip(player->mo)); // Also intentionally not player scale P_SetObjectMomZ(mo, HEIGHT, false); mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED*dir); @@ -5352,7 +5374,8 @@ static void K_DoShrink(player_t *user) if (mobj->type == MT_BANANA_SHIELD || mobj->type == MT_JAWZ_SHIELD || mobj->type == MT_SSMINE_SHIELD || mobj->type == MT_EGGMANITEM_SHIELD || - mobj->type == MT_SINK_SHIELD || mobj->type == MT_ORBINAUT_SHIELD) + mobj->type == MT_SINK_SHIELD || mobj->type == MT_ORBINAUT_SHIELD || + mobj->type == MT_DROPTARGET_SHIELD) { if (mobj->target && mobj->target->player) { @@ -5555,6 +5578,9 @@ void K_DropHnextList(player_t *player, boolean keepshields) { nextwork = work->hnext; + if (!work->health) + continue; // taking care of itself + switch (work->type) { // Kart orbit items @@ -5576,6 +5602,11 @@ void K_DropHnextList(player_t *player, boolean keepshields) dropall = false; type = MT_SSMINE; break; + case MT_DROPTARGET_SHIELD: + orbit = false; + dropall = false; + type = MT_DROPTARGET; + break; case MT_EGGMANITEM_SHIELD: orbit = false; type = MT_EGGMANITEM; @@ -5598,14 +5629,24 @@ void K_DropHnextList(player_t *player, boolean keepshields) P_SetScale(dropwork, work->scale); dropwork->destscale = K_ItemScaleForPlayer(player); //work->destscale; dropwork->scalespeed = work->scalespeed; + dropwork->spritexscale = work->spritexscale; + dropwork->spriteyscale = work->spriteyscale; dropwork->flags |= MF_NOCLIPTHING; dropwork->flags2 = work->flags2; dropwork->eflags = work->eflags; + dropwork->renderflags = work->renderflags; + dropwork->color = work->color; + dropwork->colorized = work->colorized; + dropwork->whiteshadow = work->whiteshadow; + dropwork->floorz = work->floorz; dropwork->ceilingz = work->ceilingz; + dropwork->health = work->health; // will never be set to 0 as long as above guard exists + dropwork->hitlag = work->hitlag; + // Copy interp data dropwork->old_angle = work->old_angle; dropwork->old_x = work->old_x; @@ -5673,14 +5714,22 @@ void K_DropHnextList(player_t *player, boolean keepshields) } else { - dropwork->color = work->color; dropwork->angle -= ANGLE_90; } } else // plop on the ground { - dropwork->flags &= ~MF_NOCLIPTHING; dropwork->threshold = 10; + dropwork->flags &= ~MF_NOCLIPTHING; + + if (type == MT_DROPTARGET && dropwork->hitlag) + { + dropwork->momx = work->momx; + dropwork->momy = work->momy; + dropwork->momz = work->momz; + dropwork->reactiontime = work->reactiontime; + P_SetMobjState(dropwork, mobjinfo[type].painstate); + } } P_RemoveMobj(work); @@ -6192,10 +6241,12 @@ static void K_MoveHeldObjects(player_t *player) break; case MT_BANANA_SHIELD: // Kart trailing items case MT_SSMINE_SHIELD: + case MT_DROPTARGET_SHIELD: case MT_EGGMANITEM_SHIELD: case MT_SINK_SHIELD: { mobj_t *cur = player->mo->hnext; + mobj_t *curnext; mobj_t *targ = player->mo; if (P_IsObjectOnGround(player->mo) && player->speed > 0) @@ -6208,11 +6259,17 @@ static void K_MoveHeldObjects(player_t *player) fixed_t targx, targy, targz; fixed_t speed, dist; + curnext = cur->hnext; + if (cur->type == MT_EGGMANITEM_SHIELD) { // Decided that this should use their "canon" color. cur->color = SKINCOLOR_BLACK; } + else if (cur->type == MT_DROPTARGET_SHIELD) + { + cur->renderflags = (cur->renderflags|RF_FULLBRIGHT) ^ RF_FULLDARK; // the difference between semi and fullbright + } cur->flags &= ~MF_NOCLIPTHING; @@ -6221,7 +6278,7 @@ static void K_MoveHeldObjects(player_t *player) if (!cur->health) { - cur = cur->hnext; + cur = curnext; continue; } @@ -6239,7 +6296,10 @@ static void K_MoveHeldObjects(player_t *player) dist = cur->extravalue1/2; if (!targ || P_MobjWasRemoved(targ)) + { + cur = curnext; continue; + } // Shrink your items if the player shrunk too. P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), finalscale))); @@ -6270,7 +6330,14 @@ static void K_MoveHeldObjects(player_t *player) P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false); if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) + { P_MoveOrigin(cur, targx, targy, cur->z); + if (P_MobjWasRemoved(cur)) + { + cur = curnext; + continue; + } + } if (P_IsObjectOnGround(cur)) { @@ -6278,7 +6345,7 @@ static void K_MoveHeldObjects(player_t *player) cur->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false); } - cur = cur->hnext; + cur = curnext; } } break; @@ -9250,6 +9317,33 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_PlayAttackTaunt(player->mo); } break; + case KITEM_DROPTARGET: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + K_SetItemOut(player); + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_DROPTARGET_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + mo->cusval = player->itemscale; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) + { + K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0); + K_PlayAttackTaunt(player->mo); + player->itemamount--; + player->pflags &= ~PF_ITEMOUT; + K_UpdateHnextList(player, true); + } + break; case KITEM_BALLHOG: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { diff --git a/src/p_inter.c b/src/p_inter.c index 07ad582ac..ec49a19e9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -942,6 +942,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget && !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD || target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD + || target->type == MT_DROPTARGET || target->type == MT_DROPTARGET_SHIELD || target->type == MT_EGGMANITEM || target->type == MT_EGGMANITEM_SHIELD || target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000 @@ -981,6 +982,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { if ((target->type == MT_BANANA_SHIELD && target->target->player->itemtype == KITEM_BANANA) // trail items || (target->type == MT_SSMINE_SHIELD && target->target->player->itemtype == KITEM_MINE) + || (target->type == MT_DROPTARGET_SHIELD && target->target->player->itemtype == KITEM_DROPTARGET) || (target->type == MT_SINK_SHIELD && target->target->player->itemtype == KITEM_KITCHENSINK)) { if (target->movedir != 0 && target->movedir < (UINT16)target->target->player->itemamount) @@ -1496,6 +1498,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } break; + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + target->fuse = 1; + break; + default: break; } @@ -1834,6 +1841,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { laglength = 2; } + else if (target->type == MT_DROPTARGET || target->type == MT_DROPTARGET_SHIELD) + { + laglength = 0; // handled elsewhere + } // Everything above here can't be forced. if (!metalrecording) @@ -1906,7 +1917,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Check if the player is allowed to be damaged! // If not, then spawn the instashield effect instead. - if (!force) + if (!force && !(inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1 == 1)) { if (gametyperules & GTR_BUMPERS) { diff --git a/src/p_map.c b/src/p_map.c index 8b07a4e32..ee0cc4e1e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -768,50 +768,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (tmthing->type == MT_PLAYER) - { - // Counter desyncs - /*mobj_t *oldthing = thing; - mobj_t *oldtmthing = tmthing; - - P_Thrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), 4*thing->scale); - - thing = oldthing; - P_SetTarget(&tmthing, oldtmthing);*/ - - if (P_PlayerInPain(tmthing->player) - || tmthing->player->flashing || tmthing->player->hyudorotimer - || tmthing->player->justbumped || tmthing->scale > thing->scale + (mapobjectscale/8)) - return true; - - // Player Damage - P_DamageMobj(tmthing, ((thing->type == MT_BUBBLESHIELD) ? thing->target : thing), thing, 1, DMG_NORMAL|DMG_WOMBO); - S_StartSound(thing, sfx_s3k44); - } - else - { - if (!tmthing->threshold) - { - if (!tmthing->momx && !tmthing->momy) - { - tmthing->momz += (24*tmthing->scale) * P_MobjFlip(tmthing); - } - else - { - tmthing->momx = -tmthing->momx; - tmthing->momy = -tmthing->momy; - tmthing->momz = -tmthing->momz; - tmthing->angle += ANGLE_180; - } - if (tmthing->type == MT_JAWZ) - P_SetTarget(&tmthing->tracer, tmthing->target); // Back to the source! - tmthing->threshold = 10; - S_StartSound(thing, sfx_s3k44); - } - } - - // no interaction - return true; + return K_BubbleShieldCollide(thing, tmthing); } else if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->bubbleblowup) || (tmthing->player && tmthing->player->bubbleblowup)) @@ -826,56 +783,48 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->type == MT_PLAYER) - { - // Counter desyncs - /*mobj_t *oldthing = thing; - mobj_t *oldtmthing = tmthing; - - P_Thrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y), 4*tmthing->scale); - - thing = oldthing; - P_SetTarget(&tmthing, oldtmthing);*/ - - if (P_PlayerInPain(thing->player) - || thing->player->flashing || thing->player->hyudorotimer - || thing->player->justbumped || thing->scale > tmthing->scale + (mapobjectscale/8)) - return true; - - // Player Damage - P_DamageMobj(thing, ((tmthing->type == MT_BUBBLESHIELD) ? tmthing->target : tmthing), tmthing, 1, DMG_NORMAL); - S_StartSound(tmthing, sfx_s3k44); - } - else - { - if (!thing->threshold) - { - if (!thing->momx && !thing->momy) - { - thing->momz += (24*thing->scale) * P_MobjFlip(thing); - } - else - { - thing->momx = -thing->momx; - thing->momy = -thing->momy; - thing->momz = -thing->momz; - thing->angle += ANGLE_180; - } - if (thing->type == MT_JAWZ) - P_SetTarget(&thing->tracer, thing->target); // Back to the source! - thing->threshold = 10; - S_StartSound(tmthing, sfx_s3k44); - } - } - - // no interaction - return true; + return K_BubbleShieldCollide(tmthing, thing); } // double make sure bubbles won't collide with anything else if (thing->type == MT_BUBBLESHIELD || tmthing->type == MT_BUBBLESHIELD) return true; + // Droptarget reflect + if ((thing->type == MT_DROPTARGET || thing->type == MT_DROPTARGET_SHIELD) + && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD + || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG + || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK + || (tmthing->type == MT_PLAYER))) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + return K_DropTargetCollide(thing, tmthing); + } + else if ((tmthing->type == MT_DROPTARGET || tmthing->type == MT_DROPTARGET_SHIELD) + && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG + || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK + || (thing->type == MT_PLAYER))) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + return K_DropTargetCollide(tmthing, thing); + } + + // double make sure drop targets won't collide with anything else + if (thing->type == MT_DROPTARGET || tmthing->type == MT_DROPTARGET + || thing->type == MT_DROPTARGET_SHIELD || tmthing->type == MT_DROPTARGET_SHIELD) + return true; + if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 48fb94b92..22bce66c3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1179,6 +1179,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_EGGMANITEM: case MT_SSMINE: case MT_LANDMINE: + case MT_DROPTARGET: case MT_SINK: case MT_EMERALD: if (mo->extravalue2 > 0) @@ -2045,7 +2046,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) && (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6 - || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7)) + || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7 + || GETSECSPECIAL(mo->subsector->sector->special, 1) == 8)) return true; return false; @@ -2143,6 +2145,7 @@ boolean P_ZMovement(mobj_t *mo) case MT_BALLHOG: case MT_SSMINE: case MT_LANDMINE: + case MT_DROPTARGET: case MT_BUBBLESHIELDTRAP: // Remove stuff from death pits. if (P_CheckDeathPitCollide(mo)) @@ -4866,6 +4869,7 @@ boolean P_IsKartItem(INT32 type) { if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD || type == MT_BANANA || type == MT_BANANA_SHIELD || + type == MT_DROPTARGET || type == MT_DROPTARGET_SHIELD || type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD || type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || type == MT_SSMINE || type == MT_SSMINE_SHIELD || @@ -4903,12 +4907,14 @@ static void P_RemoveKartItem(mobj_t *thing) { mobj_t *mo; for (mo = kitemcap; mo; mo = mo->itnext) - if (mo->itnext == thing) - { - P_SetTarget(&mo->itnext, thing->itnext); - P_SetTarget(&thing->itnext, NULL); - return; - } + { + if (mo->itnext != thing) + continue; + + P_SetTarget(&mo->itnext, thing->itnext); + P_SetTarget(&thing->itnext, NULL); + return; + } } // Doesn't actually do anything since items have their own thinkers, @@ -5640,14 +5646,15 @@ static void P_MobjSceneryThink(mobj_t *mobj) { mobj_t *blast = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BATTLEBUMPER_BLAST); - P_InitAngle(blast, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45); - blast->destscale *= 4; - + blast->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45; if (i & 1) { blast->angle += ANGLE_90; S_StartSound(blast, sfx_cdfm64); } + P_InitAngle(blast, blast->angle); + + blast->destscale *= 4; } for (i = 0; i < 10; i++) @@ -6164,6 +6171,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) case MT_BANANA: case MT_EGGMANITEM: case MT_LANDMINE: + //case MT_DROPTARGET: case MT_SPB: if (P_IsObjectOnGround(mobj)) { @@ -6843,6 +6851,45 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->health = 1; } + if (mobj->threshold > 0) + mobj->threshold--; + break; + case MT_DROPTARGET: + if (mobj->reactiontime > 0) + { + // Slippery tipping mode. + INT32 slippytip = 1 + (mobj->reactiontime/2); + if (slippytip > 64) + slippytip = 64; + else if (slippytip < 8) + slippytip = 8; + if (!(mobj->health & 1) == !(mobj->flags2 & MF2_AMBUSH)) + { + slippytip = -slippytip; + } + mobj->angle += slippytip*ANG2; + + mobj->friction = ((2*ORIG_FRICTION)+FRACUNIT)/3; // too low still? + + /*if (mobj->momx || mobj->momy || mobj->momz) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! + }*/ + + if (!--mobj->reactiontime) + { + P_SetMobjState(mobj, mobj->info->spawnstate); + } + } + else + { + // Time to stop, ramp up the friction... + mobj->friction = ORIG_FRICTION/4; // too high still? + } + + mobj->renderflags = (mobj->renderflags|RF_FULLBRIGHT) ^ RF_FULLDARK; // the difference between semi and fullbright + if (mobj->threshold > 0) mobj->threshold--; break; @@ -9050,6 +9097,13 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->hitlag > 0) { mobj->hitlag--; + + if (mobj->type == MT_DROPTARGET && mobj->reactiontime > 0 && mobj->hitlag == 2) + { + mobj->spritexscale = FRACUNIT; + mobj->spriteyscale = 5*FRACUNIT; + } + return; } @@ -9234,7 +9288,8 @@ void P_MobjThinker(mobj_t *mobj) || mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_FALLINGROCK || mobj->type == MT_ORBINAUT - || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD) { + || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD + || (mobj->type == MT_DROPTARGET && mobj->reactiontime)) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly if (P_MobjWasRemoved(mobj)) // anything that calls checkposition can be lethal return; @@ -9547,6 +9602,11 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) thing->shadowscale = 3*FRACUNIT/2; thing->whiteshadow = false; break; + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + thing->shadowscale = 5*FRACUNIT/4; + thing->whiteshadow = true; + break; case MT_THUNDERSHIELD: case MT_BUBBLESHIELD: case MT_BUBBLESHIELDTRAP: @@ -10082,6 +10142,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } } break; + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + mobj->color = SKINCOLOR_LIME; + mobj->colorized = true; + mobj->renderflags |= RF_FULLBRIGHT; + break; case MT_SMK_MOLE: mobj->reactiontime = P_RandomRange(0, 3*mobj->info->reactiontime/2); // Random delay on start of level break;