Merge branch 'ringbox' into 'master'

Ring Box

See merge request KartKrew/Kart!1292
This commit is contained in:
Oni 2023-06-27 09:47:15 +00:00
commit fe3790b0db
17 changed files with 463 additions and 102 deletions

View file

@ -433,6 +433,8 @@ consvar_t cv_kartbot = CVAR_INIT ("bots", "0", CV_NETVAR, kartbot_cons_t, NULL);
consvar_t cv_karteliminatelast = CVAR_INIT ("eliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); consvar_t cv_karteliminatelast = CVAR_INIT ("eliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange);
consvar_t cv_thunderdome = CVAR_INIT ("thunderdome", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartusepwrlv = CVAR_INIT ("usepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL); consvar_t cv_kartusepwrlv = CVAR_INIT ("usepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL);
static CV_PossibleValue_t kartdebugitem_cons_t[] = static CV_PossibleValue_t kartdebugitem_cons_t[] =

View file

@ -88,6 +88,7 @@ extern consvar_t cv_kartspeedometer;
extern consvar_t cv_kartvoices; extern consvar_t cv_kartvoices;
extern consvar_t cv_kartbot; extern consvar_t cv_kartbot;
extern consvar_t cv_karteliminatelast; extern consvar_t cv_karteliminatelast;
extern consvar_t cv_thunderdome;
extern consvar_t cv_kartusepwrlv; extern consvar_t cv_kartusepwrlv;
extern consvar_t cv_votetime; extern consvar_t cv_votetime;

View file

@ -192,6 +192,17 @@ typedef enum
NUMKARTSHIELDS NUMKARTSHIELDS
} kartshields_t; } kartshields_t;
typedef enum
{
KSM_BAR,
KSM_DOUBLEBAR,
KSM_TRIPLEBAR,
KSM_RING,
KSM_SEVEN,
KSM_JACKPOT,
KSM__MAX,
} kartslotmachine_t;
typedef enum typedef enum
{ {
KSPIN_THRUST = (1<<0), KSPIN_THRUST = (1<<0),
@ -410,6 +421,7 @@ struct itemroulette_t
tic_t elapsed; tic_t elapsed;
boolean eggman; boolean eggman;
boolean ringbox;
}; };
// enum for bot item priorities // enum for bot item priorities
@ -767,6 +779,9 @@ struct player_t
boolean markedfordeath; boolean markedfordeath;
UINT8 ringboxdelay; // Delay until Ring Box auto-activates
UINT8 ringboxaward; // Where did we stop?
fixed_t outrun; // Milky Way road effect fixed_t outrun; // Milky Way road effect
uint8_t public_key[PUBKEYLENGTH]; uint8_t public_key[PUBKEYLENGTH];

View file

@ -283,7 +283,6 @@ actionpointer_t actionpointers[] =
{{A_ChangeHeight}, "A_CHANGEHEIGHT"}, {{A_ChangeHeight}, "A_CHANGEHEIGHT"},
// SRB2Kart // SRB2Kart
{{A_ItemPop}, "A_ITEMPOP"},
{{A_JawzExplode}, "A_JAWZEXPLODE"}, {{A_JawzExplode}, "A_JAWZEXPLODE"},
{{A_SSMineSearch}, "A_SSMINESEARCH"}, {{A_SSMineSearch}, "A_SSMINESEARCH"},
{{A_SSMineExplode}, "A_SSMINEEXPLODE"}, {{A_SSMineExplode}, "A_SSMINEEXPLODE"},
@ -3223,7 +3222,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_RANDOMITEM10", "S_RANDOMITEM10",
"S_RANDOMITEM11", "S_RANDOMITEM11",
"S_RANDOMITEM12", "S_RANDOMITEM12",
"S_DEADRANDOMITEM",
// Ring Box
"S_RINGBOX1",
"S_RINGBOX2",
"S_RINGBOX3",
"S_RINGBOX4",
"S_RINGBOX5",
"S_RINGBOX6",
"S_RINGBOX7",
"S_RINGBOX8",
"S_RINGBOX9",
"S_RINGBOX10",
"S_RINGBOX11",
"S_RINGBOX12",
// Sphere Box (for Battle) // Sphere Box (for Battle)
"S_SPHEREBOX1", "S_SPHEREBOX1",
@ -3238,7 +3250,6 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_SPHEREBOX10", "S_SPHEREBOX10",
"S_SPHEREBOX11", "S_SPHEREBOX11",
"S_SPHEREBOX12", "S_SPHEREBOX12",
"S_DEADSPHEREBOX",
// Random Item Pop // Random Item Pop
"S_RANDOMITEMPOP1", "S_RANDOMITEMPOP1",

View file

@ -531,6 +531,7 @@ char sprnames[NUMSPRITES + 1][5] =
//SRB2kart Sprites (sort later) //SRB2kart Sprites (sort later)
"RNDM", // Random Item Box "RNDM", // Random Item Box
"SBOX", // Sphere Box (for Battle) "SBOX", // Sphere Box (for Battle)
"RBOX", // Ring Box
"RPOP", // Random Item Box Pop "RPOP", // Random Item Box Pop
"ITRI", // Item Box Debris "ITRI", // Item Box Debris
"ITPA", // Paper item backdrop "ITPA", // Paper item backdrop
@ -3895,7 +3896,19 @@ state_t states[NUMSTATES] =
{SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10 {SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10
{SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11 {SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11
{SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12 {SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12
{SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_RANDOMITEM1}, // S_DEADRANDOMITEM
{SPR_RBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX2}, // S_RINGBOX1
{SPR_RBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX3}, // S_RINGBOX2
{SPR_RBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX4}, // S_RINGBOX3
{SPR_RBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX5}, // S_RINGBOX4
{SPR_RBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX6}, // S_RINGBOX5
{SPR_RBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX7}, // S_RINGBOX6
{SPR_RBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX8}, // S_RINGBOX7
{SPR_RBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX9}, // S_RINGBOX8
{SPR_RBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX10}, // S_RINGBOX9
{SPR_RBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX11}, // S_RINGBOX10
{SPR_RBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX12}, // S_RINGBOX11
{SPR_RBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX1}, // S_RINGBOX12
{SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1 {SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1
{SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2 {SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2
@ -3909,7 +3922,6 @@ state_t states[NUMSTATES] =
{SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10 {SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10
{SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11 {SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11
{SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12 {SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12
{SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX
{SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1
{SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2
@ -22394,7 +22406,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
// SRB2kart MT's // SRB2kart MT's
{ // MT_RANDOMITEM { // MT_RANDOMITEM
2000, // doomednum 2000, // doomednum
S_RANDOMITEM1, // spawnstate S_RINGBOX1, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -22405,7 +22417,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_DEADRANDOMITEM, // deathstate S_NULL, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_kc2e, // deathsound sfx_kc2e, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
@ -22432,7 +22444,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_DEADSPHEREBOX, // deathstate S_NULL, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_kc2e, // deathsound sfx_kc2e, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed

View file

@ -277,7 +277,6 @@ enum actionnum
A_DRAGONWING, A_DRAGONWING,
A_DRAGONSEGMENT, A_DRAGONSEGMENT,
A_CHANGEHEIGHT, A_CHANGEHEIGHT,
A_ITEMPOP,
A_JAWZEXPLODE, A_JAWZEXPLODE,
A_SSMINESEARCH, A_SSMINESEARCH,
A_SSMINEEXPLODE, A_SSMINEEXPLODE,
@ -550,7 +549,6 @@ void A_ChangeHeight();
// //
// SRB2Kart // SRB2Kart
// //
void A_ItemPop();
void A_JawzExplode(); void A_JawzExplode();
void A_SSMineSearch(); void A_SSMineSearch();
void A_SSMineExplode(); void A_SSMineExplode();
@ -1084,6 +1082,7 @@ typedef enum sprite
// SRB2Kart // SRB2Kart
SPR_RNDM, // Random Item Box SPR_RNDM, // Random Item Box
SPR_SBOX, // Sphere Box (for Battle) SPR_SBOX, // Sphere Box (for Battle)
SPR_RBOX, // Ring Box
SPR_RPOP, // Random Item Box Pop SPR_RPOP, // Random Item Box Pop
SPR_ITRI, // Item Box Debris SPR_ITRI, // Item Box Debris
SPR_ITPA, // Paper item backdrop SPR_ITPA, // Paper item backdrop
@ -4302,7 +4301,20 @@ typedef enum state
S_RANDOMITEM10, S_RANDOMITEM10,
S_RANDOMITEM11, S_RANDOMITEM11,
S_RANDOMITEM12, S_RANDOMITEM12,
S_DEADRANDOMITEM,
// Ring Box
S_RINGBOX1,
S_RINGBOX2,
S_RINGBOX3,
S_RINGBOX4,
S_RINGBOX5,
S_RINGBOX6,
S_RINGBOX7,
S_RINGBOX8,
S_RINGBOX9,
S_RINGBOX10,
S_RINGBOX11,
S_RINGBOX12,
// Sphere Box (for Battle) // Sphere Box (for Battle)
S_SPHEREBOX1, S_SPHEREBOX1,
@ -4317,7 +4329,6 @@ typedef enum state
S_SPHEREBOX10, S_SPHEREBOX10,
S_SPHEREBOX11, S_SPHEREBOX11,
S_SPHEREBOX12, S_SPHEREBOX12,
S_DEADSPHEREBOX,
// Random Item Pop // Random Item Pop
S_RANDOMITEMPOP1, S_RANDOMITEMPOP1,

View file

@ -114,6 +114,7 @@ static patch_t *kp_wantedsplit;
static patch_t *kp_wantedreticle; static patch_t *kp_wantedreticle;
static patch_t *kp_itembg[4]; static patch_t *kp_itembg[4];
static patch_t *kp_ringbg[4];
static patch_t *kp_itemtimer[2]; static patch_t *kp_itemtimer[2];
static patch_t *kp_itemmulsticker[2]; static patch_t *kp_itemmulsticker[2];
static patch_t *kp_itemx; static patch_t *kp_itemx;
@ -142,6 +143,12 @@ static patch_t *kp_kitchensink[2];
static patch_t *kp_droptarget[2]; static patch_t *kp_droptarget[2];
static patch_t *kp_gardentop[2]; static patch_t *kp_gardentop[2];
static patch_t *kp_gachabom[2]; static patch_t *kp_gachabom[2];
static patch_t *kp_bar[2];
static patch_t *kp_doublebar[2];
static patch_t *kp_triplebar[2];
static patch_t *kp_slotring[2];
static patch_t *kp_seven[2];
static patch_t *kp_jackpot[2];
static patch_t *kp_check[6]; static patch_t *kp_check[6];
@ -443,6 +450,9 @@ void K_LoadKartHUDGraphics(void)
HU_UpdatePatch(&kp_itemmulsticker[0], "K_ITMUL"); HU_UpdatePatch(&kp_itemmulsticker[0], "K_ITMUL");
HU_UpdatePatch(&kp_itemx, "K_ITX"); HU_UpdatePatch(&kp_itemx, "K_ITX");
HU_UpdatePatch(&kp_ringbg[0], "K_RBBG");
HU_UpdatePatch(&kp_ringbg[1], "K_SBBG");
HU_UpdatePatch(&kp_sadface[0], "K_ITSAD"); HU_UpdatePatch(&kp_sadface[0], "K_ITSAD");
HU_UpdatePatch(&kp_sneaker[0], "K_ITSHOE"); HU_UpdatePatch(&kp_sneaker[0], "K_ITSHOE");
HU_UpdatePatch(&kp_rocketsneaker[0], "K_ITRSHE"); HU_UpdatePatch(&kp_rocketsneaker[0], "K_ITRSHE");
@ -478,6 +488,12 @@ void K_LoadKartHUDGraphics(void)
HU_UpdatePatch(&kp_droptarget[0], "K_ITDTRG"); HU_UpdatePatch(&kp_droptarget[0], "K_ITDTRG");
HU_UpdatePatch(&kp_gardentop[0], "K_ITGTOP"); HU_UpdatePatch(&kp_gardentop[0], "K_ITGTOP");
HU_UpdatePatch(&kp_gachabom[0], "K_ITGBOM"); HU_UpdatePatch(&kp_gachabom[0], "K_ITGBOM");
HU_UpdatePatch(&kp_bar[0], "K_RBBAR");
HU_UpdatePatch(&kp_doublebar[0], "K_RBBAR2");
HU_UpdatePatch(&kp_triplebar[0], "K_RBBAR3");
HU_UpdatePatch(&kp_slotring[0], "K_RBRING");
HU_UpdatePatch(&kp_seven[0], "K_RBSEV");
HU_UpdatePatch(&kp_jackpot[0], "K_RBJACK");
sprintf(buffer, "FSMFGxxx"); sprintf(buffer, "FSMFGxxx");
for (i = 0; i < 104; i++) for (i = 0; i < 104; i++)
@ -531,6 +547,12 @@ void K_LoadKartHUDGraphics(void)
HU_UpdatePatch(&kp_droptarget[1], "K_ISDTRG"); HU_UpdatePatch(&kp_droptarget[1], "K_ISDTRG");
HU_UpdatePatch(&kp_gardentop[1], "K_ISGTOP"); HU_UpdatePatch(&kp_gardentop[1], "K_ISGTOP");
HU_UpdatePatch(&kp_gachabom[1], "K_ISGBOM"); HU_UpdatePatch(&kp_gachabom[1], "K_ISGBOM");
HU_UpdatePatch(&kp_bar[1], "K_SBBAR");
HU_UpdatePatch(&kp_doublebar[1], "K_SBBAR2");
HU_UpdatePatch(&kp_triplebar[1], "K_SBBAR3");
HU_UpdatePatch(&kp_slotring[1], "K_SBRING");
HU_UpdatePatch(&kp_seven[1], "K_SBSEV");
HU_UpdatePatch(&kp_jackpot[1], "K_SBJACK");
sprintf(buffer, "FSMFSxxx"); sprintf(buffer, "FSMFSxxx");
for (i = 0; i < 104; i++) for (i = 0; i < 104; i++)
@ -875,6 +897,23 @@ static patch_t *K_GetSmallStaticCachedItemPatch(kartitems_t item)
return K_GetCachedItemPatch(item, offset); return K_GetCachedItemPatch(item, offset);
} }
static patch_t *K_GetCachedSlotMachinePatch(INT32 item, UINT8 offset)
{
patch_t **kp[KSM__MAX] = {
kp_bar,
kp_doublebar,
kp_triplebar,
kp_slotring,
kp_seven,
kp_jackpot,
};
if (item >= 0 && item < KSM__MAX)
return kp[item][offset];
else
return NULL;
}
//} //}
INT32 ITEM_X, ITEM_Y; // Item Window INT32 ITEM_X, ITEM_Y; // Item Window
@ -1217,7 +1256,7 @@ static void K_drawKartItem(void)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
const SINT8 indexOfs = i-1; const SINT8 indexOfs = i-1;
const size_t index = (stplyr->itemRoulette.index + indexOfs) % stplyr->itemRoulette.itemListLen; const size_t index = (stplyr->itemRoulette.itemListLen + (stplyr->itemRoulette.index + indexOfs)) % stplyr->itemRoulette.itemListLen;
const SINT8 result = stplyr->itemRoulette.itemList[index]; const SINT8 result = stplyr->itemRoulette.itemList[index];
const SINT8 item = K_ItemResultToType(result); const SINT8 item = K_ItemResultToType(result);
@ -1533,6 +1572,118 @@ static void K_drawKartItem(void)
} }
} }
static void K_drawKartSlotMachine(void)
{
// ITEM_X = BASEVIDWIDTH-50; // 270
// ITEM_Y = 24; // 24
// Why write V_DrawScaledPatch calls over and over when they're all the same?
// Set to 'no item' just in case.
const UINT8 offset = ((r_splitscreen > 1) ? 1 : 0);
patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw };
patch_t *localbg = offset ? kp_ringbg[1] : kp_ringbg[0];
// == SHITGARBAGE UNLIMITED 2: RISE OF MY ASS ==
// FIVE LAYERS OF BULLSHIT PER-PIXEL SHOVING BECAUSE THE PATCHES HAVE DIFFERENT OFFSETS
// IF YOU ARE HERE TO ADJUST THE RINGBOX HUD TURN OFF YOUR COMPUTER AND GO TO YOUR LOCAL PARK
INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags...
INT32 boxoffx = 0;
INT32 boxoffy = -6;
INT32 vstretch = 0;
INT32 hstretch = 3;
INT32 splitbsx, splitbsy = 0;
UINT16 localcolor[3] = { stplyr->skincolor };
SINT8 colormode[3] = { TC_RAINBOW };
fixed_t rouletteOffset = 0;
fixed_t rouletteSpace = SLOT_SPACING;
vector2_t rouletteCrop = {10, 10};
INT32 i;
if (stplyr->itemRoulette.itemListLen > 0)
{
// Init with item roulette stuff.
for (i = 0; i < 3; i++)
{
const SINT8 indexOfs = i-1;
const size_t index = (stplyr->itemRoulette.itemListLen + (stplyr->itemRoulette.index + indexOfs)) % stplyr->itemRoulette.itemListLen;
const SINT8 result = stplyr->itemRoulette.itemList[index];
localpatch[i] = K_GetCachedSlotMachinePatch(result, offset);
}
}
if (stplyr->itemRoulette.active == true)
{
rouletteOffset = K_GetSlotOffset(&stplyr->itemRoulette, rendertimefrac);
}
else
{
if (!stplyr->ringboxdelay)
return;
}
// pain and suffering defined below
if (offset)
{
boxoffx -= 4;
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{
fx = ITEM_X + 10;
fy = ITEM_Y + 10;
fflags = V_SNAPTOLEFT|V_SNAPTOTOP|V_SPLITSCREEN;
}
else // else, that means we're P2 or P4.
{
fx = ITEM2_X + 7;
fy = ITEM2_Y + 10;
fflags = V_SNAPTORIGHT|V_SNAPTOTOP|V_SPLITSCREEN;
}
rouletteSpace = SLOT_SPACING_SPLITSCREEN;
rouletteOffset = FixedMul(rouletteOffset, FixedDiv(SLOT_SPACING_SPLITSCREEN, SLOT_SPACING));
rouletteCrop.x = 16;
rouletteCrop.y = 13;
splitbsx = -6;
splitbsy = -6;
boxoffy += 2;
hstretch = 0;
}
else
{
fx = ITEM_X;
fy = ITEM_Y;
fflags = V_SNAPTOTOP|V_SNAPTOLEFT|V_SPLITSCREEN;
}
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg);
V_SetClipRect(
((fx + rouletteCrop.x + boxoffx + splitbsx) << FRACBITS), ((fy + rouletteCrop.y + boxoffy - vstretch + splitbsy) << FRACBITS),
rouletteSpace + (hstretch<<FRACBITS), rouletteSpace + (vstretch<<FRACBITS),
V_SLIDEIN|fflags
);
// item box has special layering, transparency, different sized patches, other fucked up shit
// ring box is evenly spaced and easy
rouletteOffset += rouletteSpace;
for (i = 0; i < 3; i++)
{
V_DrawFixedPatch(
((fx)<<FRACBITS), ((fy)<<FRACBITS) + rouletteOffset,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[i], (localcolor[i] ? R_GetTranslationColormap(colormode[i], localcolor[i], GTC_CACHE) : NULL)
);
rouletteOffset -= rouletteSpace;
}
V_ClearClipRect();
}
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, UINT8 mode) void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, UINT8 mode)
{ {
// TIME_X = BASEVIDWIDTH-124; // 196 // TIME_X = BASEVIDWIDTH-124; // 196
@ -4943,7 +5094,7 @@ static void K_drawDistributionDebugger(void)
return; return;
} }
K_FillItemRouletteData(stplyr, &rouletteData); K_FillItemRouletteData(stplyr, &rouletteData, false);
for (i = 0; i < rouletteData.itemListLen; i++) for (i = 0; i < rouletteData.itemListLen; i++)
{ {
@ -5200,7 +5351,16 @@ void K_drawKartHUD(void)
// Draw the item window // Draw the item window
if (LUA_HudEnabled(hud_item) && !freecam) if (LUA_HudEnabled(hud_item) && !freecam)
K_drawKartItem(); {
if (stplyr->itemRoulette.ringbox && stplyr->itemamount == 0 && stplyr->itemtype == 0)
{
K_drawKartSlotMachine();
}
else
{
K_drawKartItem();
}
}
if (demo.title) if (demo.title)
; ;

View file

@ -361,6 +361,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartvoices); CV_RegisterVar(&cv_kartvoices);
CV_RegisterVar(&cv_kartbot); CV_RegisterVar(&cv_kartbot);
CV_RegisterVar(&cv_karteliminatelast); CV_RegisterVar(&cv_karteliminatelast);
CV_RegisterVar(&cv_thunderdome);
CV_RegisterVar(&cv_kartusepwrlv); CV_RegisterVar(&cv_kartusepwrlv);
CV_RegisterVar(&cv_votetime); CV_RegisterVar(&cv_votetime);
CV_RegisterVar(&cv_botscanvote); CV_RegisterVar(&cv_botscanvote);
@ -10753,6 +10754,26 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->pflags &= ~PF_USERINGS; player->pflags &= ~PF_USERINGS;
} }
if (player->ringboxdelay)
{
player->ringboxdelay--;
if (player->ringboxdelay == 0)
{
// TODO
UINT32 behind = K_GetItemRouletteDistance(player, player->itemRoulette.playing);
UINT32 behindMulti = behind / 1000;
behindMulti = min(behindMulti, 20);
UINT32 award = 5*player->ringboxaward + 10;
if (player->ringboxaward > 2) // not a BAR
award = 3 * award / 2;
award = award * (behindMulti + 10) / 10;
K_AwardPlayerRings(player, award, true);
player->ringboxaward = 0;
}
}
if (player && player->mo && player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime) if (player && player->mo && player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime)
{ {
// First, the really specific, finicky items that function without the item being directly in your item slot. // First, the really specific, finicky items that function without the item being directly in your item slot.

View file

@ -135,6 +135,7 @@ void Obj_RandomItemVisuals(mobj_t *mobj);
boolean Obj_RandomItemSpawnIn(mobj_t *mobj); boolean Obj_RandomItemSpawnIn(mobj_t *mobj);
fixed_t Obj_RandomItemScale(fixed_t oldScale); fixed_t Obj_RandomItemScale(fixed_t oldScale);
void Obj_RandomItemSpawn(mobj_t *mobj); void Obj_RandomItemSpawn(mobj_t *mobj);
#define RINGBOX_TIME (70)
/* Gachabom Rebound */ /* Gachabom Rebound */
void Obj_GachaBomReboundThink(mobj_t *mobj); void Obj_GachaBomReboundThink(mobj_t *mobj);

View file

@ -218,6 +218,17 @@ static kartitems_t K_KartItemReelBoss[] =
KITEM_NONE KITEM_NONE
}; };
static kartslotmachine_t K_KartItemReelRingBox[] =
{
KSM_BAR,
KSM_DOUBLEBAR,
KSM_TRIPLEBAR,
KSM_RING,
KSM_SEVEN,
KSM_JACKPOT,
KSM__MAX
};
/*-------------------------------------------------- /*--------------------------------------------------
boolean K_ItemEnabled(kartitems_t item) boolean K_ItemEnabled(kartitems_t item)
@ -438,7 +449,7 @@ static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers)
Return:- Return:-
The player's finalized item distance. The player's finalized item distance.
--------------------------------------------------*/ --------------------------------------------------*/
static UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers) UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers)
{ {
UINT32 pdis = 0; UINT32 pdis = 0;
@ -1052,6 +1063,7 @@ static void K_InitRoulette(itemroulette_t *const roulette)
roulette->active = true; roulette->active = true;
roulette->eggman = false; roulette->eggman = false;
roulette->ringbox = false;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -1104,19 +1116,20 @@ static void K_InitRoulette(itemroulette_t *const roulette)
} }
/*-------------------------------------------------- /*--------------------------------------------------
static void K_PushToRouletteItemList(itemroulette_t *const roulette, kartitems_t item) static void K_PushToRouletteItemList(itemroulette_t *const roulette, INT32 item)
Pushes a new item to the end of the item Pushes a new item to the end of the item
roulette's item list. roulette's item list. Also accepts slot machine
values instead of items.
Input Arguments:- Input Arguments:-
roulette - The item roulette data to modify. roulette - The item roulette data to modify.
item - The item to push to the list. item - The item / slot machine index to push to the list.
Return:- Return:-
N/A N/A
--------------------------------------------------*/ --------------------------------------------------*/
static void K_PushToRouletteItemList(itemroulette_t *const roulette, kartitems_t item) static void K_PushToRouletteItemList(itemroulette_t *const roulette, INT32 item)
{ {
#ifdef ITEM_LIST_SIZE #ifdef ITEM_LIST_SIZE
if (roulette->itemListLen >= ITEM_LIST_SIZE) if (roulette->itemListLen >= ITEM_LIST_SIZE)
@ -1253,11 +1266,11 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette)
} }
/*-------------------------------------------------- /*--------------------------------------------------
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette) void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox)
See header file for description. See header file for description.
--------------------------------------------------*/ --------------------------------------------------*/
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette) void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox)
{ {
UINT32 spawnChance[NUMKARTRESULTS] = {0}; UINT32 spawnChance[NUMKARTRESULTS] = {0};
UINT32 totalSpawnChance = 0; UINT32 totalSpawnChance = 0;
@ -1276,6 +1289,20 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
K_CalculateRouletteSpeed(roulette); K_CalculateRouletteSpeed(roulette);
} }
if (ringbox == true)
{
// If this is being invoked by a Ring Box, it should literally never produce items.
kartslotmachine_t *presetlist = K_KartItemReelRingBox;
roulette->ringbox = true;
for (i = 0; presetlist[i] != KSM__MAX; i++)
{
K_PushToRouletteItemList(roulette, presetlist[i]);
}
return;
}
// SPECIAL CASE No. 1: // SPECIAL CASE No. 1:
// Give only the debug item if specified // Give only the debug item if specified
if (cv_kartdebugitem.value != KITEM_NONE) if (cv_kartdebugitem.value != KITEM_NONE)
@ -1412,12 +1439,12 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
See header file for description. See header file for description.
--------------------------------------------------*/ --------------------------------------------------*/
void K_StartItemRoulette(player_t *const player) void K_StartItemRoulette(player_t *const player, boolean ringbox)
{ {
itemroulette_t *const roulette = &player->itemRoulette; itemroulette_t *const roulette = &player->itemRoulette;
size_t i; size_t i;
K_FillItemRouletteData(player, roulette); K_FillItemRouletteData(player, roulette, ringbox);
if (K_PlayerUsesBotMovement(player) == true) if (K_PlayerUsesBotMovement(player) == true)
{ {
@ -1444,7 +1471,7 @@ void K_StartItemRoulette(player_t *const player)
void K_StartEggmanRoulette(player_t *const player) void K_StartEggmanRoulette(player_t *const player)
{ {
itemroulette_t *const roulette = &player->itemRoulette; itemroulette_t *const roulette = &player->itemRoulette;
K_StartItemRoulette(player); K_StartItemRoulette(player, false);
roulette->eggman = true; roulette->eggman = true;
} }
@ -1461,6 +1488,19 @@ fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta)
return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), ROULETTE_SPACING); return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), ROULETTE_SPACING);
} }
/*--------------------------------------------------
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta)
See header file for description.
--------------------------------------------------*/
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta)
{
const fixed_t curTic = (roulette->tics << FRACBITS) - renderDelta;
const fixed_t midTic = roulette->speed * (FRACUNIT >> 1);
return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), SLOT_SPACING);
}
/*-------------------------------------------------- /*--------------------------------------------------
static void K_KartGetItemResult(player_t *const player, kartitems_t getitem) static void K_KartGetItemResult(player_t *const player, kartitems_t getitem)
@ -1572,9 +1612,17 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
// And one more nudge for the remaining delay. // And one more nudge for the remaining delay.
roulette->tics = (roulette->tics + fudgedDelay) % roulette->speed; roulette->tics = (roulette->tics + fudgedDelay) % roulette->speed;
kartitems_t finalItem = roulette->itemList[ roulette->index ]; INT32 finalItem = roulette->itemList[ roulette->index ];
K_KartGetItemResult(player, finalItem); if (roulette->ringbox == true)
{
player->ringboxdelay = TICRATE;
player->ringboxaward = finalItem;
}
else
{
K_KartGetItemResult(player, finalItem);
}
player->karthud[khud_itemblink] = TICRATE; player->karthud[khud_itemblink] = TICRATE;
player->karthud[khud_itemblinkmode] = 0; player->karthud[khud_itemblinkmode] = 0;
@ -1582,7 +1630,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
if (P_IsDisplayPlayer(player) && !demo.freecam) if (P_IsDisplayPlayer(player) && !demo.freecam)
{ {
S_StartSound(NULL, sfx_itrolf); if (roulette->ringbox)
S_StartSound(NULL, sfx_s245);
else
S_StartSound(NULL, sfx_itrolf);
} }
} }
@ -1603,7 +1654,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
if (P_IsDisplayPlayer(player) && !demo.freecam) if (P_IsDisplayPlayer(player) && !demo.freecam)
{ {
S_StartSound(NULL, sfx_itrol1 + roulette->sound); if (roulette->ringbox)
S_StartSound(NULL, sfx_s240);
else
S_StartSound(NULL, sfx_itrol1 + roulette->sound);
} }
} }
else else

View file

@ -23,6 +23,9 @@ extern "C" {
#define ROULETTE_SPACING (36 << FRACBITS) #define ROULETTE_SPACING (36 << FRACBITS)
#define ROULETTE_SPACING_SPLITSCREEN (16 << FRACBITS) #define ROULETTE_SPACING_SPLITSCREEN (16 << FRACBITS)
#define SLOT_SPACING (40 << FRACBITS)
#define SLOT_SPACING_SPLITSCREEN (22 << FRACBITS)
/*-------------------------------------------------- /*--------------------------------------------------
boolean K_ItemEnabled(kartitems_t item); boolean K_ItemEnabled(kartitems_t item);
@ -98,7 +101,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette,
/*-------------------------------------------------- /*--------------------------------------------------
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette); void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox);
Fills out the item roulette struct when it is Fills out the item roulette struct when it is
initially created. This function needs to be initially created. This function needs to be
@ -109,16 +112,17 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette,
player - The player this roulette data is for. player - The player this roulette data is for.
Can be NULL for generic use. Can be NULL for generic use.
roulette - The roulette data struct to fill out. roulette - The roulette data struct to fill out.
ringbox - Is this roulette fill triggered by a just-respawned Ring Box?
Return:- Return:-
N/A N/A
--------------------------------------------------*/ --------------------------------------------------*/
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette); void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox);
/*-------------------------------------------------- /*--------------------------------------------------
void K_StartItemRoulette(player_t *const player); void K_StartItemRoulette(player_t *const player, boolean ringbox);
Starts the item roulette sequence for a player. Starts the item roulette sequence for a player.
This stage can only be used by gameplay, thus This stage can only be used by gameplay, thus
@ -126,12 +130,13 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
Input Arguments:- Input Arguments:-
player - The player to start the item roulette for. player - The player to start the item roulette for.
ringbox - Is this roulette being started from a just-respawned Ring Box?
Return:- Return:-
N/A N/A
--------------------------------------------------*/ --------------------------------------------------*/
void K_StartItemRoulette(player_t *const player); void K_StartItemRoulette(player_t *const player, boolean ringbox);
/*-------------------------------------------------- /*--------------------------------------------------
@ -169,6 +174,23 @@ void K_StartEggmanRoulette(player_t *const player);
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta); fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta);
/*--------------------------------------------------
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta);
Gets the Y offset, for use in the slot HUD.
A separate function since it is used both by the
HUD itself, as well as when confirming an item.
Input Arguments:-
roulette - The roulette we are drawing for.
renderDelta - Fractional tic delta, when used for HUD.
Return:-
The Y offset when drawing the item.
--------------------------------------------------*/
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta);
/*-------------------------------------------------- /*--------------------------------------------------
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd); void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
@ -186,6 +208,8 @@ fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta)
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd); void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View file

@ -251,6 +251,10 @@ static int player_get(lua_State *L)
lua_pushboolean(L, plr->flipDI); lua_pushboolean(L, plr->flipDI);
else if (fastcmp(field,"markedfordeath")) else if (fastcmp(field,"markedfordeath"))
lua_pushboolean(L, plr->markedfordeath); lua_pushboolean(L, plr->markedfordeath);
else if (fastcmp(field,"ringboxdelay"))
lua_pushinteger(L, plr->ringboxdelay);
else if (fastcmp(field,"ringboxaward"))
lua_pushinteger(L, plr->ringboxaward);
else if (fastcmp(field,"drift")) else if (fastcmp(field,"drift"))
lua_pushinteger(L, plr->drift); lua_pushinteger(L, plr->drift);
else if (fastcmp(field,"driftcharge")) else if (fastcmp(field,"driftcharge"))
@ -651,6 +655,10 @@ static int player_set(lua_State *L)
plr->flipDI = luaL_checkboolean(L, 3); plr->flipDI = luaL_checkboolean(L, 3);
else if (fastcmp(field,"markedfordeath")) else if (fastcmp(field,"markedfordeath"))
plr->markedfordeath = luaL_checkboolean(L, 3); plr->markedfordeath = luaL_checkboolean(L, 3);
else if (fastcmp(field,"ringboxdelay"))
plr->ringboxdelay = luaL_checkinteger(L, 3);
else if (fastcmp(field,"ringboxaward"))
plr->ringboxaward = luaL_checkinteger(L, 3);
else if (fastcmp(field,"drift")) else if (fastcmp(field,"drift"))
plr->drift = luaL_checkinteger(L, 3); plr->drift = luaL_checkinteger(L, 3);
else if (fastcmp(field,"driftcharge")) else if (fastcmp(field,"driftcharge"))

View file

@ -102,6 +102,29 @@ void Obj_RandomItemVisuals(mobj_t *mobj)
ItemBoxBob(mobj); ItemBoxBob(mobj);
ItemBoxScaling(mobj); ItemBoxScaling(mobj);
item_vfxtimer(mobj)++; item_vfxtimer(mobj)++;
if (mobj->type != MT_RANDOMITEM)
return;
// Respawn flow, documented by a dumb asshole:
// P_TouchSpecialThing -> P_ItemPop sets fuse, NOCLIPTHING and DONTDRAW.
// P_FuseThink does visual flicker, and when fuse is 0, unsets NOCLIPTHING/DONTDRAW/etc...
// ...unless it's a map-start box from Battle, in which case it does nothing and waits for
// P_RespawnBattleBoxes to trigger the effect instead, since Battle boxes don't respawn until
// the player's cleared out a good portion of the map.
//
// Then extraval1 starts ticking up and triggers the transformation from Ringbox to Random Item.
if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING) && !cv_thunderdome.value)
{
mobj->extravalue1++;
if (mobj->extravalue1 == RINGBOX_TIME)
{
// Sync the position in RINGBOX and RANDOMITEM animations.
statenum_t animDelta = mobj->state - states - S_RINGBOX1;
P_SetMobjState(mobj, S_RANDOMITEM1 + (animDelta%12));
}
}
} }
boolean Obj_RandomItemSpawnIn(mobj_t *mobj) boolean Obj_RandomItemSpawnIn(mobj_t *mobj)
@ -116,6 +139,7 @@ boolean Obj_RandomItemSpawnIn(mobj_t *mobj)
} }
else else
{ {
// Spawn a battle monitor in your place and Fucking Die
mobj_t *paperspawner = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PAPERITEMSPOT); mobj_t *paperspawner = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PAPERITEMSPOT);
paperspawner->spawnpoint = mobj->spawnpoint; paperspawner->spawnpoint = mobj->spawnpoint;
mobj->spawnpoint->mobj = paperspawner; mobj->spawnpoint->mobj = paperspawner;
@ -148,6 +172,14 @@ void Obj_RandomItemSpawn(mobj_t *mobj)
{ {
item_vfxtimer(mobj) = P_RandomRange(PR_DECORATION, 0, SCALE_TIME - 1); item_vfxtimer(mobj) = P_RandomRange(PR_DECORATION, 0, SCALE_TIME - 1);
// Respawns are handled by P_RespawnBattleBoxes,
// but we do need to start MT_RANDOMITEMs in the right state...
if (mobj->type == MT_RANDOMITEM && (gametyperules & GTR_BUMPERS))
{
mobj->extravalue1 = RINGBOX_TIME;
P_SetMobjState(mobj, S_RANDOMITEM1);
}
mobj->destscale = Obj_RandomItemScale(mobj->destscale); mobj->destscale = Obj_RandomItemScale(mobj->destscale);
P_SetScale(mobj, mobj->destscale); P_SetScale(mobj, mobj->destscale);
} }

View file

@ -312,7 +312,6 @@ void A_ChangeHeight(mobj_t *actor);
// //
// SRB2Kart // SRB2Kart
// //
void A_ItemPop(mobj_t *actor);
void A_JawzExplode(mobj_t *actor); void A_JawzExplode(mobj_t *actor);
void A_SSMineSearch(mobj_t *actor); void A_SSMineSearch(mobj_t *actor);
void A_SSMineExplode(mobj_t *actor); void A_SSMineExplode(mobj_t *actor);
@ -12984,54 +12983,6 @@ void A_ChangeHeight(mobj_t *actor)
// SRB2Kart // SRB2Kart
// //
void A_ItemPop(mobj_t *actor)
{
INT32 locvar1 = var1;
if (LUA_CallAction(A_ITEMPOP, actor))
return;
if (!(actor->target && actor->target->player))
{
if (cht_debug && !(actor->target && actor->target->player))
CONS_Printf("ERROR: Powerup has no target!\n");
return;
}
// de-solidify
P_UnsetThingPosition(actor);
actor->flags &= ~MF_SOLID;
actor->flags |= MF_NOCLIP;
P_SetThingPosition(actor);
// RF_DONTDRAW will flicker as the object's fuse gets
// closer to running out (see P_FuseThink)
actor->renderflags |= RF_DONTDRAW|RF_TRANS50;
actor->color = SKINCOLOR_GREY;
actor->colorized = true;
Obj_SpawnItemDebrisEffects(actor, actor->target);
if (locvar1 == 1)
{
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
}
else if (locvar1 == 0)
{
K_StartItemRoulette(actor->target->player);
}
// Here at mapload in battle?
if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP))
{
numgotboxes++;
// do not flicker back in just yet, handled by
// P_RespawnBattleBoxes eventually
P_SetMobjState(actor, S_INVISIBLE);
}
}
void A_JawzExplode(mobj_t *actor) void A_JawzExplode(mobj_t *actor)
{ {
INT32 shrapnel = 2; INT32 shrapnel = 2;

View file

@ -140,6 +140,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
// Item slot already taken up // Item slot already taken up
if (player->itemRoulette.active == true if (player->itemRoulette.active == true
|| player->ringboxdelay > 0
|| (weapon != 3 && player->itemamount) || (weapon != 3 && player->itemamount)
|| (player->pflags & PF_ITEMOUT)) || (player->pflags & PF_ITEMOUT))
return false; return false;
@ -186,6 +187,61 @@ boolean P_EmblemWasCollected(INT32 emblemID)
return gamedata->collected[emblemID]; return gamedata->collected[emblemID];
} }
static void P_ItemPop(mobj_t *actor)
{
/*
INT32 locvar1 = var1;
if (LUA_CallAction(A_ITEMPOP, actor))
return;
if (!(actor->target && actor->target->player))
{
if (cht_debug && !(actor->target && actor->target->player))
CONS_Printf("ERROR: Powerup has no target!\n");
return;
}
*/
P_SetMobjState(actor, S_RINGBOX1);
actor->extravalue1 = 0;
// de-solidify
actor->flags |= MF_NOCLIPTHING;
// RF_DONTDRAW will flicker as the object's fuse gets
// closer to running out (see P_FuseThink)
actor->renderflags |= RF_DONTDRAW|RF_TRANS50;
actor->color = SKINCOLOR_GREY;
actor->colorized = true;
Obj_SpawnItemDebrisEffects(actor, actor->target);
/*
if (locvar1 == 1)
{
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
}
else if (locvar1 == 0)
{
if (actor->extravalue1 >= TICRATE)
K_StartItemRoulette(actor->target->player, false);
else
K_StartItemRoulette(actor->target->player, true);
}
*/
// Here at mapload in battle?
if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP))
{
numgotboxes++;
// do not flicker back in just yet, handled by
// P_RespawnBattleBoxes eventually
P_SetMobjState(actor, S_INVISIBLE);
}
}
/** Takes action based on a ::MF_SPECIAL thing touched by a player. /** Takes action based on a ::MF_SPECIAL thing touched by a player.
* Actually, this just checks a few things (heights, toucher->player, no * Actually, this just checks a few things (heights, toucher->player, no
* objectplace, no dead or disappearing things) * objectplace, no dead or disappearing things)
@ -300,7 +356,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->momx = special->momy = special->momz = 0; special->momx = special->momy = special->momz = 0;
P_SetTarget(&special->target, toucher); P_SetTarget(&special->target, toucher);
P_KillMobj(special, toucher, toucher, DMG_NORMAL); // P_KillMobj(special, toucher, toucher, DMG_NORMAL);
if (special->extravalue1 >= RINGBOX_TIME)
K_StartItemRoulette(player, false);
else
K_StartItemRoulette(player, true);
P_ItemPop(special);
special->fuse = TICRATE;
return; return;
case MT_SPHEREBOX: case MT_SPHEREBOX:
if (!P_CanPickupItem(player, 0)) if (!P_CanPickupItem(player, 0))
@ -308,7 +370,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->momx = special->momy = special->momz = 0; special->momx = special->momy = special->momz = 0;
P_SetTarget(&special->target, toucher); P_SetTarget(&special->target, toucher);
P_KillMobj(special, toucher, toucher, DMG_NORMAL); // P_KillMobj(special, toucher, toucher, DMG_NORMAL);
P_ItemPop(special);
P_GivePlayerSpheres(player, special->extravalue1);
return; return;
case MT_ITEMCAPSULE: case MT_ITEMCAPSULE:
if (special->scale < special->extravalue1) // don't break it while it's respawning if (special->scale < special->extravalue1) // don't break it while it's respawning
@ -434,7 +498,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->fuse || !P_CanPickupItem(player, 1)) if (special->fuse || !P_CanPickupItem(player, 1))
return; return;
K_StartItemRoulette(player); K_StartItemRoulette(player, false);
// Karma fireworks // Karma fireworks
/*for (i = 0; i < 5; i++) /*for (i = 0; i < 5; i++)

View file

@ -9718,7 +9718,7 @@ static boolean P_FuseThink(mobj_t *mobj)
case MT_RANDOMITEM: case MT_RANDOMITEM:
if (mobj->flags2 & MF2_DONTRESPAWN) if (mobj->flags2 & MF2_DONTRESPAWN)
{ {
; P_RemoveMobj(mobj);
} }
else if (!(gametyperules & GTR_CIRCUIT) && (mobj->state == &states[S_INVISIBLE])) else if (!(gametyperules & GTR_CIRCUIT) && (mobj->state == &states[S_INVISIBLE]))
{ {
@ -9726,22 +9726,10 @@ static boolean P_FuseThink(mobj_t *mobj)
} }
else else
{ {
mobj_t *newmobj; mobj->flags &= ~MF_NOCLIPTHING;
mobj->renderflags &= ~(RF_DONTDRAW|RF_TRANSMASK);
// Respawn from mapthing if you have one!
if (mobj->spawnpoint)
{
P_SpawnMapThing(mobj->spawnpoint);
newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
}
else
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
// Transfer flags2 (strongbox, objectflip, bossnotrap)
newmobj->flags2 = mobj->flags2;
} }
P_RemoveMobj(mobj); // make sure they disappear
return false; return false;
case MT_ITEMCAPSULE: case MT_ITEMCAPSULE:
if (mobj->spawnpoint) if (mobj->spawnpoint)
@ -11592,11 +11580,11 @@ void P_RespawnBattleBoxes(void)
if (box->type != MT_RANDOMITEM if (box->type != MT_RANDOMITEM
|| (box->flags2 & MF2_DONTRESPAWN) || (box->flags2 & MF2_DONTRESPAWN)
|| box->health > 0 || !(box->flags & MF_NOCLIPTHING)
|| box->fuse) || box->fuse)
continue; // only popped items continue; // only popped items
box->fuse = TICRATE; // flicker back in (A_ItemPop preps this effect) box->fuse = TICRATE; // flicker back in
P_SetMobjState(box, box->info->raisestate); P_SetMobjState(box, box->info->raisestate);
if (numgotboxes > 0) if (numgotboxes > 0)

View file

@ -527,6 +527,8 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT8(save->p, players[i].markedfordeath); WRITEUINT8(save->p, players[i].markedfordeath);
WRITEUINT8(save->p, players[i].ringboxdelay);
WRITEUINT8(save->p, players[i].ringboxaward);
WRITEFIXED(save->p, players[i].outrun); WRITEFIXED(save->p, players[i].outrun);
// respawnvars_t // respawnvars_t
@ -600,6 +602,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT32(save->p, players[i].itemRoulette.tics); WRITEUINT32(save->p, players[i].itemRoulette.tics);
WRITEUINT32(save->p, players[i].itemRoulette.elapsed); WRITEUINT32(save->p, players[i].itemRoulette.elapsed);
WRITEUINT8(save->p, players[i].itemRoulette.eggman); WRITEUINT8(save->p, players[i].itemRoulette.eggman);
WRITEUINT8(save->p, players[i].itemRoulette.ringbox);
// sonicloopsvars_t // sonicloopsvars_t
WRITEFIXED(save->p, players[i].loop.radius); WRITEFIXED(save->p, players[i].loop.radius);
@ -931,6 +934,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].markedfordeath = READUINT8(save->p); players[i].markedfordeath = READUINT8(save->p);
players[i].ringboxdelay = READUINT8(save->p);
players[i].ringboxaward = READUINT8(save->p);
players[i].outrun = READFIXED(save->p); players[i].outrun = READFIXED(save->p);
// respawnvars_t // respawnvars_t
@ -1015,6 +1020,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].itemRoulette.tics = (tic_t)READUINT32(save->p); players[i].itemRoulette.tics = (tic_t)READUINT32(save->p);
players[i].itemRoulette.elapsed = (tic_t)READUINT32(save->p); players[i].itemRoulette.elapsed = (tic_t)READUINT32(save->p);
players[i].itemRoulette.eggman = (boolean)READUINT8(save->p); players[i].itemRoulette.eggman = (boolean)READUINT8(save->p);
players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p);
// sonicloopsvars_t // sonicloopsvars_t
players[i].loop.radius = READFIXED(save->p); players[i].loop.radius = READFIXED(save->p);