Paper item spawners

Code is a little horrendous in a few places but I will hopefully fix later :V
This commit is contained in:
Sally Coolatta 2020-10-26 22:20:02 -04:00
parent 5f0658e6ca
commit 62139f144a
11 changed files with 298 additions and 35 deletions

View file

@ -10430,6 +10430,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_WATERTRAIL",
"MT_WATERTRAILUNDERLAY",
"MT_PAPERITEMSPOT",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif

View file

@ -459,27 +459,28 @@ enum GameTypeRules
GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype.
// Battle gametype rules
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_BUMPERS = 1<<3, // Enables the bumper health system
GTR_SPHERES = 1<<4, // Replaces rings with blue spheres
GTR_PAPERITEMS = 1<<5, // Replaces item boxes with paper item spawners
GTR_WANTED = 1<<6, // Enables the wanted anti-camping system
GTR_KARMA = 1<<7, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<8, // Show item box arrows above players
GTR_CAPSULES = 1<<9, // Enables the wanted anti-camping system
GTR_BATTLESTARTS = 1<<10, // Use Battle Mode start positions.
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
GTR_POINTLIMIT = 1<<11, // Reaching point limit ends the round
GTR_TIMELIMIT = 1<<12, // Reaching time limit ends the round
GTR_OVERTIME = 1<<13, // Allow overtime behavior
// Custom gametype rules
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
GTR_TEAMS = 1<<14, // Teams are forced on
GTR_NOTEAMS = 1<<15, // Teams are forced off
GTR_TEAMSTARTS = 1<<16, // Use team-based start positions
// Grand Prix rules
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.
GTR_CAMPAIGN = 1<<17, // Handles cup-based progression
GTR_LIVES = 1<<18, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<19, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
// free: to and including 1<<31
};

View file

@ -2793,7 +2793,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
// Race
GTR_CIRCUIT|GTR_BOTS,
// Battle
GTR_SPHERES|GTR_BUMPERS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
};
//

View file

@ -28680,6 +28680,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_PAPERITEMSPOT
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
48*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES

View file

@ -6312,6 +6312,8 @@ typedef enum mobj_type
MT_WATERTRAIL,
MT_WATERTRAILUNDERLAY,
MT_PAPERITEMSPOT,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

View file

@ -277,6 +277,127 @@ void K_CheckBumpers(void)
P_DoPlayerExit(&players[i]);
}
void K_RunPaperItemSpawners(void)
{
const boolean overtime = (battleovertime.enabled >= 10*TICRATE);
tic_t interval = 8*TICRATE;
if (leveltime <= starttime)
{
return;
}
if ((battleovertime.enabled > 0) && (battleovertime.radius < 256*mapobjectscale))
{
return;
}
if (overtime == true)
{
interval /= 2;
}
if (((leveltime - starttime - (interval / 2)) % interval) != 0)
{
return;
}
if (overtime == true)
{
SINT8 flip = 1;
K_CreatePaperItem(
battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
0, 0
);
}
else
{
UINT8 pcount = 0;
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator
|| players[i].exiting > 0
|| players[i].eliminated)
{
continue;
}
if ((gametyperules & GTR_BUMPERS) && players[i].bumpers <= 0)
{
continue;
}
pcount++;
}
if (pcount > 0)
{
#define MAXITEM 64
UINT16 item = 0;
mobj_t *spotList[MAXITEM];
boolean spotUsed[MAXITEM];
thinker_t *th;
mobj_t *mo;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (item >= MAXITEM)
break;
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_PAPERITEMSPOT)
{
spotList[item] = mo;
item++;
}
}
if (item <= 0)
{
return;
}
for (i = 0; i < min(item, pcount); i++)
{
UINT8 r = P_RandomRange(0, item-1);
UINT8 recursion = 0;
mobj_t *drop = NULL;
SINT8 flip = 1;
while (spotUsed[r] == true)
{
r = P_RandomRange(0, item-1);
if ((recursion++) > 32)
{
break;
}
}
flip = P_MobjFlip(spotList[r]);
drop = K_CreatePaperItem(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
0, 0
);
K_FlipFromObject(drop, spotList[r]);
spotUsed[r] = true;
}
}
}
}
static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
{
UINT8 i, j;
@ -359,8 +480,6 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
}
}
#undef MAXPLANESPERSECTOR
void K_RunBattleOvertime(void)
{
if (battleovertime.enabled < 10*TICRATE)

View file

@ -20,6 +20,7 @@ boolean K_IsPlayerWanted(player_t *player);
void K_CalculateBattleWanted(void);
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
void K_CheckBumpers(void);
void K_RunPaperItemSpawners(void);
void K_RunBattleOvertime(void);
void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj);
void K_SpawnBattleCapsules(void);

View file

@ -4342,6 +4342,118 @@ void K_DropHnextList(player_t *player, boolean keepshields)
}
}
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount)
{
mobj_t *drop = P_SpawnMobj(x, y, z, MT_FLOATINGITEM);
P_SetScale(drop, drop->scale>>4);
drop->destscale = (3*drop->destscale)/2;
drop->angle = angle;
P_Thrust(drop,
FixedAngle(P_RandomFixed() * 180) + angle,
16*mapobjectscale);
drop->momz = flip * 3 * mapobjectscale;
if (drop->eflags & MFE_UNDERWATER)
drop->momz = (117 * drop->momz) / 200;
if (type == 0)
{
UINT8 useodds = 0;
INT32 spawnchance[NUMKARTRESULTS];
INT32 totalspawnchance = 0;
INT32 i;
memset(spawnchance, 0, sizeof (spawnchance));
useodds = amount;
for (i = 1; i < NUMKARTRESULTS; i++)
spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(useodds, i, 0, false, false, false));
if (totalspawnchance > 0)
{
UINT8 newType;
UINT8 newAmount;
totalspawnchance = P_RandomKey(totalspawnchance);
for (i = 0; i < NUMKARTRESULTS && spawnchance[i] <= totalspawnchance; i++);
// TODO: this is bad!
// K_KartGetItemResult requires a player
// but item roulette will need rewritten to change this
switch (i)
{
// Special roulettes first, then the generic ones are handled by default
case KRITEM_DUALSNEAKER: // Sneaker x2
newType = KITEM_SNEAKER;
newAmount = 2;
break;
case KRITEM_TRIPLESNEAKER: // Sneaker x3
newType = KITEM_SNEAKER;
newAmount = 3;
break;
case KRITEM_TRIPLEBANANA: // Banana x3
newType = KITEM_BANANA;
newAmount = 3;
break;
case KRITEM_TENFOLDBANANA: // Banana x10
newType = KITEM_BANANA;
newAmount = 10;
break;
case KRITEM_TRIPLEORBINAUT: // Orbinaut x3
newType = KITEM_ORBINAUT;
newAmount = 3;
break;
case KRITEM_QUADORBINAUT: // Orbinaut x4
newType = KITEM_ORBINAUT;
newAmount = 4;
break;
case KRITEM_DUALJAWZ: // Jawz x2
newType = KITEM_JAWZ;
newAmount = 2;
break;
default:
newType = i;
newAmount = 1;
break;
}
if (newAmount > 1)
{
UINT8 j;
for (j = 0; j < newAmount-1; j++)
{
K_CreatePaperItem(
x, y, z,
angle, flip,
newType, 1
);
}
}
drop->threshold = newType;
drop->movecount = 1;
}
else
{
drop->threshold = 1;
drop->movecount = 1;
}
}
else
{
drop->threshold = type;
drop->movecount = amount;
}
drop->flags |= MF_NOCLIPTHING;
return drop;
}
// For getting EXTRA hit!
void K_DropItems(player_t *player)
{
@ -4349,24 +4461,13 @@ void K_DropItems(player_t *player)
if (player->mo && !P_MobjWasRemoved(player->mo) && player->kartstuff[k_itemamount] > 0)
{
mobj_t *drop = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FLOATINGITEM);
P_SetScale(drop, drop->scale>>4);
drop->destscale = (3*drop->destscale)/2;
drop->angle = player->mo->angle + ANGLE_90;
P_Thrust(drop,
FixedAngle(P_RandomFixed()*180) + player->mo->angle + ANGLE_90,
16*mapobjectscale);
drop->momz = P_MobjFlip(player->mo)*3*mapobjectscale;
if (drop->eflags & MFE_UNDERWATER)
drop->momz = (117 * drop->momz) / 200;
drop->threshold = player->kartstuff[k_itemtype];
drop->movecount = player->kartstuff[k_itemamount];
mobj_t *drop = K_CreatePaperItem(
player->mo->x, player->mo->y, player->mo->z + player->mo->height/2,
player->mo->angle + ANGLE_90, P_MobjFlip(player->mo),
player->kartstuff[k_itemtype], player->kartstuff[k_itemamount]
);
K_FlipFromObject(drop, player->mo);
drop->flags |= MF_NOCLIPTHING;
}
K_StripItems(player);

View file

@ -70,6 +70,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
INT32 K_GetKartDriftSparkValue(player_t *player);
void K_SpawnDriftBoostExplosion(player_t *player, int stage);
void K_KartUpdatePosition(player_t *player);
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount);
void K_DropItems(player_t *player);
void K_DropRocketSneaker(player_t *player);
void K_DropKitchenSink(player_t *player);

View file

@ -10512,6 +10512,9 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
if ((gametyperules & GTR_SPHERES) && (i == MT_RING))
return MT_BLUESPHERE;
if ((gametyperules & GTR_PAPERITEMS) && (i == MT_RANDOMITEM))
return MT_PAPERITEMSPOT;
return i;
}

View file

@ -595,6 +595,9 @@ void P_Ticker(boolean run)
if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled)
K_RunBattleOvertime();
if (gametyperules & GTR_PAPERITEMS)
K_RunPaperItemSpawners();
ps_lua_thinkframe_time = I_GetTimeMicros();
LUAh_ThinkFrame();
ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time;
@ -755,6 +758,9 @@ void P_PreTicker(INT32 frames)
if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled)
K_RunBattleOvertime();
if (gametyperules & GTR_PAPERITEMS)
K_RunPaperItemSpawners();
LUAh_ThinkFrame();
// Run shield positioning