Quasar
Moderator

Posts: 4484
Registered: 08-00 |
A while back some people asked me to reverse-engineer the precise behavior of the mace spots as they functioned in Heretic 1.0, and I completed that tonight during some spare time.
code:
int MaceTypes[] =
{
0, // unused, bumps array up by 1 for gameepisode
MT_WIZARD, // episode 1
MT_BEAST, // episode 2
MT_SNAKE, // episode 3
};
void P_CloseWeapons(void)
{
int spot, i;
if(!MaceSpotCount)
return;
spot = P_Random() % MaceSpotCount;
if(!deathmatch && P_Random() < 64)
spot = -1;
for(i = 0; i < MaceSpotCount; ++i)
{
if(i == spot)
P_SpawnMobj(MaceSpots[i].x, MaceSpots[i].y, ONFLOORZ, MT_MACE);
else if(!nomonsters)
{
P_SpawnMobj(MaceSpots[i].x, MaceSpots[i].y, ONFLOORZ, MaceTypes[gameepisode]);
++totalkills;
}
}
}
Note that the array used by this routine is only 4 integers in length. This means that when playing E4M1, the array is accessed out of bounds. The next item in memory is a dummy ambient sound sequence called AmbSndSeqInit, which contains a single command, afxcmd_end, with the value 0x05. 5 as an mobj type number is the Shadowsphere.
The other routines involved in mace spot tracking were mostly identical, except that P_RepositionMace is missing calls to P_(Un)SetThingPosition, meaning that it effectively corrupts the blockmap by leaving dangling links to the object in an incorrect cell. I do not know what version of Heretic that was fixed in for certain.
Note: Anyone can use this code in a Heretic port, but please give explicit credit to me in a comment along with it :)
Last edited by Quasar on 11-01-09 at 04:33
|