Skip to content

Commit

Permalink
libheretic|Fixed: Errant Firemace spawning/repositioning
Browse files Browse the repository at this point in the history
Also fixed a multiplayer specific bug where clients would spawn a
duplicate Firemace locally.
  • Loading branch information
danij-deng committed Mar 26, 2013
1 parent aad4be3 commit 83975f3
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 38 deletions.
22 changes: 20 additions & 2 deletions doomsday/plugins/common/include/p_start.h
Expand Up @@ -129,10 +129,10 @@ typedef struct {
} playerstart_t;

extern uint numMapSpots;
extern mapspot_t* mapSpots;
extern mapspot_t *mapSpots;

#if __JHERETIC__
extern mapspotid_t* maceSpots;
extern mapspotid_t *maceSpots;
extern uint maceSpotCount;
extern mapspotid_t* bossSpots;
extern uint bossSpotCount;
Expand Down Expand Up @@ -183,7 +183,25 @@ void P_TurnGizmosAwayFromDoors(void);
#endif

#if __JHERETIC__
/**
* Add a new map spot to the list of mace spawn spots.
*
* @param id Unique identifier of the map spot to add.
*/
void P_AddMaceSpot(mapspotid_t id);

/**
* Choose a random map spot from the list of mace spawn spots which passes
* validation according to the current game rules configuration.
*
* @note Randomization depends on the seeded playsim RNG. Ensure to call
* this at the correct time otherwise the RNG will "drift", resulting in
* behavior which differs from that of the original game logic.
*
* @return The chosen map spot; otherwise @c 0.
*/
mapspot_t const *P_ChooseRandomMaceSpot(void);

void P_AddBossSpot(mapspotid_t id);
#endif

Expand Down
88 changes: 76 additions & 12 deletions doomsday/plugins/common/src/p_mapsetup.c
Expand Up @@ -250,11 +250,11 @@ int applySurfaceColor(void* obj, void* context)
}
#endif

static boolean checkMapSpotSpawnFlags(const mapspot_t* spot)
static boolean checkMapSpotSpawnFlags(mapspot_t const *spot)
{
#if __JHEXEN__
/// @todo Move to classinfo_t
static unsigned int classFlags[] = {
static uint classFlags[] = {
MSF_FIGHTER,
MSF_CLERIC,
MSF_MAGE
Expand Down Expand Up @@ -334,7 +334,7 @@ static boolean P_IsClientAllowedToSpawn(int doomEdNum)
/**
* Should we auto-spawn one or more mobjs from the specified map spot?
*/
static boolean checkMapSpotAutoSpawn(const mapspot_t* spot)
static boolean checkMapSpotAutoSpawn(mapspot_t const *spot)
{
#if __JHERETIC__
// Ambient sound sequence activator?
Expand Down Expand Up @@ -560,13 +560,69 @@ static void loadMapSpots(void)
}
}

#if __JHERETIC__
mapspot_t const *P_ChooseRandomMaceSpot(void)
{
uint i, numQualifyingSpots;
uint chosenQualifyingSpotIdx, qualifyingSpotIdx;

if(!maceSpots || !maceSpotCount) return 0;

/*
* Pass 1: Determine how many spots qualify given the current game rules.
*/
numQualifyingSpots = 0;
for(i = 0; i < maceSpotCount; ++i)
{
mapspotid_t mapSpotId = maceSpots[i];
DENG_ASSERT(mapSpots != 0 && mapSpotId < numMapSpots);
{
// Does this spot qualify given the current game configuration?
mapspot_t const *mapSpot = &mapSpots[mapSpotId];
if(checkMapSpotSpawnFlags(mapSpot))
numQualifyingSpots += 1;
}
}
if(!numQualifyingSpots) return 0;

/*
* Pass 2: Choose and locate the chosen spot.
*/
chosenQualifyingSpotIdx = P_Random() % numQualifyingSpots;
qualifyingSpotIdx = 0;
for(i = 0; i < maceSpotCount; ++i)
{
mapspotid_t mapSpotId = maceSpots[i];
mapspot_t const *mapSpot = &mapSpots[mapSpotId];

if(!checkMapSpotSpawnFlags(mapSpot))
continue;

if(qualifyingSpotIdx != chosenQualifyingSpotIdx)
{
qualifyingSpotIdx++;
continue;
}

#if _DEBUG
Con_Message("P_ChooseRandomMaceSpot: Chosen map spot id:%u.", mapSpotId);
#endif
return mapSpot;
}

// Unreachable.
DENG_ASSERT(false);
return 0;
}
#endif // __JHERETIC__

static void spawnMapObjects(void)
{
uint i;

for(i = 0; i < numMapSpots; ++i)
{
const mapspot_t* spot = &mapSpots[i];
mapspot_t const *spot = &mapSpots[i];
mobjtype_t type;

// Not all map spots spawn mobjs on map load.
Expand All @@ -579,7 +635,7 @@ static void spawnMapObjects(void)
type = P_DoomEdNumToMobjType(spot->doomEdNum);
if(type != MT_NONE)
{
mobj_t* mo;
mobj_t *mo;

// Check for things that clients don't spawn on their own.
if(IS_CLIENT)
Expand Down Expand Up @@ -635,15 +691,23 @@ static void spawnMapObjects(void)
}

#if __JHERETIC__
if(maceSpotCount)
// Spawn a Firemace?
if(!IS_CLIENT && maceSpotCount)
{
// Sometimes doesn't show up if not in deathmatch.
// Sometimes the Firemace doesn't show up if not in deathmatch.
if(!(!deathmatch && P_Random() < 64))
{
const mapspot_t* spot = &mapSpots[maceSpots[P_Random() % maceSpotCount]];
mapspot_t const *spot = P_ChooseRandomMaceSpot();
if(spot)
{
# if _DEBUG
Con_Message("spawnMapObjects: Spawning Firemace at (%.2f, %.2f, %.2f).",
spot->origin[VX], spot->origin[VY], spot->origin[VZ]);
# endif

P_SpawnMobjXYZ(MT_WMACE, spot->origin[VX], spot->origin[VY], 0,
spot->angle, MSF_Z_FLOOR);
P_SpawnMobjXYZ(MT_WMACE, spot->origin[VX], spot->origin[VY], 0,
spot->angle, MSF_Z_FLOOR);
}
}
}
#endif
Expand Down Expand Up @@ -829,9 +893,9 @@ static void P_ResetWorldState(void)

#if __JHERETIC__
maceSpotCount = 0;
maceSpots = NULL;
maceSpots = 0;
bossSpotCount = 0;
bossSpots = NULL;
bossSpots = 0;
#endif

P_PurgeDeferredSpawns();
Expand Down
5 changes: 4 additions & 1 deletion doomsday/plugins/common/src/p_start.c
Expand Up @@ -79,7 +79,7 @@ mapspot_t* mapSpots;

#if __JHERETIC__
uint maceSpotCount;
mapspotid_t* maceSpots;
mapspotid_t *maceSpots;
uint bossSpotCount;
mapspotid_t* bossSpots;
#endif
Expand Down Expand Up @@ -973,6 +973,9 @@ boolean P_CheckSpot(coord_t x, coord_t y)
#if __JHERETIC__
void P_AddMaceSpot(mapspotid_t id)
{
#ifdef _DEBUG
Con_Message("P_AddMaceSpot: Added mace spot %u", id);
#endif
maceSpots = Z_Realloc(maceSpots, sizeof(mapspotid_t) * ++maceSpotCount, PU_MAP);
maceSpots[maceSpotCount-1] = id;
}
Expand Down
5 changes: 5 additions & 0 deletions doomsday/plugins/heretic/include/acfnlink.h
Expand Up @@ -131,7 +131,12 @@ void C_DECL A_Raise();
void C_DECL A_ReFire();
void C_DECL A_RemovePod();
void C_DECL A_RestoreArtifact();

/**
* Make a special 'thing' visible again.
*/
void C_DECL A_RestoreSpecialThing1();

void C_DECL A_RestoreSpecialThing2();
void C_DECL A_Scream();
void C_DECL A_ShutdownPhoenixPL2();
Expand Down
6 changes: 5 additions & 1 deletion doomsday/plugins/heretic/include/p_local.h
Expand Up @@ -93,7 +93,11 @@
#define USE_MACE_AMMO_1 1
#define USE_MACE_AMMO_2 5

void P_RepositionMace(mobj_t* mo);
/**
* Chooses the next spot to place the mace.
*/
void P_RepositionMace(mobj_t *mo);

void P_SetPsprite(player_t* player, int position,
statenum_t stnum);
void P_SetupPsprites(player_t* curplayer);
Expand Down
16 changes: 7 additions & 9 deletions doomsday/plugins/heretic/src/p_inter.c
Expand Up @@ -378,18 +378,16 @@ void P_HideSpecialThing(mobj_t* thing)
P_MobjChangeState(thing, S_HIDESPECIAL1);
}

/**
* Make a special thing visible again.
*/
void C_DECL A_RestoreSpecialThing1(mobj_t* thing)
void C_DECL A_RestoreSpecialThing1(mobj_t *mo)
{
if(thing->type == MT_WMACE)
{ // Do random mace placement.
P_RepositionMace(thing);
if(mo->type == MT_WMACE)
{
// Do random mace placement.
P_RepositionMace(mo);
}

thing->flags2 &= ~MF2_DONTDRAW;
S_StartSound(SFX_RESPAWN, thing);
mo->flags2 &= ~MF2_DONTDRAW;
S_StartSound(SFX_RESPAWN, mo);
}

void C_DECL A_RestoreSpecialThing2(mobj_t* thing)
Expand Down
43 changes: 30 additions & 13 deletions doomsday/plugins/heretic/src/p_mobj.c
Expand Up @@ -1141,25 +1141,42 @@ mobj_t* P_SpawnMobj(mobjtype_t type, coord_t const pos[3], angle_t angle, int sp
return P_SpawnMobjXYZ(type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags);
}

/**
* Chooses the next spot to place the mace.
*/
void P_RepositionMace(mobj_t* mo)
void P_RepositionMace(mobj_t *mo)
{
mapspotid_t spot;
BspLeaf* bspLeaf;
mapspot_t const *mapSpot;
BspLeaf *bspLeaf;

DENG_ASSERT(mo && mo->type == MT_WMACE);
#if _DEBUG
Con_Message("P_RepositionMace: Repositioning mobj [%p], thinkerId:%i.", mo, mo->thinker.id);
#endif

mapSpot = P_ChooseRandomMaceSpot();
if(!mapSpot)
{
#if _DEBUG
Con_Message("P_RepositionMace: Failed to choose a map spot, aborting...");
#endif
return;
}

P_MobjUnsetOrigin(mo);
spot = maceSpots[P_Random() % maceSpotCount];
mo->origin[VX] = mapSpots[spot].origin[VX];
mo->origin[VY] = mapSpots[spot].origin[VY];
bspLeaf = P_BspLeafAtPoint(mo->origin);
{
mo->origin[VX] = mapSpot->origin[VX];
mo->origin[VY] = mapSpot->origin[VY];
bspLeaf = P_BspLeafAtPoint(mo->origin);

mo->floorZ = P_GetDoublep(bspLeaf, DMU_CEILING_HEIGHT);
mo->origin[VZ] = mo->floorZ;
mo->floorZ = P_GetDoublep(bspLeaf, DMU_CEILING_HEIGHT);
mo->origin[VZ] = mo->floorZ;

mo->ceilingZ = P_GetDoublep(bspLeaf, DMU_CEILING_HEIGHT);
mo->ceilingZ = P_GetDoublep(bspLeaf, DMU_CEILING_HEIGHT);
}
P_MobjSetOrigin(mo);

#if _DEBUG
Con_Message("P_RepositionMace: Mobj [%p], thinkerId:%i - now at (%.2f, %.2f, %.2f).",
mo, mo->thinker.id, mo->origin[VX], mo->origin[VY], mo->origin[VZ]);
#endif
}

void P_SpawnPuff(coord_t x, coord_t y, coord_t z, angle_t angle)
Expand Down

0 comments on commit 83975f3

Please sign in to comment.