Add blue spheres

Doesn't have animations, and doesn't have stat-specific buffs. But it's already a massive improvement
This commit is contained in:
Sally Coolatta 2020-10-22 02:52:33 -04:00
parent 08dc784c17
commit 7ce53ac104
13 changed files with 111 additions and 69 deletions

View file

@ -545,6 +545,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
// Score is resynched in the rspfirm resync packet
rsp->rings = SHORT(players[i].rings);
rsp->spheres = SHORT(players[i].spheres);
rsp->lives = players[i].lives;
rsp->lostlife = players[i].lostlife;
rsp->continues = players[i].continues;
@ -689,6 +690,7 @@ static void resynch_read_player(resynch_pak *rsp)
// Score is resynched in the rspfirm resync packet
players[i].rings = SHORT(rsp->rings);
players[i].spheres = SHORT(rsp->spheres);
players[i].lives = rsp->lives;
players[i].lostlife = rsp->lostlife;
players[i].continues = rsp->continues;

View file

@ -214,6 +214,7 @@ typedef struct
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
boolean lostlife;
SINT8 continues;

View file

@ -497,6 +497,7 @@ typedef struct player_s
// player's ring count
INT16 rings;
INT16 spheres;
// Power ups. invinc and invis are tic counters.
UINT16 powers[NUMPOWERS];

View file

@ -461,30 +461,30 @@ enum GameTypeRules
{
// Race rules
GTR_CIRCUIT = 1, // Enables the finish line, laps, and the waypoint system.
GTR_RINGS = 1<<1, // Rings will be spawned in this mode. (Don't get too cheeky, ring sting is still enabled :])
GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype.
// Battle gametype rules
GTR_BUMPERS = 1<<3, // Enables the bumper health system
GTR_WANTED = 1<<4, // Enables the wanted anti-camping system
GTR_KARMA = 1<<5, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<6, // Show item box arrows above players
GTR_CAPSULES = 1<<7, // Enables the wanted anti-camping system
GTR_BATTLESTARTS = 1<<8, // Use Battle Mode start positions.
GTR_SPHERES = 1<<3, // Replaces rings with blue spheres
GTR_BUMPERS = 1<<4, // Enables the bumper health system
GTR_WANTED = 1<<5, // Enables the wanted anti-camping system
GTR_KARMA = 1<<6, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<7, // Show item box arrows above players
GTR_CAPSULES = 1<<8, // Enables the wanted anti-camping system
GTR_BATTLESTARTS = 1<<9, // Use Battle Mode start positions.
GTR_POINTLIMIT = 1<<9, // Reaching point limit ends the round
GTR_TIMELIMIT = 1<<10, // Reaching time limit ends the round
GTR_OVERTIME = 1<<11, // Allow overtime behavior
GTR_POINTLIMIT = 1<<10, // Reaching point limit ends the round
GTR_TIMELIMIT = 1<<11, // Reaching time limit ends the round
GTR_OVERTIME = 1<<12, // Allow overtime behavior
// Custom gametype rules
GTR_TEAMS = 1<<12, // Teams are forced on
GTR_NOTEAMS = 1<<13, // Teams are forced off
GTR_TEAMSTARTS = 1<<14, // Use team-based start positions
GTR_TEAMS = 1<<13, // Teams are forced on
GTR_NOTEAMS = 1<<14, // Teams are forced off
GTR_TEAMSTARTS = 1<<15, // Use team-based start positions
// Grand Prix rules
GTR_CAMPAIGN = 1<<15, // Handles cup-based progression
GTR_LIVES = 1<<16, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<17, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
GTR_CAMPAIGN = 1<<16, // Handles cup-based progression
GTR_LIVES = 1<<17, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<18, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
// free: to and including 1<<31
};

View file

@ -2056,6 +2056,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
UINT8 botdifficulty;
INT16 rings;
INT16 spheres;
angle_t playerangleturn;
UINT8 botdiffincrease;
@ -2140,7 +2141,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
itemamount = 0;
growshrinktimer = 0;
bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0);
rings = ((gametyperules & GTR_RINGS) ? 5 : 0);
rings = ((gametyperules & GTR_SPHERES) ? 0 : 5);
spheres = 0;
comebackpoints = 0;
wanted = 0;
}
@ -2168,6 +2170,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
bumper = players[player].kartstuff[k_bumper];
rings = players[player].rings;
spheres = players[player].spheres;
comebackpoints = players[player].kartstuff[k_comebackpoints];
wanted = players[player].kartstuff[k_wanted];
}
@ -2216,6 +2219,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->bot = bot;
p->botvars.difficulty = botdifficulty;
p->rings = rings;
p->spheres = spheres;
p->botvars.diffincrease = botdiffincrease;
p->botvars.rival = botrival;
p->xtralife = xtralife;
@ -2788,9 +2792,9 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] =
UINT32 gametypedefaultrules[NUMGAMETYPES] =
{
// Race
GTR_CIRCUIT|GTR_RINGS|GTR_BOTS,
GTR_CIRCUIT|GTR_BOTS,
// Battle
GTR_BUMPERS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
GTR_SPHERES|GTR_BUMPERS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
};
//

View file

@ -135,7 +135,7 @@ char sprnames[NUMSPRITES + 1][5] =
"TOKE", // Special Stage Token
"RFLG", // Red CTF Flag
"BFLG", // Blue CTF Flag
//"SPHR", // Sphere
"BSPH", // Sphere
"NCHP", // NiGHTS chip
"NSTR", // NiGHTS star
"EMBM", // Emblem
@ -1800,19 +1800,19 @@ state_t states[NUMSTATES] =
{SPR_RING, 22, 1, {NULL}, 0, 0, S_FASTRING1}, // S_FASTRING12
// Blue Sphere for special stages
{SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE
{SPR_SPHR, FF_FULLBRIGHT
{SPR_BSPH, FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE
{SPR_BSPH, FF_FULLBRIGHT
#ifdef MANIASPHERES
|FF_ANIMATE|FF_RANDOMANIM
#endif
, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS
{SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK
{SPR_BSPH, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK
// Bomb Sphere
{SPR_SPHR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2}, // S_BOMBSPHERE1
{SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3}, // S_BOMBSPHERE2
{SPR_SPHR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4}, // S_BOMBSPHERE3
{SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1}, // S_BOMBSPHERE4
{SPR_BSPH, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2}, // S_BOMBSPHERE1
{SPR_BSPH, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3}, // S_BOMBSPHERE2
{SPR_BSPH, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4}, // S_BOMBSPHERE3
{SPR_BSPH, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1}, // S_BOMBSPHERE4
// NiGHTS Chip
{SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIP
@ -7923,29 +7923,29 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
},
{ // MT_BLUESPHERE
1706, // doomednum
-1, // doomednum
S_BLUESPHERE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
MT_FLINGBLUESPHERE, // reactiontime
MT_FLINGBLUESPHERE, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_BLUESPHERESPARK, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_s3k65, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
48*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
S_BLUESPHEREBONUS // raisestate
},
@ -7962,7 +7962,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_BLUESPHERESPARK, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_s3k65, // deathsound
38*FRACUNIT, // speed

View file

@ -406,7 +406,7 @@ typedef enum sprite
SPR_TOKE, // Special Stage Token
SPR_RFLG, // Red CTF Flag
SPR_BFLG, // Blue CTF Flag
//SPR_SPHR, // Sphere
SPR_BSPH, // Sphere
SPR_NCHP, // NiGHTS chip
SPR_NSTR, // NiGHTS star
SPR_EMBM, // Emblem

View file

@ -897,7 +897,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
// SPECIAL CASE No. 4:
// Being in ring debt occasionally forces Super Ring on you if you mashed
if ((gametyperules & GTR_RINGS) && mashed && player->rings < 0 && cv_superring.value)
if (!(gametyperules & GTR_SPHERES) && mashed && player->rings < 0 && cv_superring.value)
{
INT32 debtamount = min(20, abs(player->rings));
if (P_RandomChance((debtamount*FRACUNIT)/20))
@ -2221,6 +2221,12 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
finalspeed = K_GetKartSpeedFromStat(kartspeed);
if (player->spheres > 0)
{
fixed_t sphereAdd = (FRACUNIT/80); // 50% at max
finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres));
}
if (K_PlayerUsesBotMovement(player))
{
// Give top speed a buff for bots, since it's a fairly weak stat without drifting
@ -2261,6 +2267,11 @@ fixed_t K_GetKartAccel(player_t *player)
//k_accel += 3 * (9 - kartspeed); // 36 - 60
k_accel += 4 * (9 - kartspeed); // 32 - 64
if (player->spheres > 0)
{
fixed_t sphereAdd = (FRACUNIT/10); // 500% at max
k_accel = FixedMul(k_accel, FRACUNIT + (sphereAdd * player->spheres));
}
if (K_PlayerUsesBotMovement(player))
{
@ -5614,6 +5625,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
else if (player->rings < -20)
player->rings = -20;
if ((leveltime % TICRATE) == 0)
player->spheres--;
if (player->spheres > 40)
player->spheres = 40;
else if (player->spheres < 0)
player->spheres = 0;
if (player->kartstuff[k_ringdelay])
player->kartstuff[k_ringdelay]--;

View file

@ -209,6 +209,8 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->drawangle);
else if (fastcmp(field,"rings"))
lua_pushinteger(L, plr->rings);
else if (fastcmp(field,"spheres"))
lua_pushinteger(L, plr->spheres);
else if (fastcmp(field,"powers"))
LUA_PushUserdata(L, plr->powers, META_POWERS);
else if (fastcmp(field,"kartstuff"))
@ -476,6 +478,8 @@ static int player_set(lua_State *L)
plr->drawangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"rings"))
plr->rings = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spheres"))
plr->spheres = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"powers"))
return NOSET;
else if (fastcmp(field,"pflags"))

View file

@ -2371,7 +2371,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, puncher, puncher, 1, DMG_NORMAL);
else if (thing->type == MT_RING || thing->type == MT_COIN || thing->type == MT_RANDOMITEM)
else if (thing->type == MT_RING || thing->type == MT_RANDOMITEM)
{
thing->momz = FixedMul(3*FRACUNIT, thing->scale);
P_TouchSpecialThing(thing, puncher, false);

View file

@ -553,6 +553,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_BLUESPHERE:
if (!(P_CanPickupItem(player, 0)))
return;
// Reached the cap, don't waste 'em!
if (player->spheres >= 40)
return;
special->momx = special->momy = special->momz = 0;
player->spheres++;
break;
// Secret emblem thingy
case MT_EMBLEM:
{
@ -2000,7 +2012,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
// Rings shouldn't be in Battle!
if (!(gametyperules & GTR_RINGS))
if (gametyperules & GTR_SPHERES)
return;
// Better safe than sorry.

View file

@ -2111,18 +2111,8 @@ boolean P_ZMovement(mobj_t *mo)
break;
case MT_RING: // Ignore still rings
case MT_COIN:
case MT_BLUESPHERE:
case MT_BOMBSPHERE:
case MT_NIGHTSCHIP:
case MT_NIGHTSSTAR:
case MT_REDTEAMRING:
case MT_BLUETEAMRING:
case MT_FLINGRING:
case MT_FLINGCOIN:
case MT_FLINGBLUESPHERE:
case MT_FLINGNIGHTSCHIP:
case MT_FLINGEMERALD:
// Remove flinged stuff from death pits.
if (P_CheckDeathPitCollide(mo))
{
@ -8916,6 +8906,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
break;
case MT_RING:
case MT_FLOATINGITEM:
case MT_BLUESPHERE:
thing->shadowscale = FRACUNIT/2;
break;
case MT_DRIFTCLIP:
@ -9205,8 +9196,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->color = skincolor_blueteam;
break;
case MT_RING:
case MT_COIN:
case MT_NIGHTSSTAR:
if (nummaprings >= 0)
nummaprings++;
break;
@ -9564,10 +9553,7 @@ void P_RemoveMobj(mobj_t *mobj)
// Rings only, please!
if (mobj->spawnpoint &&
(mobj->type == MT_RING
|| mobj->type == MT_COIN
|| mobj->type == MT_NIGHTSSTAR
|| mobj->type == MT_REDTEAMRING
|| mobj->type == MT_BLUETEAMRING)
|| mobj->type == MT_BLUESPHERE)
&& !(mobj->flags2 & MF2_DONTRESPAWN))
{
itemrespawnque[iquehead] = mobj->spawnpoint;
@ -9979,22 +9965,29 @@ void P_RespawnSpecials(void)
pcount++;
}
if (pcount == 1) // No respawn when alone
return;
else if (pcount > 1)
if (gametyperules & GTR_SPHERES)
{
time = (120 - ((pcount-2) * 10))*TICRATE;
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
if (time < 10*TICRATE)
time = ((MAXPLAYERS+1) - pcount) * (2*TICRATE);
}
else
{
if (pcount == 1) // No respawn when alone
return;
else if (pcount > 1)
{
// Ensure it doesn't go into absurdly low values
time = 10*TICRATE;
time = (120 - ((pcount-2) * 10))*TICRATE;
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
if (time < 10*TICRATE)
{
// Ensure it doesn't go into absurdly low values
time = 10*TICRATE;
}
}
}
@ -10410,6 +10403,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
case MT_SPIKEBALL:
case MT_EMBLEM:
case MT_RING:
case MT_BLUESPHERE:
offset += mthing->options & MTF_AMBUSH ? 24*mapobjectscale : 0;
break;
@ -10516,8 +10510,11 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
{
// Don't need this for Kart YET!
(void)mthing;
if ((gametyperules & GTR_SPHERES) && (i == MT_RING))
return MT_BLUESPHERE;
return i;
}

View file

@ -109,6 +109,7 @@ static void P_NetArchivePlayers(void)
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
WRITEINT16(save_p, players[i].rings);
WRITEINT16(save_p, players[i].spheres);
for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]);
@ -302,6 +303,7 @@ static void P_NetUnArchivePlayers(void)
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
players[i].rings = READINT16(save_p);
players[i].spheres = READINT16(save_p);
for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p);