mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 12:31:54 +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 "r_sky.h" // skyflatnum
|
||||||
#include "k_grandprix.h" // K_CanChangeRules
|
#include "k_grandprix.h" // K_CanChangeRules
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
|
#include "k_objects.h"
|
||||||
|
|
||||||
// Battle overtime info
|
// Battle overtime info
|
||||||
struct battleovertime battleovertime;
|
struct battleovertime battleovertime;
|
||||||
|
|
@ -472,9 +473,7 @@ void K_RunPaperItemSpawners(void)
|
||||||
#define MAXITEM 64
|
#define MAXITEM 64
|
||||||
mobj_t *spotList[MAXITEM];
|
mobj_t *spotList[MAXITEM];
|
||||||
UINT8 spotMap[MAXITEM];
|
UINT8 spotMap[MAXITEM];
|
||||||
UINT8 spotCount = 0, spotBackup = 0;
|
UINT8 spotCount = 0, spotBackup = 0, spotAvailable = 0;
|
||||||
|
|
||||||
INT16 starti = 0;
|
|
||||||
|
|
||||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||||
{
|
{
|
||||||
|
|
@ -488,14 +487,26 @@ void K_RunPaperItemSpawners(void)
|
||||||
emeraldsSpawned |= mo->extravalue1;
|
emeraldsSpawned |= mo->extravalue1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mo->type == MT_MONITOR)
|
||||||
|
{
|
||||||
|
emeraldsSpawned |= Obj_MonitorGetEmerald(mo);
|
||||||
|
}
|
||||||
|
|
||||||
if (mo->type != MT_PAPERITEMSPOT)
|
if (mo->type != MT_PAPERITEMSPOT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (spotCount >= MAXITEM)
|
if (spotCount >= MAXITEM)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (Obj_ItemSpotIsAvailable(mo))
|
||||||
|
{
|
||||||
|
// spotMap first only includes spots
|
||||||
|
// where a monitor doesn't exist
|
||||||
|
spotMap[spotAvailable] = spotCount;
|
||||||
|
spotAvailable++;
|
||||||
|
}
|
||||||
|
|
||||||
spotList[spotCount] = mo;
|
spotList[spotCount] = mo;
|
||||||
spotMap[spotCount] = spotCount;
|
|
||||||
spotCount++;
|
spotCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,7 +524,6 @@ void K_RunPaperItemSpawners(void)
|
||||||
if (!(emeraldsSpawned & emeraldFlag))
|
if (!(emeraldsSpawned & emeraldFlag))
|
||||||
{
|
{
|
||||||
firstUnspawnedEmerald = emeraldFlag;
|
firstUnspawnedEmerald = emeraldFlag;
|
||||||
starti = -1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -521,77 +531,72 @@ void K_RunPaperItemSpawners(void)
|
||||||
|
|
||||||
//CONS_Printf("leveltime = %d ", leveltime);
|
//CONS_Printf("leveltime = %d ", leveltime);
|
||||||
|
|
||||||
spotBackup = spotCount;
|
if (spotAvailable > 0)
|
||||||
for (i = starti; i < pcount; i++)
|
|
||||||
{
|
{
|
||||||
UINT8 r = 0, key = 0;
|
const UINT8 r = spotMap[P_RandomKey(PR_ITEM_ROULETTE, spotAvailable)];
|
||||||
mobj_t *drop = NULL;
|
|
||||||
SINT8 flip = 1;
|
|
||||||
|
|
||||||
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
|
UINT8 r = 0, key = 0;
|
||||||
spotCount = spotBackup;
|
mobj_t *drop = NULL;
|
||||||
}
|
SINT8 flip = 1;
|
||||||
|
|
||||||
if (spotCount == 1)
|
if (spotCount == 0)
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
drop = K_SpawnSphereBox(
|
// all are accessible again
|
||||||
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
spotCount = spotBackup;
|
||||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
|
||||||
10
|
|
||||||
);
|
|
||||||
K_FlipFromObject(drop, spotList[r]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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),
|
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
||||||
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
FixedAngle(P_RandomRange(PR_ITEM_ROULETTE, 0, 359) * FRACUNIT), flip,
|
||||||
0, 0
|
10
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
K_FlipFromObject(drop, spotList[r]);
|
K_FlipFromObject(drop, spotList[r]);
|
||||||
|
|
||||||
spotCount--;
|
spotCount--;
|
||||||
if (key != spotCount)
|
if (key != spotCount)
|
||||||
{
|
{
|
||||||
// So the core theory of what's going on is that we keep every
|
// 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
|
// available option at the front of the array, so we don't have
|
||||||
// to skip over any gaps or do recursion to avoid doubles.
|
// to skip over any gaps or do recursion to avoid doubles.
|
||||||
// But because spotCount can be reset in the case of a low
|
// But because spotCount can be reset in the case of a low
|
||||||
// quanitity of item spawnpoints in a map, we still need every
|
// quanitity of item spawnpoints in a map, we still need every
|
||||||
// entry in the array, even outside of the "visible" range.
|
// entry in the array, even outside of the "visible" range.
|
||||||
// A series of swaps allows us to adhere to both constraints.
|
// A series of swaps allows us to adhere to both constraints.
|
||||||
// -toast 22/03/22 (semipalindromic!)
|
// -toast 22/03/22 (semipalindromic!)
|
||||||
spotMap[key] = spotMap[spotCount];
|
spotMap[key] = spotMap[spotCount];
|
||||||
spotMap[spotCount] = r; // was set to spotMap[key] previously
|
spotMap[spotCount] = r; // was set to spotMap[key] previously
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//CONS_Printf("\n");
|
//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_MonitorOnDeath(mobj_t *monitor);
|
||||||
void Obj_MonitorShardThink(mobj_t *shard);
|
void Obj_MonitorShardThink(mobj_t *shard);
|
||||||
UINT32 Obj_MonitorGetEmerald(const mobj_t *monitor);
|
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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,5 @@ target_sources(SRB2SDL2 PRIVATE
|
||||||
broly.c
|
broly.c
|
||||||
ufo.c
|
ufo.c
|
||||||
monitor.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),
|
MONITOR_PART_DEFINE (-5, 5, S_MONITOR_STAND),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define monitor_spot(o) ((o)->target)
|
||||||
#define monitor_rngseed(o) ((o)->movedir)
|
#define monitor_rngseed(o) ((o)->movedir)
|
||||||
#define monitor_itemcount(o) ((o)->movecount)
|
#define monitor_itemcount(o) ((o)->movecount)
|
||||||
#define monitor_spawntic(o) ((o)->reactiontime)
|
#define monitor_spawntic(o) ((o)->reactiontime)
|
||||||
|
|
@ -671,6 +672,11 @@ Obj_MonitorOnDeath (mobj_t *monitor)
|
||||||
// There is hitlag from being damaged, so remove
|
// There is hitlag from being damaged, so remove
|
||||||
// tangibility RIGHT NOW.
|
// tangibility RIGHT NOW.
|
||||||
monitor->flags &= ~(MF_SOLID);
|
monitor->flags &= ~(MF_SOLID);
|
||||||
|
|
||||||
|
if (!P_MobjWasRemoved(monitor_spot(monitor)))
|
||||||
|
{
|
||||||
|
Obj_ItemSpotUpdate(monitor_spot(monitor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -689,3 +695,11 @@ Obj_MonitorGetEmerald (const mobj_t *monitor)
|
||||||
{
|
{
|
||||||
return monitor_emerald(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