mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-02-17 19:11:30 +00:00
Spawn Battle monitors
- Item count has always scaled up with player count. Items spawn every N tics. Previously, these items were evenly distributed across all item spots. Now, only one monitor is spawned at a time and the number of items inside scales up. - Emeralds spawn inside of monitors instead of loosely. - Sphere boxes should spawn in the same way as before. - Once a monitor has been spawned at an item spot, no more monitors can be spawned there until that one is destroyed. There's an additional delay of one spawn interval before a monitor can be spawned in that location again. This is so a monitor cannot ever instantly spawn back if one is destroyed at just the right time.
This commit is contained in:
parent
3491bd0b1d
commit
7ce12f37dc
5 changed files with 126 additions and 65 deletions
135
src/k_battle.c
135
src/k_battle.c
|
|
@ -18,6 +18,7 @@
|
|||
#include "r_sky.h" // skyflatnum
|
||||
#include "k_grandprix.h" // K_CanChangeRules
|
||||
#include "p_spec.h"
|
||||
#include "k_objects.h"
|
||||
|
||||
// Battle overtime info
|
||||
struct battleovertime battleovertime;
|
||||
|
|
@ -472,9 +473,7 @@ void K_RunPaperItemSpawners(void)
|
|||
#define MAXITEM 64
|
||||
mobj_t *spotList[MAXITEM];
|
||||
UINT8 spotMap[MAXITEM];
|
||||
UINT8 spotCount = 0, spotBackup = 0;
|
||||
|
||||
INT16 starti = 0;
|
||||
UINT8 spotCount = 0, spotBackup = 0, spotAvailable = 0;
|
||||
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
|
|
@ -488,14 +487,26 @@ void K_RunPaperItemSpawners(void)
|
|||
emeraldsSpawned |= mo->extravalue1;
|
||||
}
|
||||
|
||||
if (mo->type == MT_MONITOR)
|
||||
{
|
||||
emeraldsSpawned |= Obj_MonitorGetEmerald(mo);
|
||||
}
|
||||
|
||||
if (mo->type != MT_PAPERITEMSPOT)
|
||||
continue;
|
||||
|
||||
if (spotCount >= MAXITEM)
|
||||
continue;
|
||||
|
||||
if (Obj_ItemSpotIsAvailable(mo))
|
||||
{
|
||||
// spotMap first only includes spots
|
||||
// where a monitor doesn't exist
|
||||
spotMap[spotAvailable] = spotCount;
|
||||
spotAvailable++;
|
||||
}
|
||||
|
||||
spotList[spotCount] = mo;
|
||||
spotMap[spotCount] = spotCount;
|
||||
spotCount++;
|
||||
}
|
||||
|
||||
|
|
@ -513,7 +524,6 @@ void K_RunPaperItemSpawners(void)
|
|||
if (!(emeraldsSpawned & emeraldFlag))
|
||||
{
|
||||
firstUnspawnedEmerald = emeraldFlag;
|
||||
starti = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -521,77 +531,72 @@ void K_RunPaperItemSpawners(void)
|
|||
|
||||
//CONS_Printf("leveltime = %d ", leveltime);
|
||||
|
||||
spotBackup = spotCount;
|
||||
for (i = starti; i < pcount; i++)
|
||||
if (spotAvailable > 0)
|
||||
{
|
||||
UINT8 r = 0, key = 0;
|
||||
mobj_t *drop = NULL;
|
||||
SINT8 flip = 1;
|
||||
const UINT8 r = spotMap[P_RandomKey(PR_ITEM_ROULETTE, spotAvailable)];
|
||||
|
||||
if (spotCount == 0)
|
||||
Obj_ItemSpotAssignMonitor(spotList[r], Obj_SpawnMonitor(
|
||||
spotList[r], 1 + pcount, firstUnspawnedEmerald));
|
||||
}
|
||||
|
||||
for (i = 0; i < spotCount; ++i)
|
||||
{
|
||||
// now spotMap includes every spot
|
||||
spotMap[i] = i;
|
||||
}
|
||||
|
||||
if ((gametyperules & GTR_SPHERES) && IsOnInterval(2 * interval))
|
||||
{
|
||||
spotBackup = spotCount;
|
||||
for (i = 0; i < pcount; i++)
|
||||
{
|
||||
// all are accessible again
|
||||
spotCount = spotBackup;
|
||||
}
|
||||
UINT8 r = 0, key = 0;
|
||||
mobj_t *drop = NULL;
|
||||
SINT8 flip = 1;
|
||||
|
||||
if (spotCount == 1)
|
||||
{
|
||||
key = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = P_RandomKey(PR_ITEM_ROULETTE, spotCount);
|
||||
}
|
||||
|
||||
r = spotMap[key];
|
||||
|
||||
//CONS_Printf("[%d %d %d] ", i, key, r);
|
||||
|
||||
flip = P_MobjFlip(spotList[r]);
|
||||
|
||||
// When -1, we're spawning a Chaos Emerald.
|
||||
if (i == -1)
|
||||
{
|
||||
drop = K_SpawnChaosEmerald(
|
||||
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
||||
firstUnspawnedEmerald
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((gametyperules & GTR_SPHERES) && IsOnInterval(2 * interval))
|
||||
if (spotCount == 0)
|
||||
{
|
||||
drop = K_SpawnSphereBox(
|
||||
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
||||
10
|
||||
);
|
||||
K_FlipFromObject(drop, spotList[r]);
|
||||
// all are accessible again
|
||||
spotCount = spotBackup;
|
||||
}
|
||||
|
||||
drop = K_CreatePaperItem(
|
||||
if (spotCount == 1)
|
||||
{
|
||||
key = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = P_RandomKey(PR_ITEM_ROULETTE, spotCount);
|
||||
}
|
||||
|
||||
r = spotMap[key];
|
||||
|
||||
//CONS_Printf("[%d %d %d] ", i, key, r);
|
||||
|
||||
flip = P_MobjFlip(spotList[r]);
|
||||
|
||||
drop = K_SpawnSphereBox(
|
||||
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
||||
0, 0
|
||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
||||
10
|
||||
);
|
||||
}
|
||||
|
||||
K_FlipFromObject(drop, spotList[r]);
|
||||
K_FlipFromObject(drop, spotList[r]);
|
||||
|
||||
spotCount--;
|
||||
if (key != spotCount)
|
||||
{
|
||||
// So the core theory of what's going on is that we keep every
|
||||
// available option at the front of the array, so we don't have
|
||||
// to skip over any gaps or do recursion to avoid doubles.
|
||||
// But because spotCount can be reset in the case of a low
|
||||
// quanitity of item spawnpoints in a map, we still need every
|
||||
// entry in the array, even outside of the "visible" range.
|
||||
// A series of swaps allows us to adhere to both constraints.
|
||||
// -toast 22/03/22 (semipalindromic!)
|
||||
spotMap[key] = spotMap[spotCount];
|
||||
spotMap[spotCount] = r; // was set to spotMap[key] previously
|
||||
spotCount--;
|
||||
if (key != spotCount)
|
||||
{
|
||||
// So the core theory of what's going on is that we keep every
|
||||
// available option at the front of the array, so we don't have
|
||||
// to skip over any gaps or do recursion to avoid doubles.
|
||||
// But because spotCount can be reset in the case of a low
|
||||
// quanitity of item spawnpoints in a map, we still need every
|
||||
// entry in the array, even outside of the "visible" range.
|
||||
// A series of swaps allows us to adhere to both constraints.
|
||||
// -toast 22/03/22 (semipalindromic!)
|
||||
spotMap[key] = spotMap[spotCount];
|
||||
spotMap[spotCount] = r; // was set to spotMap[key] previously
|
||||
}
|
||||
}
|
||||
}
|
||||
//CONS_Printf("\n");
|
||||
|
|
|
|||
|
|
@ -82,6 +82,12 @@ void Obj_MonitorOnDamage(mobj_t *monitor, mobj_t *inflictor, INT32 damage);
|
|||
void Obj_MonitorOnDeath(mobj_t *monitor);
|
||||
void Obj_MonitorShardThink(mobj_t *shard);
|
||||
UINT32 Obj_MonitorGetEmerald(const mobj_t *monitor);
|
||||
void Obj_MonitorSetItemSpot(mobj_t *monitor, mobj_t *spot);
|
||||
|
||||
/* Item Spot */
|
||||
boolean Obj_ItemSpotIsAvailable(const mobj_t *spot);
|
||||
void Obj_ItemSpotAssignMonitor(mobj_t *spot, mobj_t *monitor);
|
||||
void Obj_ItemSpotUpdate(mobj_t *spot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
broly.c
|
||||
ufo.c
|
||||
monitor.c
|
||||
item-spot.c
|
||||
)
|
||||
|
|
|
|||
35
src/objects/item-spot.c
Normal file
35
src/objects/item-spot.c
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include "../doomdef.h"
|
||||
#include "../m_fixed.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../k_battle.h"
|
||||
#include "../p_tick.h"
|
||||
#include "../p_local.h"
|
||||
|
||||
#define spot_monitor(o) ((o)->target)
|
||||
#define spot_cool(o) ((o)->threshold)
|
||||
|
||||
boolean
|
||||
Obj_ItemSpotIsAvailable (const mobj_t *spot)
|
||||
{
|
||||
return P_MobjWasRemoved(spot_monitor(spot)) &&
|
||||
(leveltime - spot_cool(spot)) > BATTLE_SPAWN_INTERVAL;
|
||||
}
|
||||
|
||||
void
|
||||
Obj_ItemSpotAssignMonitor
|
||||
( mobj_t * spot,
|
||||
mobj_t * monitor)
|
||||
{
|
||||
P_SetTarget(&spot_monitor(spot), monitor);
|
||||
Obj_MonitorSetItemSpot(monitor, spot);
|
||||
}
|
||||
|
||||
void
|
||||
Obj_ItemSpotUpdate (mobj_t *spot)
|
||||
{
|
||||
if (P_MobjWasRemoved(spot_monitor(spot)) ||
|
||||
spot_monitor(spot)->health <= 0)
|
||||
{
|
||||
spot_cool(spot) = leveltime;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ static const struct monitor_part_config {
|
|||
MONITOR_PART_DEFINE (-5, 5, S_MONITOR_STAND),
|
||||
};
|
||||
|
||||
#define monitor_spot(o) ((o)->target)
|
||||
#define monitor_rngseed(o) ((o)->movedir)
|
||||
#define monitor_itemcount(o) ((o)->movecount)
|
||||
#define monitor_spawntic(o) ((o)->reactiontime)
|
||||
|
|
@ -671,6 +672,11 @@ Obj_MonitorOnDeath (mobj_t *monitor)
|
|||
// There is hitlag from being damaged, so remove
|
||||
// tangibility RIGHT NOW.
|
||||
monitor->flags &= ~(MF_SOLID);
|
||||
|
||||
if (!P_MobjWasRemoved(monitor_spot(monitor)))
|
||||
{
|
||||
Obj_ItemSpotUpdate(monitor_spot(monitor));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -689,3 +695,11 @@ Obj_MonitorGetEmerald (const mobj_t *monitor)
|
|||
{
|
||||
return monitor_emerald(monitor);
|
||||
}
|
||||
|
||||
void
|
||||
Obj_MonitorSetItemSpot
|
||||
( mobj_t * monitor,
|
||||
mobj_t * spot)
|
||||
{
|
||||
P_SetTarget(&monitor_spot(monitor), spot);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue