Merge branch 'capsules-improvement' into 'master'

Break the Capsules additions

See merge request KartKrew/Kart!793
This commit is contained in:
toaster 2022-12-20 21:26:46 +00:00
commit 33167078c8
16 changed files with 488 additions and 24 deletions

View file

@ -383,12 +383,14 @@ consvar_t cv_items[NUMKARTRESULTS-1] = {
CVAR_INIT ("kitchensink", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("droptarget", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("gardentop", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("gachabom", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("dualsneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplesneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplebanana", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("quadorbinaut", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL)
CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplegachabom", "On", CV_NETVAR, CV_OnOff, NULL)
};
consvar_t cv_kartspeed = CVAR_INIT ("gamespeed", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange);

View file

@ -154,7 +154,8 @@ Run this macro, then #undef FOREACH afterward
FOREACH (SUPERRING, 19),\
FOREACH (KITCHENSINK, 20),\
FOREACH (DROPTARGET, 21),\
FOREACH (GARDENTOP, 22)
FOREACH (GARDENTOP, 22),\
FOREACH (GACHABOM, 23)
typedef enum
{
@ -171,6 +172,7 @@ typedef enum
KRITEM_TRIPLEORBINAUT,
KRITEM_QUADORBINAUT,
KRITEM_DUALJAWZ,
KRITEM_TRIPLEGACHABOM,
NUMKARTRESULTS
} kartitems_t;

View file

@ -5379,6 +5379,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_SINK_SHIELD",
"MT_SINKTRAIL",
"MT_GACHABOM",
"MT_DUELBOMB", // Duel mode bombs
"MT_BATTLEBUMPER", // Battle Mode bumper
@ -6787,6 +6789,7 @@ struct int_const_s const INT_CONST[] = {
{"KRITEM_TRIPLEORBINAUT",KRITEM_TRIPLEORBINAUT},
{"KRITEM_QUADORBINAUT",KRITEM_QUADORBINAUT},
{"KRITEM_DUALJAWZ",KRITEM_DUALJAWZ},
{"KRITEM_TRIPLEGACHABOM",KRITEM_TRIPLEGACHABOM},
{"NUMKARTRESULTS",NUMKARTRESULTS},
// kartshields_t

View file

@ -24193,6 +24193,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_GACHABOM
-1, // doomednum
S_ORBINAUT1, // spawnstate
7, // spawnhealth
S_NULL, // seestate
sfx_tossed, // seesound
8, // reactiontime
sfx_s3k49, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_ORBINAUT_DEAD,// deathstate
S_NULL, // xdeathstate
sfx_s3k5d, // deathsound
64*FRACUNIT, // speed
24*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_s3k96, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
S_NULL // raisestate
},
{ // MT_DUELBOMB
2050, // doomednum
S_SPB1, // spawnstate

View file

@ -6433,6 +6433,8 @@ typedef enum mobj_type
MT_SINK_SHIELD,
MT_SINKTRAIL,
MT_GACHABOM,
MT_DUELBOMB, // Duel mode bombs
MT_BATTLEBUMPER, // Battle Mode bumpers

View file

@ -1558,6 +1558,11 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
case KITEM_FLAMESHIELD:
K_BotItemFlame(player, cmd);
break;
/*
case KITEM_GACHABOM:
K_BotItemGachabom(player, cmd);
break;
*/
}
}
}

View file

@ -415,6 +415,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
case MT_SPB:
case MT_BUBBLESHIELDTRAP:
case MT_DUELBOMB:
case MT_GACHABOM:
K_AddDodgeObject(thing, side, 20);
break;
case MT_SHRINK_GUN:

View file

@ -87,7 +87,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD
|| t2->type == MT_JAWZ || t2->type == MT_JAWZ_SHIELD
|| t2->type == MT_BALLHOG)
|| t2->type == MT_BALLHOG || t2->type == MT_GACHABOM)
{
// Other Item Damage
angle_t bounceangle = K_GetCollideAngle(t1, t2);
@ -353,7 +353,8 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
}
}
else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD
|| t2->type == MT_GACHABOM)
{
// Bomb death
angle_t bounceangle = K_GetCollideAngle(t1, t2);
@ -415,7 +416,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD
|| t2->type == MT_JAWZ || t2->type == MT_JAWZ_SHIELD
|| t2->type == MT_BALLHOG)
|| t2->type == MT_BALLHOG || t2->type == MT_GACHABOM)
{
// Other Item Damage
angle_t bounceangle = K_GetCollideAngle(t1, t2);

View file

@ -173,6 +173,11 @@ static patch_t *kp_bossret[4];
static patch_t *kp_trickcool[2];
static patch_t *kp_capsuletarget_arrow[2][2];
static patch_t *kp_capsuletarget_icon[2];
static patch_t *kp_capsuletarget_far[2];
static patch_t *kp_capsuletarget_near[8];
void K_LoadKartHUDGraphics(void)
{
INT32 i, j, k;
@ -644,6 +649,39 @@ void K_LoadKartHUDGraphics(void)
buffer[7] = '0'+((i+1)%10);
HU_UpdatePatch(&kp_bossret[i], "%s", buffer);
}
sprintf(buffer, "HCAPARxx");
for (i = 0; i < 2; i++)
{
buffer[6] = 'A'+i;
for (j = 0; j < 2; j++)
{
buffer[7] = '0'+j;
HU_UpdatePatch(&kp_capsuletarget_arrow[i][j], "%s", buffer);
}
}
sprintf(buffer, "HUDCAPCx");
for (i = 0; i < 2; i++)
{
buffer[7] = '0'+i;
HU_UpdatePatch(&kp_capsuletarget_icon[i], "%s", buffer);
}
sprintf(buffer, "HUDCAPBx");
for (i = 0; i < 2; i++)
{
buffer[7] = '0'+i;
HU_UpdatePatch(&kp_capsuletarget_far[i], "%s", buffer);
}
sprintf(buffer, "HUDCAPAx");
for (i = 0; i < 8; i++)
{
buffer[7] = '0'+i;
HU_UpdatePatch(&kp_capsuletarget_near[i], "%s", buffer);
}
}
// For the item toggle menu
@ -699,6 +737,9 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny)
return (tiny ? "K_ISDTRG" : "K_ITDTRG");
case KITEM_GARDENTOP:
return (tiny ? "K_ISGTOP" : "K_ITGTOP");
case KITEM_GACHABOM: // temp
case KRITEM_TRIPLEGACHABOM: // temp
return (tiny ? "K_ISSINK" : "K_ITSINK");
case KRITEM_TRIPLEORBINAUT:
return (tiny ? "K_ISORBN" : "K_ITORB3");
case KRITEM_QUADORBINAUT:
@ -735,6 +776,7 @@ static patch_t *K_GetCachedItemPatch(INT32 item, UINT8 offset)
kp_kitchensink,
kp_droptarget,
kp_gardentop,
kp_kitchensink, // temp
};
if (item == KITEM_SAD || (item > KITEM_NONE && item < NUMKARTITEMS))
@ -778,7 +820,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean revers
fixed_t fovDiff, fov, fovTangent, fg;
fixed_t h;
INT32 da;
INT32 da, dp;
UINT8 cameraNum = R_GetViewNumber();
@ -839,6 +881,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean revers
// Determine viewpoint factors.
h = R_PointToDist2(point->x, point->y, viewx, viewy);
da = AngleDeltaSigned(viewpointAngle, R_PointToAngle2(point->x, point->y, viewx, viewy));
dp = AngleDeltaSigned(viewpointAiming, R_PointToAngle2(0, 0, h, viewz));
if (reverse)
{
@ -849,6 +892,10 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean revers
result->x = FixedMul(NEWTAN(da), fg);
result->y = FixedMul((NEWTAN(viewpointAiming) - FixedDiv((viewz - point->z), 1 + FixedMul(NEWCOS(da), h))), fg);
result->angle = da;
result->pitch = dp;
result->fov = fg;
// Rotate for screen roll...
if (viewpointRoll)
{
@ -3075,6 +3122,217 @@ static void K_DrawWeakSpot(weakspotdraw_t *ws)
V_DrawFixedPatch(ws->x, ws->y, FRACUNIT, 0, kp_bossret[j+1], colormap);
}
typedef struct capsuletracking_s
{
mobj_t *mobj;
vector3_t point;
fixed_t camDist;
} capsuletracking_t;
static void K_DrawCapsuleTracking(capsuletracking_t *caps)
{
trackingResult_t result = {0};
INT32 timer = 0;
K_ObjectTracking(&result, &caps->point, false);
if (result.onScreen == false)
{
// Off-screen, draw alongside the borders of the screen.
// Probably the most complicated thing.
INT32 scrVal = 240;
vector2_t screenSize = {0};
INT32 borderSize = 7;
vector2_t borderWin = {0};
vector2_t borderDir = {0};
fixed_t borderLen = FRACUNIT;
vector2_t arrowDir = {0};
vector2_t arrowPos = {0};
patch_t *arrowPatch = NULL;
INT32 arrowFlags = 0;
vector2_t capsulePos = {0};
patch_t *capsulePatch = NULL;
timer = (leveltime / 3);
screenSize.x = vid.width / vid.dupx;
screenSize.y = vid.height / vid.dupy;
if (r_splitscreen >= 2)
{
// Half-wide screens
screenSize.x >>= 1;
borderSize >>= 1;
}
if (r_splitscreen >= 1)
{
// Half-tall screens
screenSize.y >>= 1;
}
scrVal = max(screenSize.x, screenSize.y) - 80;
borderWin.x = screenSize.x - borderSize;
borderWin.y = screenSize.y - borderSize;
arrowDir.x = 0;
arrowDir.y = P_MobjFlip(caps->mobj) * FRACUNIT;
// Simply pointing towards the result doesn't work, so inaccurate hack...
borderDir.x = FixedMul(
FixedMul(
FINESINE((-result.angle >> ANGLETOFINESHIFT) & FINEMASK),
FINECOSINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK)
),
result.fov
);
borderDir.y = FixedMul(
FINESINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK),
result.fov
);
borderLen = R_PointToDist2(0, 0, borderDir.x, borderDir.y);
if (borderLen > 0)
{
borderDir.x = FixedDiv(borderDir.x, borderLen);
borderDir.y = FixedDiv(borderDir.y, borderLen);
}
else
{
// Eh just put it at the bottom.
borderDir.x = 0;
borderDir.y = FRACUNIT;
}
capsulePatch = kp_capsuletarget_icon[timer & 1];
if (abs(borderDir.x) > abs(borderDir.y))
{
// Horizontal arrow
arrowPatch = kp_capsuletarget_arrow[1][timer & 1];
arrowDir.y = 0;
if (borderDir.x < 0)
{
// LEFT
arrowDir.x = -FRACUNIT;
}
else
{
// RIGHT
arrowDir.x = FRACUNIT;
}
}
else
{
// Vertical arrow
arrowPatch = kp_capsuletarget_arrow[0][timer & 1];
arrowDir.x = 0;
if (borderDir.y < 0)
{
// UP
arrowDir.y = -FRACUNIT;
}
else
{
// DOWN
arrowDir.y = FRACUNIT;
}
}
arrowPos.x = (screenSize.x >> 1) + FixedMul(scrVal, borderDir.x);
arrowPos.y = (screenSize.y >> 1) + FixedMul(scrVal, borderDir.y);
arrowPos.x = min(max(arrowPos.x, borderSize), borderWin.x) * FRACUNIT;
arrowPos.y = min(max(arrowPos.y, borderSize), borderWin.y) * FRACUNIT;
capsulePos.x = arrowPos.x - (arrowDir.x * 12);
capsulePos.y = arrowPos.y - (arrowDir.y * 12);
arrowPos.x -= (arrowPatch->width << FRACBITS) >> 1;
arrowPos.y -= (arrowPatch->height << FRACBITS) >> 1;
capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1;
capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1;
if (arrowDir.x < 0)
{
arrowPos.x += arrowPatch->width << FRACBITS;
arrowFlags |= V_FLIP;
}
if (arrowDir.y < 0)
{
arrowPos.y += arrowPatch->height << FRACBITS;
arrowFlags |= V_VFLIP;
}
V_DrawFixedPatch(
capsulePos.x, capsulePos.y,
FRACUNIT,
V_SPLITSCREEN,
capsulePatch, NULL
);
V_DrawFixedPatch(
arrowPos.x, arrowPos.y,
FRACUNIT,
V_SPLITSCREEN | arrowFlags,
arrowPatch, NULL
);
}
else
{
// Draw simple overlay.
const fixed_t farDistance = 1280*mapobjectscale;
boolean useNear = (caps->camDist < farDistance);
patch_t *capsulePatch = NULL;
vector2_t capsulePos = {0};
boolean visible = P_CheckSight(stplyr->mo, caps->mobj);
if (visible == false && (leveltime & 1))
{
// Flicker when not visible.
return;
}
capsulePos.x = result.x;
capsulePos.y = result.y;
if (useNear == true)
{
timer = (leveltime / 2);
capsulePatch = kp_capsuletarget_near[timer % 8];
}
else
{
timer = (leveltime / 3);
capsulePatch = kp_capsuletarget_far[timer & 1];
}
capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1;
capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1;
V_DrawFixedPatch(
capsulePos.x, capsulePos.y,
FRACUNIT,
V_SPLITSCREEN,
capsulePatch, NULL
);
}
}
static void K_drawKartNameTags(void)
{
const fixed_t maxdistance = 8192*mapobjectscale;
@ -3083,7 +3341,7 @@ static void K_drawKartNameTags(void)
UINT8 tobesorted[MAXPLAYERS];
fixed_t sortdist[MAXPLAYERS];
UINT8 sortlen = 0;
UINT8 i, j;
size_t i, j;
if (stplyr == NULL || stplyr->mo == NULL || P_MobjWasRemoved(stplyr->mo))
{
@ -3174,6 +3432,85 @@ static void K_drawKartNameTags(void)
}
}
if (battlecapsules == true)
{
#define MAX_CAPSULE_HUD 32
capsuletracking_t capsuleList[MAX_CAPSULE_HUD];
size_t capsuleListLen = 0;
mobj_t *mobj = NULL;
mobj_t *next = NULL;
for (mobj = kitemcap; mobj; mobj = next)
{
capsuletracking_t *caps = NULL;
next = mobj->itnext;
if (mobj->health <= 0)
{
continue;
}
if (mobj->type != MT_BATTLECAPSULE)
{
continue;
}
caps = &capsuleList[capsuleListLen];
caps->mobj = mobj;
caps->point.x = R_InterpolateFixed(mobj->old_x, mobj->x);
caps->point.y = R_InterpolateFixed(mobj->old_y, mobj->y);
caps->point.z = R_InterpolateFixed(mobj->old_z, mobj->z);
caps->point.z += (mobj->height >> 1);
caps->camDist = R_PointToDist2(c.x, c.y, caps->point.x, caps->point.y);
capsuleListLen++;
if (capsuleListLen >= MAX_CAPSULE_HUD)
{
break;
}
}
if (capsuleListLen > 0)
{
// Sort by distance from camera.
if (capsuleListLen > 1)
{
for (i = 0; i < capsuleListLen-1; i++)
{
size_t swap = i;
for (j = i + 1; j < capsuleListLen; j++)
{
capsuletracking_t *cj = &capsuleList[j];
capsuletracking_t *cSwap = &capsuleList[swap];
if (cj->camDist > cSwap->camDist)
{
swap = j;
}
}
if (swap != i)
{
capsuletracking_t temp = capsuleList[swap];
capsuleList[swap] = capsuleList[i];
capsuleList[i] = temp;
}
}
}
for (i = 0; i < capsuleListLen; i++)
{
K_DrawCapsuleTracking(&capsuleList[i]);
}
}
#undef MAX_CAPSULE_HUD
}
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *ntplayer = &players[i];
@ -3288,7 +3625,7 @@ static void K_drawKartNameTags(void)
{
if (!(demo.playback == true && demo.freecam == true))
{
for (j = 0; j <= r_splitscreen; j++)
for (j = 0; j <= (unsigned)r_splitscreen; j++)
{
if (ntplayer == &players[displayplayers[j]])
{
@ -3296,7 +3633,7 @@ static void K_drawKartNameTags(void)
}
}
if (j <= r_splitscreen && j != cnum)
if (j <= (unsigned)r_splitscreen && j != cnum)
{
localindicator = j;
}

View file

@ -26,6 +26,8 @@ struct trackingResult_t
fixed_t x, y;
fixed_t scale;
boolean onScreen;
INT32 angle, pitch;
fixed_t fov;
};
void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean reverse);

View file

@ -433,6 +433,9 @@ SINT8 K_ItemResultToType(SINT8 getitem)
case KRITEM_DUALJAWZ:
return KITEM_JAWZ;
case KRITEM_TRIPLEGACHABOM:
return KITEM_GACHABOM;
default:
I_Error("Bad item cooldown redirect for result %d\n", getitem);
break;
@ -453,6 +456,7 @@ UINT8 K_ItemResultToAmount(SINT8 getitem)
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEBANANA:
case KRITEM_TRIPLEORBINAUT:
case KRITEM_TRIPLEGACHABOM:
return 3;
case KRITEM_QUADORBINAUT:
@ -577,6 +581,7 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
break;
case MT_ORBINAUT:
case MT_ORBINAUT_SHIELD:
case MT_GACHABOM:
case MT_DUELBOMB:
if (against->player)
weight = K_PlayerWeight(against, NULL);
@ -4305,7 +4310,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
finalscale = source->scale;
}
if (dir == -1 && (type == MT_ORBINAUT || type == MT_BALLHOG))
if (dir == -1 && (type == MT_ORBINAUT || type == MT_GACHABOM || type == MT_BALLHOG))
{
// Backwards nerfs
finalspeed /= 8;
@ -4362,6 +4367,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
switch (type)
{
case MT_ORBINAUT:
case MT_GACHABOM:
Obj_OrbinautThrown(th, finalspeed, dir);
break;
case MT_JAWZ:
@ -5209,6 +5215,12 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
dir = defaultDir;
}
if (mapthing == MT_GACHABOM && dir > 0)
{
// This item is both a missile and not!
missile = false;
}
if (missile) // Shootables
{
if (dir < 0 && mapthing != MT_SPB && mapthing != MT_GARDENTOP)
@ -5276,6 +5288,16 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
mo->rollangle = FixedAngle(P_RandomRange(PR_DECORATION, -180, 180) << FRACBITS);
}
if (mapthing == MT_GACHABOM)
{
// Set dropped flag
mo->flags2 |= MF2_AMBUSH;
mo->movecount = 2;
P_SetMobjState(mo, mo->info->deathstate);
mo->tics = -1;
mo->color = player->skincolor;
}
// this is the small graphic effect that plops in you when you throw an item:
throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FIREDITEM);
P_SetTarget(&throwmo->target, player->mo);
@ -10481,6 +10503,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_UpdateHnextList(player, true);
}
break;
case KITEM_GACHABOM:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
K_ThrowKartItem(player, true, MT_GACHABOM, 0, 0, 0);
K_PlayAttackTaunt(player->mo);
player->itemamount--;
K_UpdateHnextList(player, false);
}
break;
case KITEM_SAD:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO
&& !player->sadtimer)

View file

@ -98,12 +98,14 @@ static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
{ 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
{ 0, 0, 0, 3, 5, 0, 0, 0 }, // Garden Top
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // Gachabom
{ 0, 0, 2, 2, 2, 0, 0, 0 }, // Sneaker x2
{ 0, 0, 0, 0, 4, 4, 4, 0 }, // Sneaker x3
{ 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
{ 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3
{ 0, 0, 0, 2, 0, 0, 0, 0 }, // Orbinaut x4
{ 0, 0, 1, 2, 1, 0, 0, 0 } // Jawz x2
{ 0, 0, 1, 2, 1, 0, 0, 0 }, // Jawz x2
{ 0, 0, 0, 0, 0, 0, 0, 0 } // Gachabom x3
};
static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS-1][2] =
@ -131,12 +133,14 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS-1][2] =
{ 0, 0 }, // Kitchen Sink
{ 2, 0 }, // Drop Target
{ 4, 0 }, // Garden Top
{ 0, 0 }, // Gachabom
{ 0, 0 }, // Sneaker x2
{ 0, 1 }, // Sneaker x3
{ 0, 0 }, // Banana x3
{ 2, 0 }, // Orbinaut x3
{ 1, 1 }, // Orbinaut x4
{ 5, 1 } // Jawz x2
{ 5, 1 }, // Jawz x2
{ 0, 0 } // Gachabom x3
};
static kartitems_t K_KartItemReelTimeAttack[] =
@ -148,13 +152,14 @@ static kartitems_t K_KartItemReelTimeAttack[] =
static kartitems_t K_KartItemReelBreakTheCapsules[] =
{
KRITEM_TRIPLEORBINAUT,
KITEM_BANANA,
KITEM_GACHABOM,
KRITEM_TRIPLEGACHABOM,
KITEM_NONE
};
static kartitems_t K_KartItemReelBoss[] =
{
// FIXME: gachabom...?
KITEM_ORBINAUT,
KITEM_BANANA,
KITEM_NONE

View file

@ -184,7 +184,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
if (t2->player)
{
if ((t2->player->flashing > 0 && t2->hitlag == 0)
&& !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ))
&& !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_GACHABOM))
return true;
if (t2->player->hyudorotimer)
@ -209,7 +209,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD
|| t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_BALLHOG)
|| t2->type == MT_BALLHOG || t2->type == MT_GACHABOM)
{
// Other Item Damage
angle_t bounceangle = K_GetCollideAngle(t1, t2);

View file

@ -1001,7 +1001,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|| 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->type == MT_BALLHOG || target->type == MT_SPB
|| target->type == MT_GACHABOM)) // kart dead items
target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000
else
target->flags &= ~MF_NOGRAVITY; // lose it if you for whatever reason have it, I'm looking at you shields

View file

@ -874,7 +874,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
// Bubble Shield reflect
if (((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup)
|| (thing->player && thing->player->bubbleblowup))
&& (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ
&& (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_GACHABOM
|| tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG
|| tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK
|| tm.thing->type == MT_GARDENTOP
@ -890,7 +890,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
}
else if (((tm.thing->type == MT_BUBBLESHIELD && tm.thing->target->player && tm.thing->target->player->bubbleblowup)
|| (tm.thing->player && tm.thing->player->bubbleblowup))
&& (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ
&& (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_GACHABOM
|| thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG
|| thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK
|| thing->type == MT_GARDENTOP
@ -911,7 +911,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
// Droptarget reflect
if ((thing->type == MT_DROPTARGET || thing->type == MT_DROPTARGET_SHIELD)
&& (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ
&& (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_GACHABOM
|| tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG
|| tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK
|| tm.thing->type == MT_GARDENTOP
@ -926,7 +926,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return K_DropTargetCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
else if ((tm.thing->type == MT_DROPTARGET || tm.thing->type == MT_DROPTARGET_SHIELD)
&& (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ
&& (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_GACHABOM
|| thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG
|| thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK
|| thing->type == MT_GARDENTOP
@ -946,7 +946,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|| thing->type == MT_DROPTARGET_SHIELD || tm.thing->type == MT_DROPTARGET_SHIELD)
return BMIT_CONTINUE;
if (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ
if (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_GACHABOM
|| tm.thing->type == MT_ORBINAUT_SHIELD || tm.thing->type == MT_JAWZ_SHIELD
|| tm.thing->type == MT_GARDENTOP)
{
@ -958,7 +958,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return Obj_OrbinautJawzCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_GACHABOM
|| thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD
|| thing->type == MT_GARDENTOP)
{

View file

@ -1195,6 +1195,13 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_BATTLEBUMPER:
gravityadd /= 2;
break;
case MT_GACHABOM:
if (!(mo->flags2 & MF2_AMBUSH))
{
// Use normal gravity, unless if it was tossed.
break;
}
/*FALLTHRU*/
case MT_BANANA:
case MT_EGGMANITEM:
case MT_SSMINE:
@ -1742,7 +1749,7 @@ void P_XYMovement(mobj_t *mo)
//{ SRB2kart - Orbinaut, Ballhog
// Bump sparks
if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG)
if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG || mo->type == MT_GACHABOM)
{
mobj_t *fx;
fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP);
@ -1756,6 +1763,7 @@ void P_XYMovement(mobj_t *mo)
switch (mo->type)
{
case MT_ORBINAUT: // Orbinaut speed decreasing
case MT_GACHABOM:
case MT_GARDENTOP:
if (mo->health > 1)
{
@ -5174,6 +5182,7 @@ boolean P_IsKartFieldItem(INT32 type)
case MT_SINK:
case MT_DROPTARGET:
case MT_DUELBOMB:
case MT_GACHABOM:
return true;
default:
@ -6653,6 +6662,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
case MT_LANDMINE:
//case MT_DROPTARGET:
case MT_SPB:
case MT_GACHABOM:
if (P_IsObjectOnGround(mobj))
{
P_RemoveMobj(mobj);
@ -7077,6 +7087,39 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
}
break;
case MT_GACHABOM:
{
if (mobj->flags2 & MF2_AMBUSH)
{
mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy)
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
}
if (P_IsObjectOnGround(mobj))
{
if (mobj->movecount > 1)
{
S_StartSound(mobj, mobj->info->activesound);
mobj->momx = mobj->momy = 0;
mobj->movecount = 1;
}
}
if (mobj->threshold > 0)
mobj->threshold--;
break;
}
}
/* FALLTHRU */
case MT_ORBINAUT:
{
Obj_OrbinautThink(mobj);
@ -9822,6 +9865,7 @@ void P_MobjThinker(mobj_t *mobj)
|| mobj->type == MT_CANNONBALLDECOR
|| mobj->type == MT_FALLINGROCK
|| mobj->type == MT_ORBINAUT
|| mobj->type == MT_GACHABOM
|| mobj->type == MT_JAWZ
|| (mobj->type == MT_DROPTARGET && mobj->reactiontime))
{
@ -10100,6 +10144,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
case MT_ROCKETSNEAKER:
case MT_SPB:
case MT_DUELBOMB:
case MT_GACHABOM:
thing->shadowscale = 3*FRACUNIT/2;
break;
case MT_BANANA_SHIELD: