Merge branch 'droptarget' into 'master'

"Drop Target" item

See merge request KartKrew/Kart!562
This commit is contained in:
SteelT 2022-03-22 03:33:54 +00:00
commit dbdaebbb04
15 changed files with 565 additions and 112 deletions

View file

@ -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_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_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_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_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_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); consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);

View file

@ -61,7 +61,7 @@ extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_res
// SRB2kart items // SRB2kart items
extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; 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_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield; extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield;
extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink; extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink;

View file

@ -151,7 +151,8 @@ Run this macro, then #undef FOREACH afterward
FOREACH (HYUDORO, 17),\ FOREACH (HYUDORO, 17),\
FOREACH (POGOSPRING, 18),\ FOREACH (POGOSPRING, 18),\
FOREACH (SUPERRING, 19),\ FOREACH (SUPERRING, 19),\
FOREACH (KITCHENSINK, 20) FOREACH (KITCHENSINK, 20),\
FOREACH (DROPTARGET, 21)
typedef enum typedef enum
{ {

View file

@ -3812,6 +3812,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_LANDMINE", "S_LANDMINE",
"S_LANDMINE_EXPLODE", "S_LANDMINE_EXPLODE",
// Drop Target
"S_DROPTARGET",
"S_DROPTARGET_SPIN",
// Ballhog // Ballhog
"S_BALLHOG1", "S_BALLHOG1",
"S_BALLHOG2", "S_BALLHOG2",
@ -5522,6 +5526,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_LANDMINE", // Land Mine "MT_LANDMINE", // Land Mine
"MT_DROPTARGET", // Drop Target
"MT_DROPTARGET_SHIELD",
"MT_BALLHOG", // Ballhog "MT_BALLHOG", // Ballhog
"MT_BALLHOGBOOM", "MT_BALLHOGBOOM",

View file

@ -557,6 +557,7 @@ char sprnames[NUMSPRITES + 1][5] =
"SSMN", // SS Mine "SSMN", // SS Mine
"KRBM", // SS Mine BOOM "KRBM", // SS Mine BOOM
"LNDM", // Land Mine "LNDM", // Land Mine
"DTRG", // Drop Target
"BHOG", // Ballhog "BHOG", // Ballhog
"BHBM", // Ballhog BOOM "BHBM", // Ballhog BOOM
"SPBM", // Self-Propelled Bomb "SPBM", // Self-Propelled Bomb
@ -4375,6 +4376,9 @@ state_t states[NUMSTATES] =
{SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE {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_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, 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|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2
{SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3 {SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3
@ -24193,6 +24197,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 { // MT_BALLHOG
-1, // doomednum -1, // doomednum
S_BALLHOG1, // spawnstate S_BALLHOG1, // spawnstate

View file

@ -1101,6 +1101,7 @@ typedef enum sprite
SPR_SSMN, // SS Mine SPR_SSMN, // SS Mine
SPR_KRBM, // SS Mine BOOM SPR_KRBM, // SS Mine BOOM
SPR_LNDM, // Land Mine SPR_LNDM, // Land Mine
SPR_DTRG, // Drop Target
SPR_BHOG, // Ballhog SPR_BHOG, // Ballhog
SPR_BHBM, // Ballhog BOOM SPR_BHBM, // Ballhog BOOM
SPR_SPBM, // Self-Propelled Bomb SPR_SPBM, // Self-Propelled Bomb
@ -4789,6 +4790,10 @@ typedef enum state
S_LANDMINE, S_LANDMINE,
S_LANDMINE_EXPLODE, S_LANDMINE_EXPLODE,
// Drop Target
S_DROPTARGET,
S_DROPTARGET_SPIN,
// Ballhog // Ballhog
S_BALLHOG1, S_BALLHOG1,
S_BALLHOG2, S_BALLHOG2,
@ -6536,6 +6541,9 @@ typedef enum mobj_type
MT_LANDMINE, // Land Mine MT_LANDMINE, // Land Mine
MT_DROPTARGET, // Drop Target
MT_DROPTARGET_SHIELD,
MT_BALLHOG, // Ballhog MT_BALLHOG, // Ballhog
MT_BALLHOGBOOM, MT_BALLHOGBOOM,

View file

@ -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) 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: case KITEM_LANDMINE:
K_BotItemLandmine(player, cmd, turnamt); K_BotItemLandmine(player, cmd, turnamt);
break; break;
case KITEM_DROPTARGET:
if (!(player->pflags & PF_ITEMOUT))
{
K_BotItemGenericTrapShield(player, cmd, turnamt, false);
}
else
{
K_BotItemDropTarget(player, cmd);
}
break;
case KITEM_THUNDERSHIELD: case KITEM_THUNDERSHIELD:
K_BotItemThunder(player, cmd); K_BotItemThunder(player, cmd);
break; break;

View file

@ -418,6 +418,8 @@ static boolean K_FindObjectsForNudging(mobj_t *thing)
case MT_SSMINE: case MT_SSMINE:
case MT_SSMINE_SHIELD: case MT_SSMINE_SHIELD:
case MT_LANDMINE: case MT_LANDMINE:
case MT_DROPTARGET:
case MT_DROPTARGET_SHIELD:
case MT_BALLHOG: case MT_BALLHOG:
case MT_SPB: case MT_SPB:
case MT_BUBBLESHIELDTRAP: case MT_BUBBLESHIELDTRAP:

View file

@ -446,6 +446,180 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
return true; 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) boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
{ {
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) 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 if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD || t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD
|| t2->type == MT_SSMINE || t2->type == MT_SSMINE_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) || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
return false; return false;

View file

@ -11,6 +11,8 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2);
boolean K_MineCollide(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_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
boolean K_LandMineCollide(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_KitchenSinkCollide(mobj_t *t1, mobj_t *t2);
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2);
boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2);

View file

@ -121,6 +121,7 @@ static patch_t *kp_orbinaut[5];
static patch_t *kp_jawz[2]; static patch_t *kp_jawz[2];
static patch_t *kp_mine[2]; static patch_t *kp_mine[2];
static patch_t *kp_landmine[2]; static patch_t *kp_landmine[2];
static patch_t *kp_droptarget[2];
static patch_t *kp_ballhog[2]; static patch_t *kp_ballhog[2];
static patch_t *kp_selfpropelledbomb[2]; static patch_t *kp_selfpropelledbomb[2];
static patch_t *kp_grow[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_jawz[0] = W_CachePatchName("K_ITJAWZ", PU_HUDGFX);
kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX); kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX);
kp_landmine[0] = W_CachePatchName("K_ITLNDM", 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_ballhog[0] = W_CachePatchName("K_ITBHOG", PU_HUDGFX);
kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX); kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX);
kp_grow[0] = W_CachePatchName("K_ITGROW", 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_jawz[1] = W_CachePatchName("K_ISJAWZ", PU_HUDGFX);
kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX); kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX);
kp_landmine[1] = W_CachePatchName("K_ISLNDM", 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_ballhog[1] = W_CachePatchName("K_ISBHOG", PU_HUDGFX);
kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX); kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX);
kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX); kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX);
@ -1111,7 +1114,7 @@ static void K_drawKartItem(void)
if (stplyr->skincolor) if (stplyr->skincolor)
localcolor = 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 // Each case is handled in threes, to give three frames of in-game time to see the item on the roulette
case 0: // Sneaker case 0: // Sneaker
@ -1178,6 +1181,10 @@ static void K_drawKartItem(void)
localpatch = kp_landmine[offset]; localpatch = kp_landmine[offset];
//localcolor = SKINCOLOR_JET; //localcolor = SKINCOLOR_JET;
break; break;
case 16: // Land Mine
localpatch = kp_droptarget[offset];
//localcolor = SKINCOLOR_LIME;
break;
/*case 15: // Pogo Spring /*case 15: // Pogo Spring
localpatch = kp_pogospring[offset]; localpatch = kp_pogospring[offset];
localcolor = SKINCOLOR_TANGERINE; localcolor = SKINCOLOR_TANGERINE;
@ -1266,6 +1273,9 @@ static void K_drawKartItem(void)
case KITEM_LANDMINE: case KITEM_LANDMINE:
localpatch = kp_landmine[offset]; localpatch = kp_landmine[offset];
break; break;
case KITEM_DROPTARGET:
localpatch = kp_droptarget[offset];
break;
case KITEM_BALLHOG: case KITEM_BALLHOG:
localpatch = kp_ballhog[offset]; localpatch = kp_ballhog[offset];
break; break;
@ -4551,6 +4561,7 @@ static void K_drawDistributionDebugger(void)
kp_jawz[1], kp_jawz[1],
kp_mine[1], kp_mine[1],
kp_landmine[1], kp_landmine[1],
kp_droptarget[1],
kp_ballhog[1], kp_ballhog[1],
kp_selfpropelledbomb[1], kp_selfpropelledbomb[1],
kp_grow[1], kp_grow[1],

View file

@ -215,6 +215,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_jawz); CV_RegisterVar(&cv_jawz);
CV_RegisterVar(&cv_mine); CV_RegisterVar(&cv_mine);
CV_RegisterVar(&cv_landmine); CV_RegisterVar(&cv_landmine);
CV_RegisterVar(&cv_droptarget);
CV_RegisterVar(&cv_ballhog); CV_RegisterVar(&cv_ballhog);
CV_RegisterVar(&cv_selfpropelledbomb); CV_RegisterVar(&cv_selfpropelledbomb);
CV_RegisterVar(&cv_grow); CV_RegisterVar(&cv_grow);
@ -321,6 +322,7 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] =
&cv_jawz, &cv_jawz,
&cv_mine, &cv_mine,
&cv_landmine, &cv_landmine,
&cv_droptarget,
&cv_ballhog, &cv_ballhog,
&cv_selfpropelledbomb, &cv_selfpropelledbomb,
&cv_grow, &cv_grow,
@ -350,12 +352,12 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker /*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker
/*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility /*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 /*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 /*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine /*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 /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow /*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 /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring
/*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink /*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 x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3 /*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana 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 /*Pogo Spring*/ { 2, 0 }, // Pogo Spring
/*Super Ring*/ { 0, 0 }, // Super Ring /*Super Ring*/ { 0, 0 }, // Super Ring
/*Kitchen Sink*/ { 0, 0 }, // Kitchen Sink /*Kitchen Sink*/ { 0, 0 }, // Kitchen Sink
/*Drop Target*/ { 0, 0 }, // Drop Target
/*Sneaker x2*/ { 0, 0 }, // Sneaker x2 /*Sneaker x2*/ { 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 1, 1 }, // Sneaker x3 /*Sneaker x3*/ { 1, 1 }, // Sneaker x3
/*Banana x3*/ { 1, 0 }, // Banana x3 /*Banana x3*/ { 1, 0 }, // Banana x3
@ -674,6 +678,7 @@ INT32 K_KartGetItemOdds(
case KITEM_ROCKETSNEAKER: case KITEM_ROCKETSNEAKER:
case KITEM_JAWZ: case KITEM_JAWZ:
case KITEM_LANDMINE: case KITEM_LANDMINE:
case KITEM_DROPTARGET:
case KITEM_BALLHOG: case KITEM_BALLHOG:
case KRITEM_TRIPLESNEAKER: case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEORBINAUT: case KRITEM_TRIPLEORBINAUT:
@ -1231,6 +1236,10 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
else else
weight += 3*FRACUNIT; weight += 3*FRACUNIT;
break; break;
case MT_DROPTARGET:
case MT_DROPTARGET_SHIELD:
if (against->player)
weight = K_PlayerWeight(against, NULL);
default: default:
break; break;
} }
@ -1264,6 +1273,12 @@ static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2)
{ {
S_StartSound(mobj1, sfx_s3k44); 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 else
{ {
S_StartSound(mobj1, sfx_s3k49); 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)) || (mobj2->player && mobj2->player->respawn.state != RESPAWNST_NONE))
return false; return false;
if (mobj1->type != MT_DROPTARGET && mobj1->type != MT_DROPTARGET_SHIELD)
{ // Don't bump if you're flashing { // Don't bump if you're flashing
INT32 flash; INT32 flash;
@ -4857,6 +4873,12 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
// Shoot forward // Shoot forward
mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); 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 else
@ -4886,7 +4908,7 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
if (mo) if (mo)
{ {
angle_t fa = player->mo->angle>>ANGLETOFINESHIFT; 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); P_SetObjectMomZ(mo, HEIGHT, false);
mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED*dir); 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 || if (mobj->type == MT_BANANA_SHIELD || mobj->type == MT_JAWZ_SHIELD ||
mobj->type == MT_SSMINE_SHIELD || mobj->type == MT_EGGMANITEM_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) if (mobj->target && mobj->target->player)
{ {
@ -5555,6 +5578,9 @@ void K_DropHnextList(player_t *player, boolean keepshields)
{ {
nextwork = work->hnext; nextwork = work->hnext;
if (!work->health)
continue; // taking care of itself
switch (work->type) switch (work->type)
{ {
// Kart orbit items // Kart orbit items
@ -5576,6 +5602,11 @@ void K_DropHnextList(player_t *player, boolean keepshields)
dropall = false; dropall = false;
type = MT_SSMINE; type = MT_SSMINE;
break; break;
case MT_DROPTARGET_SHIELD:
orbit = false;
dropall = false;
type = MT_DROPTARGET;
break;
case MT_EGGMANITEM_SHIELD: case MT_EGGMANITEM_SHIELD:
orbit = false; orbit = false;
type = MT_EGGMANITEM; type = MT_EGGMANITEM;
@ -5598,14 +5629,24 @@ void K_DropHnextList(player_t *player, boolean keepshields)
P_SetScale(dropwork, work->scale); P_SetScale(dropwork, work->scale);
dropwork->destscale = K_ItemScaleForPlayer(player); //work->destscale; dropwork->destscale = K_ItemScaleForPlayer(player); //work->destscale;
dropwork->scalespeed = work->scalespeed; dropwork->scalespeed = work->scalespeed;
dropwork->spritexscale = work->spritexscale;
dropwork->spriteyscale = work->spriteyscale;
dropwork->flags |= MF_NOCLIPTHING; dropwork->flags |= MF_NOCLIPTHING;
dropwork->flags2 = work->flags2; dropwork->flags2 = work->flags2;
dropwork->eflags = work->eflags; 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->floorz = work->floorz;
dropwork->ceilingz = work->ceilingz; 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 // Copy interp data
dropwork->old_angle = work->old_angle; dropwork->old_angle = work->old_angle;
dropwork->old_x = work->old_x; dropwork->old_x = work->old_x;
@ -5673,14 +5714,22 @@ void K_DropHnextList(player_t *player, boolean keepshields)
} }
else else
{ {
dropwork->color = work->color;
dropwork->angle -= ANGLE_90; dropwork->angle -= ANGLE_90;
} }
} }
else // plop on the ground else // plop on the ground
{ {
dropwork->flags &= ~MF_NOCLIPTHING;
dropwork->threshold = 10; 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); P_RemoveMobj(work);
@ -6192,10 +6241,12 @@ static void K_MoveHeldObjects(player_t *player)
break; break;
case MT_BANANA_SHIELD: // Kart trailing items case MT_BANANA_SHIELD: // Kart trailing items
case MT_SSMINE_SHIELD: case MT_SSMINE_SHIELD:
case MT_DROPTARGET_SHIELD:
case MT_EGGMANITEM_SHIELD: case MT_EGGMANITEM_SHIELD:
case MT_SINK_SHIELD: case MT_SINK_SHIELD:
{ {
mobj_t *cur = player->mo->hnext; mobj_t *cur = player->mo->hnext;
mobj_t *curnext;
mobj_t *targ = player->mo; mobj_t *targ = player->mo;
if (P_IsObjectOnGround(player->mo) && player->speed > 0) 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 targx, targy, targz;
fixed_t speed, dist; fixed_t speed, dist;
curnext = cur->hnext;
if (cur->type == MT_EGGMANITEM_SHIELD) if (cur->type == MT_EGGMANITEM_SHIELD)
{ {
// Decided that this should use their "canon" color. // Decided that this should use their "canon" color.
cur->color = SKINCOLOR_BLACK; 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; cur->flags &= ~MF_NOCLIPTHING;
@ -6221,7 +6278,7 @@ static void K_MoveHeldObjects(player_t *player)
if (!cur->health) if (!cur->health)
{ {
cur = cur->hnext; cur = curnext;
continue; continue;
} }
@ -6239,7 +6296,10 @@ static void K_MoveHeldObjects(player_t *player)
dist = cur->extravalue1/2; dist = cur->extravalue1/2;
if (!targ || P_MobjWasRemoved(targ)) if (!targ || P_MobjWasRemoved(targ))
{
cur = curnext;
continue; continue;
}
// Shrink your items if the player shrunk too. // Shrink your items if the player shrunk too.
P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), finalscale))); 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); P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false);
if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT)
{
P_MoveOrigin(cur, targx, targy, cur->z); P_MoveOrigin(cur, targx, targy, cur->z);
if (P_MobjWasRemoved(cur))
{
cur = curnext;
continue;
}
}
if (P_IsObjectOnGround(cur)) 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->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false);
} }
cur = cur->hnext; cur = curnext;
} }
} }
break; break;
@ -9250,6 +9317,33 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_PlayAttackTaunt(player->mo); K_PlayAttackTaunt(player->mo);
} }
break; 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: case KITEM_BALLHOG:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{ {

View file

@ -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_ORBINAUT || target->type == MT_ORBINAUT_SHIELD
|| target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_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_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_EGGMANITEM || target->type == MT_EGGMANITEM_SHIELD
|| target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items || target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items
target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000 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 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_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)) || (target->type == MT_SINK_SHIELD && target->target->player->itemtype == KITEM_KITCHENSINK))
{ {
if (target->movedir != 0 && target->movedir < (UINT16)target->target->player->itemamount) 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; break;
case MT_DROPTARGET:
case MT_DROPTARGET_SHIELD:
target->fuse = 1;
break;
default: default:
break; break;
} }
@ -1834,6 +1841,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{ {
laglength = 2; laglength = 2;
} }
else if (target->type == MT_DROPTARGET || target->type == MT_DROPTARGET_SHIELD)
{
laglength = 0; // handled elsewhere
}
// Everything above here can't be forced. // Everything above here can't be forced.
if (!metalrecording) 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! // Check if the player is allowed to be damaged!
// If not, then spawn the instashield effect instead. // If not, then spawn the instashield effect instead.
if (!force) if (!force && !(inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1 == 1))
{ {
if (gametyperules & GTR_BUMPERS) if (gametyperules & GTR_BUMPERS)
{ {

View file

@ -768,50 +768,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->z + tmthing->height < thing->z) if (tmthing->z + tmthing->height < thing->z)
return true; // underneath return true; // underneath
if (tmthing->type == MT_PLAYER) return K_BubbleShieldCollide(thing, tmthing);
{
// 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;
} }
else if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->bubbleblowup) else if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->bubbleblowup)
|| (tmthing->player && tmthing->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) if (tmthing->z + tmthing->height < thing->z)
return true; // underneath return true; // underneath
if (thing->type == MT_PLAYER) return K_BubbleShieldCollide(tmthing, thing);
{
// 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;
} }
// double make sure bubbles won't collide with anything else // double make sure bubbles won't collide with anything else
if (thing->type == MT_BUBBLESHIELD || tmthing->type == MT_BUBBLESHIELD) if (thing->type == MT_BUBBLESHIELD || tmthing->type == MT_BUBBLESHIELD)
return true; 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 if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD
|| tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD)
{ {

View file

@ -1179,6 +1179,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_EGGMANITEM: case MT_EGGMANITEM:
case MT_SSMINE: case MT_SSMINE:
case MT_LANDMINE: case MT_LANDMINE:
case MT_DROPTARGET:
case MT_SINK: case MT_SINK:
case MT_EMERALD: case MT_EMERALD:
if (mo->extravalue2 > 0) if (mo->extravalue2 > 0)
@ -2045,7 +2046,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
|| (mo->z + mo->height >= mo->subsector->sector->ceilingheight || (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))) && ((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) == 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 true;
return false; return false;
@ -2143,6 +2145,7 @@ boolean P_ZMovement(mobj_t *mo)
case MT_BALLHOG: case MT_BALLHOG:
case MT_SSMINE: case MT_SSMINE:
case MT_LANDMINE: case MT_LANDMINE:
case MT_DROPTARGET:
case MT_BUBBLESHIELDTRAP: case MT_BUBBLESHIELDTRAP:
// Remove stuff from death pits. // Remove stuff from death pits.
if (P_CheckDeathPitCollide(mo)) if (P_CheckDeathPitCollide(mo))
@ -4866,6 +4869,7 @@ boolean P_IsKartItem(INT32 type)
{ {
if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD || if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD ||
type == MT_BANANA || type == MT_BANANA_SHIELD || type == MT_BANANA || type == MT_BANANA_SHIELD ||
type == MT_DROPTARGET || type == MT_DROPTARGET_SHIELD ||
type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD || type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD ||
type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD ||
type == MT_SSMINE || type == MT_SSMINE_SHIELD || type == MT_SSMINE || type == MT_SSMINE_SHIELD ||
@ -4903,12 +4907,14 @@ static void P_RemoveKartItem(mobj_t *thing)
{ {
mobj_t *mo; mobj_t *mo;
for (mo = kitemcap; mo; mo = mo->itnext) for (mo = kitemcap; mo; mo = mo->itnext)
if (mo->itnext == thing) {
{ if (mo->itnext != thing)
P_SetTarget(&mo->itnext, thing->itnext); continue;
P_SetTarget(&thing->itnext, NULL);
return; P_SetTarget(&mo->itnext, thing->itnext);
} P_SetTarget(&thing->itnext, NULL);
return;
}
} }
// Doesn't actually do anything since items have their own thinkers, // 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); 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->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45;
blast->destscale *= 4;
if (i & 1) if (i & 1)
{ {
blast->angle += ANGLE_90; blast->angle += ANGLE_90;
S_StartSound(blast, sfx_cdfm64); S_StartSound(blast, sfx_cdfm64);
} }
P_InitAngle(blast, blast->angle);
blast->destscale *= 4;
} }
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
@ -6164,6 +6171,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
case MT_BANANA: case MT_BANANA:
case MT_EGGMANITEM: case MT_EGGMANITEM:
case MT_LANDMINE: case MT_LANDMINE:
//case MT_DROPTARGET:
case MT_SPB: case MT_SPB:
if (P_IsObjectOnGround(mobj)) if (P_IsObjectOnGround(mobj))
{ {
@ -6843,6 +6851,45 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->health = 1; 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) if (mobj->threshold > 0)
mobj->threshold--; mobj->threshold--;
break; break;
@ -9050,6 +9097,13 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->hitlag > 0) if (mobj->hitlag > 0)
{ {
mobj->hitlag--; mobj->hitlag--;
if (mobj->type == MT_DROPTARGET && mobj->reactiontime > 0 && mobj->hitlag == 2)
{
mobj->spritexscale = FRACUNIT;
mobj->spriteyscale = 5*FRACUNIT;
}
return; return;
} }
@ -9234,7 +9288,8 @@ void P_MobjThinker(mobj_t *mobj)
|| mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_CANNONBALLDECOR
|| mobj->type == MT_FALLINGROCK || mobj->type == MT_FALLINGROCK
|| mobj->type == MT_ORBINAUT || 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 P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly
if (P_MobjWasRemoved(mobj)) // anything that calls checkposition can be lethal if (P_MobjWasRemoved(mobj)) // anything that calls checkposition can be lethal
return; return;
@ -9547,6 +9602,11 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
thing->shadowscale = 3*FRACUNIT/2; thing->shadowscale = 3*FRACUNIT/2;
thing->whiteshadow = false; thing->whiteshadow = false;
break; break;
case MT_DROPTARGET:
case MT_DROPTARGET_SHIELD:
thing->shadowscale = 5*FRACUNIT/4;
thing->whiteshadow = true;
break;
case MT_THUNDERSHIELD: case MT_THUNDERSHIELD:
case MT_BUBBLESHIELD: case MT_BUBBLESHIELD:
case MT_BUBBLESHIELDTRAP: case MT_BUBBLESHIELDTRAP:
@ -10082,6 +10142,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
} }
} }
break; break;
case MT_DROPTARGET:
case MT_DROPTARGET_SHIELD:
mobj->color = SKINCOLOR_LIME;
mobj->colorized = true;
mobj->renderflags |= RF_FULLBRIGHT;
break;
case MT_SMK_MOLE: case MT_SMK_MOLE:
mobj->reactiontime = P_RandomRange(0, 3*mobj->info->reactiontime/2); // Random delay on start of level mobj->reactiontime = P_RandomRange(0, 3*mobj->info->reactiontime/2); // Random delay on start of level
break; break;