Other Source Code stuff
|
To do Kill this entire section, it was made when 2.0 was the latest release. Besides which, Source Code Documentation is meant to replace it anyway
|
x<<y
= x * 2^y (Left shifting)
x>>y
= x / 2^y (Right shifting)
x++
= x + 1
x--
= x - 1
m_fixed.h
fixed_t
:
- Min = -2147483648 (-1 * 2^31, or -32768*
FRACUNIT
)
- Max = 2147483647 (2^31 - 1, or 32767*
FRACUNIT
- 1)
doomdata.h
Map level types
"BSP" = Binary Space Partition
ML_LABEL
(A separator, name, MAPxx)
ML_THINGS
(Things)
ML_LINEDEFS
(Linedefs)
ML_SIDEDEFS
(Sidedefs)
ML_VERTEXES
(Vertices, edited and BSP splits generated)
ML_SEGS
(Linesegs, from linedefs split by BSP)
ML_SSECTORS
(Subsectors, list of linesegs)
ML_NODES
(Nodes)
ML_SECTORS
(Sectors)
ML_REJECT
(LUT, sector-sector visibility)
ML_BLOCKMAP
(LUT, motion clipping, walls/grid element)
info.h
NUMMOBJFREESLOTS
= 128
NUMSPRITEFREESLOTS
= NUMMOBJFREESLOTS
= 128
NUMSTATEFREESLOTS
= NUMMOBJFREESLOTS
*6 = 768
NUMSPRITES
= 445 (Total number of sprites, including freeslots)
NUMSTATES
= 2559 (Total number of states, including freeslots)
NUMMOBJTYPES
= 445 (Total number of objects, including freeslots)
p_enemy.c
P_CheckMeleeRange
Checks how far the player is from the actor:
- true - the player is within the actor's melee range
- false - the player is too far away
Actions that check P_CheckMeleeRange
:
Melee range distance limits:
- if (dist >=
MELEERANGE
- 20*FRACUNIT
+ pl->radius) return false;
- distance >= 64 fracunits - 20 fracunits + player radius
- distance >= 44 fracunits + 16 fracunits
- if distance >= 60 fracunits,
P_CheckMeleeRange
will return false
- if (dist >= (actor->radius + pl->radius)*2) return false;
- distance >= (20 fracunits + 16*fracunits)*2
- distance >= (36 fracunits)*2
- if distance >= 72 fracunits,
P_CheckMeleeRange
will return false
- if (dist >= (actor->radius + pl->radius)*4) return false;
- dist >= (32 fracunits + 16 fracunits)*4
- dist >= (48 fracunits)*4
- if distance >= 192 fracunits,
P_CheckMeleeRange
will return false
Melee Range height distance limits
- if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) return false;
- if the player's z height is higher than the top of the actor, or the actor's z height is higher than the top of the player,
P_CheckMeleeRange
will return false
- if (pl->z + pl->height > actor->z - (40<<FRACBITS)) return false;
- if the top of the player is higher than 40 fracunits below the actor,
P_CheckMeleeRange
will return false
- if (pl->z + pl->height > actor->z - (24<<FRACBITS)) return false;
- if the top of the player is higher than 24 fracunits below the actor,
P_CheckMeleeRange
will return false
Code - P_CheckMeleeRange
|
|
//
// P_CheckMeleeRange
//
static boolean P_CheckMeleeRange(mobj_t *actor)
{
mobj_t *pl;
fixed_t dist;
if (!actor->target)
return false;
pl = actor->target;
dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y);
switch (actor->type)
{
case MT_JETTBOMBER:
if (dist >= (actor->radius + pl->radius)*2)
return false;
break;
case MT_FACESTABBER:
if (dist >= (actor->radius + pl->radius)*4)
return false;
break;
default:
if (dist >= MELEERANGE - 20*FRACUNIT + pl->radius)
return false;
break;
}
// check height now, so that damn crawlas cant attack
// you if you stand on a higher ledge.
if (actor->type == MT_JETTBOMBER)
{
if (pl->z + pl->height > actor->z - (40<<FRACBITS))
return false;
}
else if (actor->type == MT_SKIM)
{
if (pl->z + pl->height > actor->z - (24<<FRACBITS))
return false;
}
else
{
if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height))
return false;
if (actor->type != MT_JETTBOMBER && actor->type != MT_SKIM
&& !P_CheckSight(actor, actor->target))
{
return false;
}
}
return true;
}
|
|
P_CheckMissileRange
Actions that check P_CheckMissileRange
:
Code - P_CheckMissileRange
|
|
//
// P_CheckMissileRange
//
static boolean P_CheckMissileRange(mobj_t *actor)
{
fixed_t dist;
if (!P_CheckSight(actor, actor->target))
return false;
if (actor->reactiontime)
return false; // do not attack yet
// OPTIMIZE: get this from a global checksight
dist = P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT;
if (!actor->info->meleestate)
dist -= 128*FRACUNIT; // no melee attack, so fire more
dist >>= 16;
if (actor->type == MT_EGGMOBILE)
dist >>= 1;
if (dist > 200)
dist = 200;
if (actor->type == MT_EGGMOBILE && dist > 160)
dist = 160;
if (P_Random() < dist)
return false;
return true;
}
|
|
p_local.h
FLOATSPEED
= FRACUNIT
*4
- = 4 fracunits
MAPBLOCKUNITS
= 128
MAPBLOCKSIZE
= MAPBLOCKUNITS
*FRACUNIT
- = 128*65536
- = 8388608
MAPBLOCKSHIFT
= FRACBITS
+7
- = 16 + 7
- = 23
MAPBMASK
= MAPBLOCKSIZE
-1
- = 8388608 - 1
- = 8388607
MAPBTOFRAC
= MAPBLOCKSHIFT
-FRACBITS
- = 23 - 16
- = 7
PLAYERRADIUS
= 16*FRACUNIT
- = 16 fracunits
MAXRADIUS
= 32*FRACUNIT
- = 32 fracunits
MAXSTEPMOVE
= 24*FRACUNIT
- = 24 fracunits (Maximum height an object, e.g. the player, can walk up/down without jumping)
USERANGE
= 64*FRACUNIT
- = 64 fracunits
MELEERANGE
= 64*FRACUNIT
- = 64 fracunits
MISSILERANGE
= 32*64*FRACUNIT
- = 2048*
FRACUNIT
- = 2048 fracunits
ONFLOORZ
= INT32_MIN
- = -2147483648 (-1 * 2*31, or -32768*
FRACUNIT
)
ONCEILINGZ
= INT32_MAX
- = 2147483647 (2*31 - 1, or (32768*
FRACUNIT
)-1)
ITEMQUESIZE
= 1024 (Time interval for item respawning)
p_mobj.c/p_mobj.h
STOPSPEED
= (FRACUNIT
/NEWTICRATERATIO
)
- =
FRACUNIT
- = 1 fracunit/1 tic (Slowest speed an object can move in any direction - if slower, the object stops moving altogether)
FRICTION
= (ORIG_FRICTION
/NEWTICRATERATIO
)
- =
ORIG_FRICTION
- = 59392
P_GenericBossThinker
(Thinker for custom SOC-made bosses)
Code - P_GenericBossThinker
|
|
// AI for a generic boss.
static void P_GenericBossThinker(mobj_t *mobj)
{
if (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)
{
mobj->flags2 &= ~MF2_FRET;
mobj->flags &= ~MF_TRANSLATION;
}
if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))
{
if (mobj->health <= 0)
{
// look for a new target
if (P_Look4Players(mobj, true) && mobj->info->mass) // Bid farewell!
S_StartSound(mobj, mobj->info->mass);
return;
}
// look for a new target
if (P_Look4Players(mobj, true) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound);
return;
}
if (mobj->state == &states[mobj->info->spawnstate])
A_Boss1Chase(mobj);
if (mobj->state == &states[mobj->info->meleestate]
|| (mobj->state == &states[mobj->info->missilestate]
&& mobj->health > mobj->info->damage))
{
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
}
}
|
|
P_Boss1Thinker
(Thinker for the Egg Mobile)
Code - P_Boss1Thinker
|
|
// AI for the first boss.
static void P_Boss1Thinker(mobj_t *mobj)
{
if (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)
{
mobj->flags2 &= ~MF2_FRET;
mobj->flags &= ~MF_TRANSLATION;
}
if (!mobj->tracer)
{
var1 = 0;
A_BossJetFume(mobj);
}
if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))
{
if (mobj->health <= 0)
{
if (P_Look4Players(mobj, true) && mobj->info->mass) // Bid farewell!
S_StartSound(mobj, mobj->info->mass);
return;
}
// look for a new target
if (P_Look4Players(mobj, true) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound);
return;
}
if (mobj->state == &states[mobj->info->spawnstate])
A_Boss1Chase(mobj);
if (mobj->state == &states[mobj->info->meleestate]
|| (mobj->state == &states[mobj->info->missilestate]
&& mobj->health > mobj->info->damage))
{
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
}
}
|
|
P_Boss2Thinker
(Thinker for the Egg Slimer)
Code - P_Boss2Thinker
|
|
// AI for the second boss.
// No, it does NOT convert "Boss" to a "Thinker". =P
static void P_Boss2Thinker(mobj_t *mobj)
{
if (mobj->movecount)
mobj->movecount--;
if (!(mobj->movecount))
{
mobj->flags2 &= ~MF2_FRET;
mobj->flags &= ~MF_TRANSLATION;
}
if (!mobj->tracer
#ifdef CHAOSISNOTDEADYET
&& gametype != GT_CHAOS
#endif
)
{
var1 = 0;
A_BossJetFume(mobj);
}
if (mobj->health <= mobj->info->damage && (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
{
if (mobj->health <= 0)
{
// look for a new target
if (P_Look4Players(mobj, true) && mobj->info->mass) // Bid farewell!
S_StartSound(mobj, mobj->info->mass);
return;
}
// look for a new target
if (P_Look4Players(mobj, true) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound);
return;
}
#ifdef CHAOSISNOTDEADYET
if (gametype == GT_CHAOS && (mobj->state == &states[S_EGGMOBILE2_POGO1]
|| mobj->state == &states[S_EGGMOBILE2_POGO2]
|| mobj->state == &states[S_EGGMOBILE2_POGO3]
|| mobj->state == &states[S_EGGMOBILE2_POGO4]
|| mobj->state == &states[S_EGGMOBILE2_STND])) // Chaos mode, he pogos only
{
mobj->flags &= ~MF_NOGRAVITY;
A_Boss2Pogo(mobj);
}
else if (gametype != GT_CHAOS)
#endif
{
if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage)
A_Boss2Chase(mobj);
else if (mobj->state == &states[mobj->info->raisestate]
|| mobj->state == &states[S_EGGMOBILE2_POGO2]
|| mobj->state == &states[S_EGGMOBILE2_POGO3]
|| mobj->state == &states[S_EGGMOBILE2_POGO4]
|| mobj->state == &states[mobj->info->spawnstate])
{
mobj->flags &= ~MF_NOGRAVITY;
A_Boss2Pogo(mobj);
}
}
}
|
|
P_Boss3Thinker
(Thinker for the Sea Egg)
Code - P_Boss3Thinker
|
|
// AI for the third boss.
static void P_Boss3Thinker(mobj_t *mobj)
{
if (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)
{
mobj->flags2 &= ~MF2_FRET;
mobj->flags &= ~MF_TRANSLATION;
}
if (mobj->flags2 & MF2_FRET)
{
mobj->movedir = 1;
if (mobj->health <= mobj->info->damage)
{
var1 = 100;
var2 = 0;
A_LinedefExecute(mobj);
}
}
if (mobj->movefactor > ORIG_FRICTION_FACTOR)
{
mobj->movefactor--;
return;
}
if (!mobj->tracer)
{
var1 = 1;
A_BossJetFume(mobj);
}
if (mobj->health <= 0)
{
mobj->movecount = 0;
mobj->reactiontime = 0;
if (mobj->state < &states[mobj->info->xdeathstate])
return;
if (mobj->threshold == -1)
{
mobj->momz = mobj->info->speed;
return;
}
}
if (mobj->reactiontime && mobj->health > mobj->info->damage) // Shock mode
{
UINT32 i;
if (mobj->state != &states[mobj->info->spawnstate])
P_SetMobjState(mobj, mobj->info->spawnstate);
if (leveltime % 2*TICRATE == 0)
{
ffloor_t *rover;
// Shock the water
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
P_DamageMobj(players[i].mo, mobj, mobj, 1);
}
// Make the water flash
for (i = 0; i < numsectors; i++)
{
if (!sectors[i].ffloors)
continue;
for (rover = sectors[i].ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
P_SpawnLightningFlash(rover->master->frontsector);
break;
}
}
if (leveltime % 35 == 0)
S_StartSound(0, sfx_buzz1);
}
// If in the center, check to make sure
// none of the players are in the water
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
return; // Stay put
}
mobj->reactiontime = 0;
}
else if (mobj->movecount) // Firing mode
{
UINT32 i;
// look for a new target
P_Look4Players(mobj, true);
if (!mobj->target || !mobj->target->player)
return;
// Are there any players underwater? If so, shock them!
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
{
mobj->movecount = 0;
P_SetMobjState(mobj, mobj->info->spawnstate);
break;
}
}
// Always face your target.
A_FaceTarget(mobj);
// Check if the attack animation is running. If not, play it.
if (mobj->state < &states[mobj->info->missilestate] || mobj->state > &states[mobj->info->raisestate])
P_SetMobjState(mobj, mobj->info->missilestate);
}
else if (mobj->threshold >= 0) // Traveling mode
{
thinker_t *th;
mobj_t *mo2;
fixed_t dist, dist2;
fixed_t speed;
P_SetTarget(&mobj->target, NULL);
if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0
&& !(mobj->flags2 & MF2_FRET))
P_SetMobjState(mobj, mobj->info->spawnstate);
// scan the thinkers
// to find a point that matches
// the number
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold)
{
P_SetTarget(&mobj->target, mo2);
break;
}
}
if (!mobj->target) // Should NEVER happen
{
CONS_Printf("Error: Boss 3 was unable to find specified waypoint: %d\n", mobj->threshold);
return;
}
dist = P_AproxDistance(P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y), mobj->target->z - mobj->z);
if (dist < 1)
dist = 1;
if ((mobj->movedir) || (mobj->health <= mobj->info->damage))
speed = mobj->info->speed * 2;
else
speed = mobj->info->speed;
mobj->momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed);
mobj->momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed);
mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed);
mobj->angle = R_PointToAngle(mobj->momx, mobj->momy);
dist2 = P_AproxDistance(P_AproxDistance(mobj->target->x - (mobj->x + mobj->momx), mobj->target->y - (mobj->y + mobj->momy)), mobj->target->z - (mobj->z + mobj->momz));
if (dist2 < 1)
dist2 = 1;
if ((dist >> FRACBITS) <= (dist2 >> FRACBITS))
{
// If further away, set XYZ of mobj to waypoint location
P_UnsetThingPosition(mobj);
mobj->x = mobj->target->x;
mobj->y = mobj->target->y;
mobj->z = mobj->target->z;
mobj->momx = mobj->momy = mobj->momz = 0;
P_SetThingPosition(mobj);
if (mobj->threshold == 0)
{
mobj->reactiontime = 1; // Bzzt! Shock the water!
mobj->movedir = 0;
if (mobj->health <= 0)
{
mobj->flags |= MF_NOGRAVITY|MF_NOCLIP;
mobj->flags |= MF_NOCLIPHEIGHT;
mobj->threshold = -1;
return;
}
}
// Set to next waypoint in sequence
if (mobj->target->spawnpoint)
{
// From the center point, choose one of the five paths
if (mobj->target->spawnpoint->angle == 0)
mobj->threshold = (P_Random()%5) + 1;
else
mobj->threshold = mobj->target->spawnpoint->extrainfo;
// If the deaf flag is set, go into firing mode
if (mobj->target->spawnpoint->options & MTF_AMBUSH)
{
if (mobj->health <= mobj->info->damage)
mobj->movefactor = ORIG_FRICTION_FACTOR + 5*TICRATE;
else
mobj->movecount = 1;
}
}
else // This should never happen, as well
CONS_Printf("Error: Boss 3 waypoint has no spawnpoint associated with it.\n");
}
}
}
|
|
P_Boss7Thinker
(Thinker for Brak Eggman)
Code - P_Boss7Thinker
|
|
// AI for Black Eggman
//
// Sorry for all of the code copypaste from p_enemy.c
// Maybe someone can un-static a lot of this stuff so it
// can be called from here?
//
// Note: You CANNOT have more than ONE Black Eggman
// in a level! Just don't try it!
//
//
typedef enum
{
DI_NODIR = -1,
DI_EAST = 0,
DI_NORTHEAST = 1,
DI_NORTH = 2,
DI_NORTHWEST = 3,
DI_WEST = 4,
DI_SOUTHWEST = 5,
DI_SOUTH = 6,
DI_SOUTHEAST = 7,
NUMDIRS = 8,
} dirtype_t;
//
// P_NewChaseDir related LUT.
//
static dirtype_t opposite[] =
{
DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
};
static dirtype_t diags[] =
{
DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
};
static const fixed_t xspeed[NUMDIRS] = {FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000};
static const fixed_t yspeed[NUMDIRS] = {0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000};
/** Moves an actor in its current direction.
*
* \param actor Actor object to move.
* \return False if the move is blocked, otherwise true.
*/
static boolean P_Move(mobj_t *actor, fixed_t speed)
{
fixed_t tryx, tryy;
dirtype_t movedir = actor->movedir;
if (movedir == DI_NODIR || !actor->health)
return false;
I_Assert((unsigned)movedir < 8);
tryx = actor->x + speed*xspeed[movedir];
tryy = actor->y + speed*yspeed[movedir];
if (!P_TryMove(actor, tryx, tryy, false))
{
if (actor->flags & MF_FLOAT && floatok)
{
// must adjust height
if (actor->z < tmfloorz)
actor->z += FLOATSPEED;
else
actor->z -= FLOATSPEED;
actor->flags2 |= MF2_INFLOAT;
return true;
}
return false;
}
else
actor->flags2 &= ~MF2_INFLOAT;
return true;
}
/** Attempts to move an actor on in its current direction.
* If the move succeeds, the actor's move count is reset
* randomly to a value from 0 to 15.
*
* \param actor Actor to move.
* \return True if the move succeeds, false if the move is blocked.
*/
static boolean P_TryWalk(mobj_t *actor)
{
if (!P_Move(actor, actor->info->speed))
return false;
actor->movecount = P_Random() & 15;
return true;
}
static void P_NewChaseDir(mobj_t *actor)
{
fixed_t deltax, deltay;
dirtype_t d[3];
dirtype_t tdir = DI_NODIR, olddir, turnaround;
#ifdef PARANOIA
if (!actor->target)
I_Error("P_NewChaseDir: called with no target");
#endif
olddir = actor->movedir;
if (olddir >= NUMDIRS)
olddir = DI_NODIR;
if (olddir != DI_NODIR)
turnaround = opposite[olddir];
else
turnaround = olddir;
deltax = actor->target->x - actor->x;
deltay = actor->target->y - actor->y;
if (deltax > 10*FRACUNIT)
d[1] = DI_EAST;
else if (deltax < -10*FRACUNIT)
d[1] = DI_WEST;
else
d[1] = DI_NODIR;
if (deltay < -10*FRACUNIT)
d[2] = DI_SOUTH;
else if (deltay > 10*FRACUNIT)
d[2] = DI_NORTH;
else
d[2] = DI_NODIR;
// try direct route
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
{
dirtype_t newdir = diags[((deltay < 0)<<1) + (deltax > 0)];
actor->movedir = newdir;
if ((newdir != turnaround) && P_TryWalk(actor))
return;
}
// try other directions
if (P_Random() > 200 || abs(deltay) > abs(deltax))
{
tdir = d[1];
d[1] = d[2];
d[2] = tdir;
}
if (d[1] == turnaround)
d[1] = DI_NODIR;
if (d[2] == turnaround)
d[2] = DI_NODIR;
if (d[1] != DI_NODIR)
{
actor->movedir = d[1];
if (P_TryWalk(actor))
return; // either moved forward or attacked
}
if (d[2] != DI_NODIR)
{
actor->movedir = d[2];
if (P_TryWalk(actor))
return;
}
// there is no direct path to the player, so pick another direction.
if (olddir != DI_NODIR)
{
actor->movedir =olddir;
if (P_TryWalk(actor))
return;
}
// randomly determine direction of search
if (P_Random() & 1)
{
for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++)
{
if (tdir != turnaround)
{
actor->movedir = tdir;
if (P_TryWalk(actor))
return;
}
}
}
else
{
for (tdir = DI_SOUTHEAST; tdir >= DI_EAST; tdir--)
{
if (tdir != turnaround)
{
actor->movedir = tdir;
if (P_TryWalk(actor))
return;
}
}
}
if (turnaround != DI_NODIR)
{
actor->movedir = turnaround;
if (P_TryWalk(actor))
return;
}
actor->movedir = (angle_t)DI_NODIR; // cannot move
}
static void P_Boss7Thinker(mobj_t *mobj)
{
if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))
{
// look for a new target
if (P_LookForPlayers(mobj, true, false, 0))
return; // got a new target
P_SetMobjStateNF(mobj, mobj->info->spawnstate);
return;
}
if (mobj->health >= 8 && (leveltime & 14) == 0)
P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height, MT_SMOK)->momz = FRACUNIT;
if (mobj->state == &states[S_BLACKEGG_STND] && mobj->tics == mobj->state->tics)
{
mobj->reactiontime += P_Random();
if (mobj->health <= 2)
mobj->reactiontime /= 4;
}
else if (mobj->state == &states[S_BLACKEGG_DIE4] && mobj->tics == mobj->state->tics)
{
INT32 i;
thinker_t *th;
mobj_t *mo2;
mobj->health = 0;
// make sure there is a player alive for victory
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (players[i].health > 0
|| ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0))))
break;
if (i == MAXPLAYERS)
return; // no one left alive, so do not end game
// scan the remaining thinkers to see
// if all bosses are dead
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 != mobj && (mo2->flags & MF_BOSS) && mo2->health > 0)
return; // other boss not dead
}
for (i = 0; i < MAXPLAYERS; i++)
P_DoPlayerExit(&players[i]);
P_SetTarget(&mobj->target, NULL);
mobj->flags |= MF_NOCLIP;
mobj->flags &= ~MF_SPECIAL;
S_StartSound(0, sfx_befall);
}
else if (mobj->state >= &states[S_BLACKEGG_WALK1]
&& mobj->state <= &states[S_BLACKEGG_WALK6])
{
// Chase
INT32 delta;
INT32 i;
if (mobj->z != mobj->floorz)
return;
// Self-adjust if stuck on the edge
if (mobj->tracer)
{
if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) > 128*FRACUNIT - mobj->radius)
P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y), FRACUNIT);
}
if (mobj->flags2 & MF2_FRET)
{
P_SetMobjState(mobj, S_BLACKEGG_DESTROYPLAT1);
S_StartSound(0, sfx_s3k_34);
mobj->flags2 &= ~MF2_FRET;
return;
}
// turn towards movement direction if not there yet
if (mobj->movedir < NUMDIRS)
{
mobj->angle &= (7<<29);
delta = mobj->angle - (mobj->movedir << 29);
if (delta > 0)
mobj->angle -= ANGLE_45;
else if (delta < 0)
mobj->angle += ANGLE_45;
}
// Is a player on top of us?
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > mobj->radius)
continue;
if (players[i].mo->z > mobj->z + mobj->height - 2*FRACUNIT
&& players[i].mo->z < mobj->z + mobj->height + 32*FRACUNIT)
{
// Punch him!
P_SetMobjState(mobj, mobj->info->meleestate);
S_StartSound(0, sfx_begrnd); // warning sound
return;
}
}
if (mobj->health <= 2
&& mobj->target
&& mobj->target->player
&& (mobj->target->player->pflags & PF_ITEMHANG))
{
A_FaceTarget(mobj);
P_SetMobjState(mobj, S_BLACKEGG_SHOOT1);
mobj->movecount = TICRATE + P_Random()/2;
return;
}
if (mobj->reactiontime)
mobj->reactiontime--;
if (mobj->reactiontime <= 0 && mobj->z == mobj->floorz)
{
// Here, we'll call P_Random() and decide what kind of attack to do
RetryAttack:
switch(mobj->threshold)
{
case 0: // Lob cannon balls
if (mobj->z < 1056*FRACUNIT)
{
A_FaceTarget(mobj);
P_SetMobjState(mobj, mobj->info->xdeathstate);
mobj->movecount = 7*TICRATE + P_Random();
}
else
{
mobj->threshold++;
goto RetryAttack;
}
break;
case 1: // Chaingun Goop
A_FaceTarget(mobj);
P_SetMobjState(mobj, S_BLACKEGG_SHOOT1);
if (mobj->health > 2)
mobj->movecount = TICRATE + P_Random()/3;
else
mobj->movecount = TICRATE + P_Random()/2;
break;
case 2: // Homing Missile
A_FaceTarget(mobj);
P_SetMobjState(mobj, mobj->info->missilestate);
S_StartSound(0, sfx_beflap);
break;
}
mobj->threshold++;
mobj->threshold %= 3;
return;
}
// possibly choose another target
if (multiplayer && (mobj->target->health <= 0 || !P_CheckSight(mobj, mobj->target))
&& P_LookForPlayers(mobj, true, false, 0))
return; // got a new target
if (leveltime & 1)
{
// chase towards player
if (--mobj->movecount < 0 || !P_Move(mobj, mobj->info->speed))
P_NewChaseDir(mobj);
}
}
else if (mobj->state == &states[S_BLACKEGG_MISSILE3] && mobj->tics == states[S_BLACKEGG_MISSILE3].tics)
{
mobj_t dummymo;
if (!mobj->target)
{
P_SetMobjState(mobj, mobj->info->spawnstate);
return;
}
A_FaceTarget(mobj);
// set dummymo's coordinates
dummymo.x = mobj->target->x;
dummymo.y = mobj->target->y;
dummymo.z = mobj->target->z + 16*FRACUNIT; // raised height
P_SpawnXYZMissile(mobj, &dummymo, MT_BLACKEGGMAN_MISSILE,
mobj->x + P_ReturnThrustX(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->y + P_ReturnThrustY(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->z + FixedDiv(mobj->height, 3*FRACUNIT/2));
P_SpawnXYZMissile(mobj, &dummymo, MT_BLACKEGGMAN_MISSILE,
mobj->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->z + FixedDiv(mobj->height, 3*FRACUNIT/2));
P_SpawnXYZMissile(mobj, &dummymo, MT_BLACKEGGMAN_MISSILE,
mobj->x + P_ReturnThrustX(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->y + P_ReturnThrustY(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->z + mobj->height/2);
P_SpawnXYZMissile(mobj, &dummymo, MT_BLACKEGGMAN_MISSILE,
mobj->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->z + mobj->height/2);
}
else if (mobj->state == &states[S_BLACKEGG_PAIN1] && mobj->tics == mobj->state->tics)
{
if (mobj->health > 0)
mobj->health--;
mobj->reactiontime /= 3;
if (mobj->health <= 0)
{
INT32 i;
P_KillMobj(mobj, NULL, NULL);
// It was a team effort
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
continue;
players[i].score += 1000;
}
}
}
else if (mobj->state == &states[S_BLACKEGG_PAIN35] && mobj->tics == 1)
{
if (mobj->health == 2)
{
// Begin platform destruction
mobj->flags2 |= MF2_FRET;
P_SetMobjState(mobj, mobj->info->raisestate);
}
}
else if (mobj->state == &states[S_BLACKEGG_HITFACE4] && mobj->tics == mobj->state->tics)
{
// This is where Black Eggman hits his face.
// If a player is on top of him, the player gets hurt.
// But, if the player has managed to escape,
// Black Eggman gets hurt!
INT32 i;
mobj->state->nextstate = mobj->info->painstate; // Reset
S_StartSound(0, sfx_bedeen);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > (mobj->radius + players[i].mo->radius))
continue;
if (players[i].mo->z > mobj->z + mobj->height - FRACUNIT
&& players[i].mo->z < mobj->z + mobj->height + 128*FRACUNIT) // You can't be in the vicinity, either...
{
// Punch him!
P_DamageMobj(players[i].mo, mobj, mobj, 1);
mobj->state->nextstate = mobj->info->spawnstate;
// Laugh
S_StartSound(0, sfx_bewar1 + (P_Random() % 4));
}
}
}
else if (mobj->state == &states[S_BLACKEGG_GOOP])
{
// Lob cannon balls
if (mobj->movecount-- <= 0 || !mobj->target)
{
P_SetMobjState(mobj, mobj->info->spawnstate);
return;
}
if ((leveltime & 15) == 0)
{
var1 = MT_CANNONBALL;
var2 = 2*TICRATE + (80<<16);
A_LobShot(mobj);
S_StartSound(0, sfx_begoop);
}
}
else if (mobj->state == &states[S_BLACKEGG_SHOOT2])
{
// Chaingun goop
mobj_t *missile;
if (mobj->movecount-- <= 0 || !mobj->target)
{
P_SetMobjState(mobj, mobj->info->spawnstate);
return;
}
A_FaceTarget(mobj);
missile = P_SpawnXYZMissile(mobj, mobj->target, MT_BLACKEGGMAN_GOOPFIRE,
mobj->x + P_ReturnThrustX(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->y + P_ReturnThrustY(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)),
mobj->z + FixedDiv(mobj->height, 3*FRACUNIT/2));
S_StopSound(missile);
if (leveltime & 1)
S_StartSound(0, sfx_beshot);
}
else if (mobj->state == &states[S_BLACKEGG_JUMP1] && mobj->tics == 1)
{
mobj_t *hitspot = NULL, *mo2;
angle_t an;
fixed_t dist, closestdist;
fixed_t vertical, horizontal;
fixed_t airtime = 5*TICRATE;
INT32 waypointNum = 0;
thinker_t *th;
INT32 i;
boolean foundgoop = false;
INT32 closestNum;
// Looks for players in goop. If you find one, try to jump on him.
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].powers[pw_ingoop])
{
closestNum = -1;
closestdist = 16384*FRACUNIT; // Just in case...
// Find waypoint he is closest to
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint)
{
dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y);
if (closestNum == -1 || dist < closestdist)
{
closestNum = (mo2->spawnpoint->options & 7);
closestdist = dist;
foundgoop = true;
}
}
}
waypointNum = closestNum;
break;
}
}
if (!foundgoop)
{
if (mobj->z > 1056*FRACUNIT)
waypointNum = 0;
else
waypointNum = 1 + (P_Random() % 4);
}
// Don't jump to the center when health is low.
// Force the player to beat you with missiles.
if (mobj->health <= 2 && waypointNum == 0)
waypointNum = 1 + (P_Random() %4);
if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT
&& mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum)
{
if (P_Random() & 1)
waypointNum++;
else
waypointNum--;
waypointNum %= 5;
if (waypointNum < 0)
waypointNum = 0;
}
if (waypointNum == 0 && mobj->health <= 2)
waypointNum = 1 + (P_Random() & 1);
// scan the thinkers to find
// the waypoint to use
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum)
{
hitspot = mo2;
break;
}
}
if (hitspot == NULL)
{
CONS_Printf("BlackEggman unable to find waypoint #%d!\n", waypointNum);
P_SetMobjState(mobj, mobj->info->spawnstate);
return;
}
P_SetTarget(&mobj->tracer, hitspot);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, hitspot->x, hitspot->y);
an = mobj->angle;
an >>= ANGLETOFINESHIFT;
dist = P_AproxDistance(hitspot->x - mobj->x, hitspot->y - mobj->y);
horizontal = dist / airtime;
vertical = (gravity*airtime)/2;
mobj->momx = FixedMul(horizontal, FINECOSINE(an));
mobj->momy = FixedMul(horizontal, FINESINE(an));
mobj->momz = vertical;
// mobj->momz = 10*FRACUNIT;
}
else if (mobj->state == &states[S_BLACKEGG_JUMP2] && mobj->z <= mobj->floorz)
{
// BANG! onto the ground
INT32 i,j;
fixed_t ns;
fixed_t x,y,z;
mobj_t *mo2;
S_StartSound(0, sfx_befall);
z = mobj->floorz;
for (j = 0; j < 2; j++)
{
for (i = 0; i < 32; i++)
{
const angle_t fa = (i*FINEANGLES/16) & FINEMASK;
ns = 64 * FRACUNIT;
x = mobj->x + FixedMul(FINESINE(fa),ns);
y = mobj->y + FixedMul(FINECOSINE(fa),ns);
mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE);
ns = 16 * FRACUNIT;
mo2->momx = FixedMul(FINESINE(fa),ns);
mo2->momy = FixedMul(FINECOSINE(fa),ns);
}
z -= 32*FRACUNIT;
}
// Hurt player??
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > mobj->radius*4)
continue;
if (players[i].mo->z > mobj->z + 128*FRACUNIT)
continue;
if (players[i].mo->z < mobj->z - 64*FRACUNIT)
continue;
P_DamageMobj(players[i].mo, mobj, mobj, 1);
// Laugh
S_StartSound(0, sfx_bewar1 + (P_Random() % 4));
}
P_SetMobjState(mobj, mobj->info->spawnstate);
}
else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics)
{
S_StartSound(0, sfx_bedie1 + (P_Random() & 1));
}
}
|
|
P_SpawnMobj
ERZ3 mode
If TypeofLevel has ERZ3 (value 2048) set, all objects will have their destscale set to 50 upon spawning (half their regular size), except for the following:
MT_BLACKEGGMAN
- Brak Eggman
MT_BLACKEGGMAN_GOOPFIRE
- Brak Eggman's Goop
MT_BLACKEGGMAN_HELPER
- Brak Eggman's Helper Object (The part of Brak Eggman you can stand on)
MT_BLACKEGGMAN_MISSILE
- Brak Eggman's Missile
MT_SMOK
- Smoke particle
MT_GOOP
- Egg Slimer's Goop
MT_POP
- Large Bubble Popping Object
Objects that are given MF_NOBLOCKMAP
:
Objects that are given MF_NOCLIPHEIGHT
when spawned:
MT_RING
- Ring
MT_COIN
- Coin
MT_BLUEBALL
- Blue Sphere (If BLUE_SPHERES
is defined)
MT_THOK
- Thok Object
MT_GHOST
- Ghost Object
Code - P_SpawnMobj
|
|
//
// P_SpawnMobj
//
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
{
const mobjinfo_t *info = &mobjinfo[type];
state_t *st;
mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
mobj->type = type;
mobj->info = info;
mobj->x = x;
mobj->y = y;
mobj->radius = info->radius;
mobj->height = info->height;
mobj->flags = info->flags;
mobj->health = info->spawnhealth;
mobj->reactiontime = info->reactiontime;
mobj->lastlook = -1; // stuff moved in P_enemy.P_LookForPlayer
// do not set the state with P_SetMobjState,
// because action routines can not be called yet
st = &states[info->spawnstate];
mobj->state = st;
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
mobj->friction = ORIG_FRICTION;
mobj->movefactor = ORIG_FRICTION_FACTOR;
// All mobjs are created at 100% scale.
mobj->scale = 100;
mobj->destscale = mobj->scale;
mobj->scalespeed = 8;
// TODO: Make this a special map header
if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN || mobj->type == MT_BLACKEGGMAN_GOOPFIRE
|| mobj->type == MT_BLACKEGGMAN_HELPER || mobj->type == MT_BLACKEGGMAN_MISSILE
|| mobj->type == MT_SMOK || mobj->type == MT_GOOP || mobj->type == MT_POP))
{
mobj->destscale = 50;
}
switch (mobj->type)
{
case MT_BLACKEGGMAN:
{
mobj_t *spawn = P_SpawnMobj(mobj->x, mobj->z, mobj->z+mobj->height-16*FRACUNIT, MT_BLACKEGGMAN_HELPER);
P_SetTarget(&spawn->target, mobj);
}
break;
case MT_DETON:
mobj->movedir = 0;
break;
case MT_EGGGUARD:
{
mobj_t *spawn = P_SpawnMobj(x, y, z, MT_EGGSHIELD);
P_SetTarget(&mobj->tracer, spawn);
P_SetTarget(&spawn->tracer, mobj);
}
break;
case MT_BIRD:
case MT_BUNNY:
case MT_MOUSE:
case MT_CHICKEN:
case MT_COW:
mobj->fuse = 300 + (P_Random() % 50);
break;
case MT_REDRING: // Make MT_REDRING red by default
mobj->flags |= MF_TRANSLATION;
mobj->color = 6;
break;
case MT_SMALLBUBBLE: // Bubbles eventually dissipate, in case they get caught somewhere.
case MT_MEDIUMBUBBLE:
case MT_EXTRALARGEBUBBLE:
mobj->fuse += 30 * TICRATE;
break;
case MT_BUSH:
case MT_BERRYBUSH:
case MT_THZPLANT:
case MT_GFZFLOWER1:
case MT_GFZFLOWER2:
case MT_GFZFLOWER3:
case MT_CEZFLOWER:
case MT_SEAWEED:
case MT_CORAL1:
case MT_CORAL2:
case MT_CORAL3:
// if (!modifiedgame) // Speedup, if the game is not modified.
mobj->flags |= MF_NOBLOCKMAP;
break;
case MT_REDTEAMRING:
mobj->flags |= MF_TRANSLATION;
mobj->color = 6;
mobj->flags |= MF_NOCLIPHEIGHT;
break;
case MT_BLUETEAMRING:
mobj->flags |= MF_TRANSLATION;
mobj->color = 7;
mobj->flags |= MF_NOCLIPHEIGHT;
break;
case MT_RING:
case MT_COIN:
#ifdef BLUE_SPHERES
case MT_BLUEBALL:
#endif
nummaprings++;
case MT_BOUNCERING:
case MT_RAILRING:
case MT_AUTOMATICRING:
case MT_EXPLOSIONRING:
case MT_SCATTERRING:
case MT_GRENADERING:
case MT_BOUNCEPICKUP:
case MT_RAILPICKUP:
case MT_AUTOPICKUP:
case MT_EXPLODEPICKUP:
case MT_SCATTERPICKUP:
case MT_GRENADEPICKUP:
case MT_NIGHTSWING:
case MT_BLUEORB:
case MT_BLACKORB:
case MT_WHITEORB:
case MT_YELLOWORB:
case MT_GREENORB:
case MT_THOK:
case MT_GHOST:
mobj->flags |= MF_NOCLIPHEIGHT;
default:
break;
}
// set subsector and/or block links
P_SetThingPosition(mobj);
mobj->floorz = mobj->subsector->sector->floorheight;
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
if (z == ONFLOORZ)
{
// defaults onground
mobj->eflags |= MFE_ONGROUND;
if ((mobj->type == MT_RING || mobj->type == MT_COIN || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING ||
mobj->type == MT_BOUNCERING || mobj->type == MT_RAILRING || mobj->type == MT_AUTOMATICRING ||
mobj->type == MT_EXPLOSIONRING || mobj->type == MT_SCATTERRING || mobj->type == MT_GRENADERING ||
mobj->type == MT_BOUNCEPICKUP || mobj->type == MT_RAILPICKUP || mobj->type == MT_AUTOPICKUP ||
mobj->type == MT_EXPLODEPICKUP || mobj->type == MT_SCATTERPICKUP || mobj->type == MT_GRENADEPICKUP
|| mobj->type == MT_EMMY)
&& mobj->flags & MF_AMBUSH)
mobj->z = mobj->floorz + 32*FRACUNIT;
else
mobj->z = mobj->floorz;
}
else if (z == ONCEILINGZ)
mobj->z = mobj->ceilingz - mobj->height;
else
mobj->z = z;
if (!(mobj->type & MF_NOTHINK))
{
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
P_AddThinker(&mobj->thinker);
}
// Call action functions when the state is set
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
{
if (levelloading)
{
// Cache actions in a linked list
// with function pointer, and
// var1 & var2, which will be executed
// when the level finishes loading.
P_AddCachedAction(mobj, mobj->info->spawnstate);
}
else
{
var1 = st->var1;
var2 = st->var2;
st->action.acp1(mobj);
}
}
if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP))
P_CheckGravity(mobj, false);
// Make sure scale matches destscale when spawned
P_SetScale(mobj, mobj->destscale);
return mobj;
}
|
|
p_polyobj.c/p_polyobj.h
BYTEANGLEMUL
= (ANGLE_11hh
/8)
- = 134217728/8
- = 16777216 (or 256*65536)
POLYOBJ_ANCHOR_DOOMEDNUM
= 760 (PolyObject Anchor)
POLYOBJ_SPAWN_DOOMEDNUM
= 761 (PolyObject Spawn Point)
POLYOBJ_SPAWNCRUSH_DOOMEDNUM
= 762 (PolyObject Spawn Point (Crush))
POLYOBJ_START_LINE
= 20 (Linedef Type 20, PolyObject - First Line)
POLYOBJ_EXPLICIT_LINE
= 21 (Linedef Type 21, PolyObject - Explicitly Include Line)
POLYINFO_SPECIALNUM
= 22 (Linedef Type 22, PolyObject - Parameters)
PolyObject Flags
PolyObject Flags
|
Flag Name
|
Value (Hex)
|
Value (Dec)
|
Description
|
POF_CLIPLINES
|
1
|
1
|
Test against lines for collision
|
POF_CLIPPLANES
|
2
|
2
|
Test against tops and bottoms for collision
|
POF_SOLID
|
3
|
3
|
(POF_CLIPLINES + POF_CLIPPLANES ) Clips things
|
POF_TESTHEIGHT
|
4
|
4
|
Test line collision with heights
|
POF_RENDERSIDES
|
8
|
8
|
Render the sides
|
POF_RENDERTOP
|
10
|
16
|
Render the top
|
POF_RENDERBOTTOM
|
20
|
32
|
Render the bottom
|
POF_RENDERPLANES
|
30
|
48
|
(POF_RENDERTOP + POF_RENDERBOTTOM ) Render top and bottom
|
POF_RENDERALL
|
38
|
56
|
(POF_RENDERSIDES + POF_RENDERPLANES ) Renders everything
|
POF_INVERT
|
40
|
64
|
Inverts collision (like a cage)
|
POF_INVERTPLANES
|
80
|
128
|
Render inside planes
|
POF_INVERTPLANESONLY
|
100
|
256
|
Only render inside planes
|
POF_PUSHABLESTOP
|
200
|
512
|
Pushables (e.g. Gargoyle) will stop movement
|
POF_LDEXEC
|
400
|
1024
|
This PO triggers a linedef executor
|
POF_ONESIDE
|
800
|
2048
|
Only use the first side of the linedef
|
POF_NOSPECIALS
|
1000
|
4096
|
Don't apply sector specials
|
Linedef Type 20 Flag settings
Linedef Flags
|
PolyObject Flags
|
(none)
|
POF_SOLID ; POF_TESTHEIGHT ; POF_RENDERSIDES
|
Effect 1
|
+ POF_ONESIDE
|
Effect 2
|
- POF_SOLID
|
Effect 3
|
+ POF_PUSHABLESTOP
|
Effect 4
|
+ POF_RENDERPLANES
|
Effect 5
|
- POF_CLIPPLANES
|
Not Climbable
|
+ POF_LDEXEC
|
p_saveg.c
Sector Data
Sector Data flags
|
Decimal
|
Hexadecimal
|
Flag Name
|
Description
|
1
|
0x01
|
SD_FLOORHT
|
Floor Height Data
|
2
|
0x02
|
SD_CEILHT
|
Ceiling Height Data
|
4
|
0x04
|
SD_FLOORPIC
|
Floor Flat Data
|
8
|
0x08
|
SD_CEILPIC
|
Ceiling Flat Data
|
16
|
0x10
|
SD_LIGHT
|
Sector Brightness Data
|
32
|
0x20
|
SD_SPECIAL
|
Sector Specials Data
|
64
|
0x40
|
SD_DIFF2
|
Sector Diff2 Data (Set if any of the Sector Diff2 flags have been set)
|
Sector Diff2 flags
|
Decimal
|
Hexadecimal
|
Flag Name
|
Description
|
1
|
0x01
|
SD_FXOFFS
|
Floor Flat X Offset Data (Set if Linedef type 7, Flat Alignment has been used to change this offset)
|
2
|
0x02
|
SD_FYOFFS
|
Floor Flat Y Offset Data (Set if Linedef type 7, Flat Alignment has been used to change this offset)
|
4
|
0x04
|
SD_CXOFFS
|
Ceiling Flat X Offset Data (Set if Linedef type 7, Flat Alignment has been used to change this offset)
|
8
|
0x08
|
SD_CYOFFS
|
Ceiling Flat Y Offset Data (Set if Linedef type 7, Flat Alignment has been used to change this offset)
|
16
|
0x10
|
SD_TAG
|
Sector Tag Data (Set if the sector has a sector tag)
|
32
|
0x20
|
SD_FLOORANG
|
Floor Flat Angle Data (Set if Linedef type 7, Flat Alignment has been used to change the angle)
|
64
|
0x40
|
SD_CEILANG
|
Ceiling Flat Angle Data (Set if Linedef type 7, Flat Alignment has been used to change the angle)
|
Linedef Data
Linedef Data flags
|
Decimal
|
Hexadecimal
|
Flag Name
|
Description
|
1
|
0x01
|
LD_FLAG
|
Linedef Flags Data
|
2
|
0x02
|
LD_SPECIAL
|
Linedef Special Data
|
8
|
0x08
|
LD_S1TEXOFF
|
Front Side Texture Offset Data
|
16
|
0x10
|
LD_S1TOPTEX
|
Front Side Upper Texture Data
|
32
|
0x20
|
LD_S1BOTTEX
|
Front Side Lower Texture Data
|
64
|
0x40
|
LD_S1MIDTEX
|
Front Side Middle Texture Data
|
128
|
0x80
|
LD_DIFF2
|
Linedef Diff2 Data (Set if any of the Linedef Diff2 flags have been set)
|
Linedef Diff2 flags
|
Decimal
|
Hexadecimal
|
Flag Name
|
Description
|
1
|
0x01
|
LD_S2TEXOFF
|
Back Side Texture Offset Data
|
2
|
0x02
|
LD_S2TOPTEX
|
Back Side Upper Texture Data
|
4
|
0x04
|
LD_S2BOTTEX
|
Back Side Lower Texture Data
|
8
|
0x08
|
LD_S2MIDTEX
|
Back Side Middle Texture Data
|
mobj_diff_t (Mobj Data)
mobj_diff_t
|
Decimal
|
Hexadecimal
|
Flag Name
|
Description
|
1
|
0x0000001
|
MD_SPAWNPOINT
|
Mobj Spawnpoint Data
|
2
|
0x0000002
|
MD_POS
|
Mobj Position Data
|
4
|
0x0000004
|
MD_TYPE
|
Mobj Thing Type Number Data
|
8
|
0x0000008
|
MD_MOM
|
Mobj Momentum Data (Set if the mobj is moving)
|
16
|
0x0000010
|
MD_RADIUS
|
Mobj Radius Data (Set if the mobj's radius is changed)
|
32
|
0x0000020
|
MD_HEIGHT
|
Mobj Height Data (Set if the mobj's height is changed)
|
64
|
0x0000040
|
MD_FLAGS
|
Mobj FLAGS Data (Set if the mobj's FLAGS are changed, or if the mobj has MF_TRANSLATION )
|
128
|
0x0000080
|
MD_HEALTH
|
Mobj Health Data (Set if the mobj's health changes)
|
256
|
0x0000100
|
MD_RTIME
|
Mobj Reaction time Data (Set if the mobj's reaction time changes)
|
512
|
0x0000200
|
MD_STATE
|
Mobj State Data (Set if the mobj's state changes)
|
1024
|
0x0000400
|
MD_TICS
|
Mobj Tics Data (Set if the mobj's tics change)
|
2048
|
0x0000800
|
MD_SPRITE
|
Mobj Sprite Data (Set if the mobj's sprite changes)
|
4096
|
0x0001000
|
MD_FRAME
|
Mobj Frame Data (Set if the mobj's frame changes)
|
8192
|
0x0002000
|
MD_EFLAGS
|
Mobj Extra Flags Data (Set if the mobj has any extra flags set)
|
16384
|
0x0004000
|
MD_PLAYER
|
Mobj Player Data (Set if the mobj is a Player)
|
32768
|
0x0008000
|
MD_MOVDIR
|
Mobj Movement direction Data
|
65536
|
0x0010000
|
MD_MOVECOUNT
|
Mobj Movecount Data
|
131072
|
0x0020000
|
MD_THRESHOLD
|
Mobj Threshold Data
|
262144
|
0x0040000
|
MD_LASTLOOK
|
Mobj Lastlook Data (Set if the mobj's lastlook is not -1)
|
524288
|
0x0080000
|
MD_TARGET
|
Mobj Target Data (Set if the mobj has a target)
|
1048576
|
0x0100000
|
MD_TRACER
|
Mobj Tracer Data (Set if the mobj has a tracer)
|
2097152
|
0x0200000
|
MD_FRICTION
|
Mobj Friction Data (Set if the mobj's friction is not ORIG_FRICTION )
|
4194304
|
0x0400000
|
MD_MOVEFACTOR
|
Mobj Movement factor Data (Set if the mobj's movefactor is not ORIG_FRICTION_FACTOR )
|
8388608
|
0x0800000
|
MD_FLAGS2
|
Mobj FLAGS2 Data
|
16777216
|
0x1000000
|
MD_FUSE
|
Mobj Fuse Data
|
33554432
|
0x2000000
|
MD_WATERTOP
|
Mobj Watertop Data
|
67108864
|
0x4000000
|
MD_WATERBOTTOM
|
Mobj Waterbottom Data
|
134217728
|
0x8000000
|
MD_SCALE
|
Mobj Scale Data (Set if the mobj's scale is not 100)
|
268435456
|
0x10000000
|
MD_DSCALE
|
Mobj Destination scale Data (Set if the mobj's destscale is not the same as it's scale)
|
536870912
|
0x20000000
|
MD_BLUEFLAG
|
Blue Flag Data (Set if the mobj is a CTF Blue Flag)
|
1073741824
|
0x40000000
|
MD_REDFLAG
|
Red Flag Data (Set if the mobj is a CTF Red Flag)
|
p_setup.c
P_SpawnSecretItems
Position of RedXVI:
x = 04220000000
*-1
- = 574619648*-1
- = -8768
y = 0554000000
*-1
- = 95420416*-1
- = -1456
z = ONFLOORZ
Code - P_SpawnSecretItems
|
|
void P_SpawnSecretItems(boolean loademblems)
{
// Now let's spawn those funky emblem things! Tails 12-08-2002
if (netgame || multiplayer || (modifiedgame && !savemoddata) || timeattacking) // No cheating!!
return;
if (loademblems)
P_SpawnEmblems();
if(gamemap == 11)
P_SpawnMobj(04220000000*-1, 0554000000*-1, ONFLOORZ, MT_PXVI)->angle = ANGLE_270;
}
|
|
p_spec.c/p_spec.h
SCROLL_SHIFT
= 5 (Amount (dx, dy) vector linedef is shifted right to get scroll amount)
CARRYFACTOR
= (3*FRACUNIT
)/32
- = 3 fracunits/32 tics (Factor to scale scrolling effect into mobj-carrying properties = 3/32)
MAXANIMS
= 64
Linedef Types 489 and 490
Linedef Flags
|
Linedef type 489
|
Linedef type 490
|
None
|
+ POF_NOSPECIALS ; - POF_RENDERALL ; - POF_SOLID
|
- POF_NOSPECIALS ; + POF_RENDERALL ; + POF_SOLID
|
Not Climbable
|
+ POF_NOSPECIALS ; - POF_RENDERALL
|
- POF_NOSPECIALS ; + POF_RENDERALL
|
VDOORSPEED
= FRACUNIT*2
/NEWTICRATERATIO
- =
FRACUNIT
*2
- = 2 fracunits/1 tic
length
= Linedef's length
friction
= (0x1EB8
*length
)/0x80
+ 0xD000
- = (7864*
length
)/128 + 53248
- = (983*
length
)/16 + 53248
If friction
> ORIG_FRICTION
(Ice):
movefactor
= ((0x10092
- friction
)*(0x70
))/0x158
- = ((65682 -
friction
)*(112))/344
- = ((65682 -
friction
)*14)/43
If friction
<= ORIG_FRICTION
(Sludge):
movefactor
= ((friction
- 0xDB34
)*(0xA
))/0x80
- = ((
friction
- 56116)*(10))/128
- = ((
friction
- 56116)*5)/64
if (friction
> FRACUNIT
)
friction
= FRACUNIT
;
if (friction
< 0)
friction
= 0;
if (movefactor
< 32)
movefactor
= 32;
Linedef length
|
friction
|
movefactor
|
1
|
53309.4375
|
-219.2626953125 = 32
|
50
|
56319.875
|
15.927734375 = 32
|
53.34852492~
|
56525.6
|
32
|
100
|
59391.75
|
255.91796875
|
100.004069~
|
59392 (ORIG_FRICTION )
|
255.9375
|
101
|
59453.1875
|
2027.98546511~
|
150
|
62463.625
|
495.908203125
|
200
|
65535.5
|
47.69767442~
|
200.00813835~
|
65536 (FRACUNIT )
|
47.53488372~
|
PUSH_FACTOR
= 7
GLOWSPEED
= 8
STROBEBRIGHT
= 5
FASTDARK
= 15
SLOWDARK
= 35
CEILSPEED
= (FRACUNIT
/NEWTICRATERATIO
)
- =
FRACUNIT
- = 1 fracunit/ 1 tic
ELEVATORSPEED
= (FRACUNIT
*4/NEWTICRATERATIO
)
- =
FRACUNIT
*4
- = 4 fracunits/1 tic
FLOORSPEED
= (FRACUNIT
/NEWTICRATERATIO
)
- =
FRACUNIT
- = 1 fracunit/1 tic
ORIG_FRICTION
= (0xE8
<< (FRACBITS
-8))
- = 232 * 2^16-8
- = 232 * 2^8
- = 232 * 256
- = 59392
ORIG_FRICTION_FACTOR
= (8 << (FRACBITS
-8))
- = 8 * 2^16-8
- = 8 * 2^8
- = 8 * 256
- = 2048
Add_Pusher
<<(FRACBITS-PUSH_FACTOR)
- = *2^(16-7)
- = *2^9
- = *512
<<(FRACBITS+1)
- = *2^(16+1)
- = *2^17
- = *131072
Code - Add_Pusher
|
|
/** Adds a pusher.
*
* \param type Type of push/pull effect.
* \param x_mag X magnitude.
* \param y_mag Y magnitude.
* \param source For a point pusher/puller, the source object.
* \param affectee Target sector.
* \param referrer What sector set it
* \sa T_Pusher, P_GetPushThing, P_SpawnPushers
*/
static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider)
{
pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL);
p->thinker.function.acp1 = (actionf_p1)T_Pusher;
p->source = source;
p->type = type;
p->x_mag = x_mag>>FRACBITS;
p->y_mag = y_mag>>FRACBITS;
p->exclusive = exclusive;
p->slider = slider;
if (referrer != -1)
{
p->roverpusher = true;
p->referrer = referrer;
}
else
p->roverpusher = false;
// "The right triangle of the square of the length of the hypotenuse is equal to the sum of the squares of the lengths of the other two sides."
// "Bah! Stupid brains! Don't you know anything besides the Pythagorean Theorem?" - Earthworm Jim
if (type == p_downcurrent || type == p_upcurrent || type == p_upwind || type == p_downwind)
p->magnitude = P_AproxDistance(p->x_mag,p->y_mag)<<(FRACBITS-PUSH_FACTOR);
else
p->magnitude = P_AproxDistance(p->x_mag,p->y_mag);
if (source) // point source exist?
{
// where force goes to zero
if (type == p_push)
p->radius = AngleFixed(source->angle);
else
p->radius = (p->magnitude)<<(FRACBITS+1);
p->x = p->source->x;
p->y = p->source->y;
p->z = p->source->z;
}
p->affectee = affectee;
P_AddThinker(&p->thinker);
}
|
|
T_Pusher
Touching the ground (while in FOF):
- Wind - Half force
- Current - Full force
Anywhere else in FOF:
- Wind - Full force
- Current - Full force
<<(FRACBITS-PUSH_FACTOR)
- = *2^(16-7)
- = *2^9
- = *512
Code - T_Pusher
|
|
/** Applies a pusher to all affected objects.
*
* \param p Thinker for the pusher effect.
* \todo Split up into multiple functions.
* \sa Add_Pusher, PIT_PushThing
*/
void T_Pusher(pusher_t *p)
{
sector_t *sec;
mobj_t *thing;
msecnode_t *node;
INT32 xspeed = 0,yspeed = 0;
INT32 xl, xh, yl, yh, bx, by;
INT32 radius;
//INT32 ht = 0;
boolean inFOF;
boolean touching;
boolean foundfloor = false;
boolean moved;
xspeed = yspeed = 0;
sec = sectors + p->affectee;
// Be sure the special sector type is still turned on. If so, proceed.
// Else, bail out; the sector type has been changed on us.
if (p->roverpusher)
{
sector_t *referrer = §ors[p->referrer];
if (GETSECSPECIAL(referrer->special, 3) == 2
|| GETSECSPECIAL(referrer->special, 3) == 3)
foundfloor = true;
}
else if (!(GETSECSPECIAL(sec->special, 3) == 2
|| GETSECSPECIAL(sec->special, 3) == 3))
return;
if (p->roverpusher && foundfloor == false) // Not even a 3d floor has the PUSH_MASK.
return;
// For constant pushers (wind/current) there are 3 situations:
//
// 1) Affected Thing is above the floor.
//
// Apply the full force if wind, no force if current.
//
// 2) Affected Thing is on the ground.
//
// Apply half force if wind, full force if current.
//
// 3) Affected Thing is below the ground (underwater effect).
//
// Apply no force if wind, full force if current.
//
// Apply the effect to clipped players only for now.
//
// In Phase II, you can apply these effects to Things other than players.
if (p->type == p_push)
{
// Seek out all pushable things within the force radius of this
// point pusher. Crosses sectors, so use blockmap.
tmpusher = p; // MT_PUSH/MT_PULL point source
radius = p->radius; // where force goes to zero
tmbbox[BOXTOP] = p->y + radius;
tmbbox[BOXBOTTOM] = p->y - radius;
tmbbox[BOXRIGHT] = p->x + radius;
tmbbox[BOXLEFT] = p->x - radius;
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++)
P_BlockThingsIterator(bx,by, PIT_PushThing);
return;
}
// constant pushers p_wind and p_current
node = sec->touching_thinglist; // things touching this sector
for (; node; node = node->m_snext)
{
thing = node->m_thing;
if (thing->flags & (MF_NOGRAVITY | MF_NOCLIP)
&& !(thing->type == MT_SMALLBUBBLE
|| thing->type == MT_MEDIUMBUBBLE
|| thing->type == MT_EXTRALARGEBUBBLE))
continue;
if (!(thing->flags & MF_PUSHABLE) && !(thing->type == MT_PLAYER
|| thing->type == MT_SMALLBUBBLE
|| thing->type == MT_MEDIUMBUBBLE
|| thing->type == MT_EXTRALARGEBUBBLE
|| thing->type == MT_LITTLETUMBLEWEED
|| thing->type == MT_BIGTUMBLEWEED))
continue;
if (thing->flags2 & MF2_PUSHED)
continue;
if (thing->player && (thing->player->pflags & PF_ROPEHANG || thing->player->pflags & PF_MINECART))
continue;
if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics))
continue;
inFOF = touching = moved = false;
// Find the area that the 'thing' is in
if (p->roverpusher)
{
sector_t *referrer = §ors[p->referrer];
INT32 special;
special = GETSECSPECIAL(referrer->special, 3);
if (!(special == 2 || special == 3))
return;
if (thing->eflags & MFE_VERTICALFLIP)
{
if (referrer->floorheight > thing->z + thing->height
|| referrer->ceilingheight < (thing->z + (thing->height >> 1)))
return;
if (thing->z < referrer->floorheight)
touching = true;
if (thing->z + (thing->height >> 1) > referrer->floorheight)
inFOF = true;
}
else
{
if (referrer->ceilingheight < thing->z || referrer->floorheight > (thing->z + (thing->height >> 1)))
return;
if (thing->z + thing->height > referrer->ceilingheight)
touching = true;
if (thing->z + (thing->height >> 1) < referrer->ceilingheight)
inFOF = true;
}
}
else // Treat the entire sector as one big FOF
{
if (thing->z == thing->subsector->sector->floorheight)
touching = true;
else if (p->type != p_current)
inFOF = true;
}
if (!touching && !inFOF) // Object is out of range of effect
continue;
if (p->type == p_wind)
{
if (touching) // on ground
{
xspeed = (p->x_mag)>>1; // half force
yspeed = (p->y_mag)>>1;
moved = true;
}
else if (inFOF)
{
xspeed = (p->x_mag); // full force
yspeed = (p->y_mag);
moved = true;
}
}
else if (p->type == p_upwind)
{
if (touching) // on ground
{
thing->momz += (p->magnitude)>>1;
moved = true;
}
else if (inFOF)
{
thing->momz += p->magnitude;
moved = true;
}
}
else if (p->type == p_downwind)
{
if (touching) // on ground
{
thing->momz -= (p->magnitude)>>1;
moved = true;
}
else if (inFOF)
{
thing->momz -= p->magnitude;
moved = true;
}
}
else // p_current
{
if (!touching && !inFOF) // Not in water at all
xspeed = yspeed = 0; // no force
else // underwater / touching water
{
if (p->type == p_upcurrent)
thing->momz += p->magnitude;
else if (p->type == p_downcurrent)
thing->momz -= p->magnitude;
else
{
xspeed = p->x_mag; // full force
yspeed = p->y_mag;
}
moved = true;
}
}
if (p->type != p_downcurrent && p->type != p_upcurrent
&& p->type != p_upwind && p->type != p_downwind)
{
thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR);
thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR);
if (thing->player)
{
thing->player->cmomx += xspeed<<(FRACBITS-PUSH_FACTOR);
thing->player->cmomy += yspeed<<(FRACBITS-PUSH_FACTOR);
thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION);
thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION);
}
// Tumbleweeds bounce a bit...
if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED)
thing->momz += P_AproxDistance(xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)) >> 2;
}
if (moved)
{
if (p->slider && thing->player)
{
boolean jumped = (thing->player->pflags & PF_JUMPED);
P_ResetPlayer (thing->player);
if (jumped)
thing->player->pflags |= PF_JUMPED;
thing->player->pflags |= PF_SLIDING;
P_SetPlayerMobjState (thing, thing->info->painstate); // Whee!
thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (splitscreen && thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;
}
if (p->exclusive)
thing->flags2 |= MF2_PUSHED;
}
}
}
|
|
p_user.c
MAXBOB
= 0x10
<<FRACBITS
- = 16 * 2^16
- = 16 * 65536
- = 16*
FRACUNIT
- = 16 fracunits (Maximum height the camera "bobs" when walking/running with 1st person camera)
SPACESPECIAL
= 12 (Sector Type 12, Space Countdown)
MAXDRILLSPEED
= 14000 (Maximum drilling speed as NiGHTS Super Sonic)
MAXNORMALSPEED
= 6000 (Maximum flying speed as NiGHTS Super Sonic)
P_GetPlayerHeight
Height = MT_PLAYER
's Height
- = 56 fracunits
Code - P_GetPlayerHeight
|
|
//
// P_GetPlayerHeight
//
// Returns the height
// of the player.
//
fixed_t P_GetPlayerHeight(player_t *player)
{
return FIXEDSCALE(player->mo->info->height, player->mo->scale);
}
|
|
P_GetPlayerSpinHeight
Height = MT_PLAYER
's Height
/7*(FRACUNIT
/4)
- = 56/1.75
- = 32 fracunits
Code - P_GetPlayerSpinHeight
|
|
//
// P_GetPlayerSpinHeight
//
// Returns the 'spin height'
// of the player.
//
fixed_t P_GetPlayerSpinHeight(player_t *player)
{
return FixedDiv(FIXEDSCALE(player->mo->info->height, player->mo->scale),7*(FRACUNIT/4));
}
|
|
P_DoJump
Momz = (jumpfactor
*momz)/100
- = momz*(
jumpfactor
/100)
- Underwater: Momz * 0.585
- Quicksand: Momz/2
- 2D Mode: Momz*1.1
Jump Momentum
|
|
Z Momentum (fracunits)
|
Condition
|
Normal
|
Underwater
|
Quicksand
|
2D Mode
|
2D Mode + Underwater
|
2D Mode + Quicksand
|
Default
|
(jumpfactor *(39*(FRACUNIT /4)))/100*FRACUNIT =9.75*(jumpfactor /100)
|
(jumpfactor *(39*(FRACUNIT /4)*(117/200)))/100*FRACUNIT =(9.75*0.585)*(jumpfactor /100) =5.70375*(jumpfactor /100)
|
(jumpfactor *(39*(FRACUNIT /4)>>1))/100*FRACUNIT =(9.75/2)*(jumpfactor /100) =4.875*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(39*(FRACUNIT /4)))/100*FRACUNIT =9.75*(jumpfactor /100)*1.1 =10.725*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(39*(FRACUNIT /4)*(117/200)))/100*FRACUNIT =(9.75*0.585)*((jumpfactor *1.1)/100) =5.70375*(jumpfactor /100)*1.1 =6.274125*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(39*(FRACUNIT /4)>>1))/100*FRACUNIT =(9.75/2)*(jumpfactor /100) =4.875*(jumpfactor /100)*1.1 =5.3625*(jumpfactor /100)
|
Jumping from being carried (PF_CARRIED /PF_ITEMHANG )
|
(jumpfactor *(9*FRACUNIT ))/100*FRACUNIT =9*(jumpfactor /100)
|
(jumpfactor *(9*FRACUNIT *(117/200)))/100*FRACUNIT =(9*0.585)*(jumpfactor /100) =5.265*(jumpfactor /100)
|
(jumpfactor *(9*FRACUNIT >>1))/100*FRACUNIT =(9/2)*(jumpfactor /100) =4.5*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(9*FRACUNIT ))/100*FRACUNIT =9*(jumpfactor /100)*1.1 =9.9*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(9*FRACUNIT *(117/200)))/100*FRACUNIT =(9.*0.585)*((jumpfactor *1.1)/100) =5.265*(jumpfactor /100)*1.1 =5.7915*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(9*FRACUNIT >>1))/100*FRACUNIT =(9/2)*(jumpfactor /100) =4.5*(jumpfactor /100)*1.1 =4.95*(jumpfactor /100)
|
Jumping from Rope Hang (PF_ROPEHANG )
|
(jumpfactor *(12*FRACUNIT ))/100*FRACUNIT =12*(jumpfactor /100)
|
(jumpfactor *(12*FRACUNIT *(117/200)))/100*FRACUNIT =(12*0.585)*(jumpfactor /100) =7.02*(jumpfactor /100)
|
(jumpfactor *(12*FRACUNIT >>1))/100*FRACUNIT =(12/2)*(jumpfactor /100) =6*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT ))/100*FRACUNIT =12*(jumpfactor /100)*1.1 =13.2*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT *(117/200)))/100*FRACUNIT =(12*0.585)*((jumpfactor *1.1)/100) =7.02*(jumpfactor /100)*1.1 =7.722*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT >>1))/100*FRACUNIT =(12/2)*(jumpfactor /100) =6*(jumpfactor /100)*1.1 =6.6*(jumpfactor /100)
|
NiGHTS Mode
|
(jumpfactor *(24*FRACUNIT ))/100*FRACUNIT =24*(jumpfactor /100)
|
(jumpfactor *(24*FRACUNIT *(117/200)))/100*FRACUNIT =(24*0.585)*(jumpfactor /100) =14.04*(jumpfactor /100)
|
(jumpfactor *(24*FRACUNIT >>1))/100*FRACUNIT =(24/2)*(jumpfactor /100) =12*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(24*FRACUNIT ))/100*FRACUNIT =24*(jumpfactor /100)*1.1 =26.4*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(24*FRACUNIT *(117/200)))/100*FRACUNIT =(24*0.585)*((jumpfactor *1.1)/100) =14.04*(jumpfactor /100)*1.1 =15.444*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(24*FRACUNIT >>1))/100*FRACUNIT =(24/2)*(jumpfactor /100) =12*(jumpfactor /100)*1.1 =13.2*(jumpfactor /100)
|
CA_DOUBLEJUMP + CA2_MULTIABILITY
|
(jumpfactor *(23*(FRACUNIT /2)))/100*FRACUNIT =11.5*(jumpfactor /100)
|
(jumpfactor *(23*(FRACUNIT /2)*(117/200)))/100*FRACUNIT =(11.5*0.585)*(jumpfactor /100) =6.7275*(jumpfactor /100)
|
(jumpfactor *(23*(FRACUNIT /2)>>1))/100*FRACUNIT =(11.5/2)*(jumpfactor /100) =5.75*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(23*(FRACUNIT /2)))/100*FRACUNIT =11.5*(jumpfactor /100)*1.1 =12.65*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(23*(FRACUNIT /2)*(117/200)))/100*FRACUNIT =(11.5*0.585)*((jumpfactor *1.1)/100) =6.7275*(jumpfactor /100)*1.1 =7.40025*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(23*(FRACUNIT /2)>>1))/100*FRACUNIT =(11.5/2)*(jumpfactor /100) =5.75*(jumpfactor /100)*1.1 =6.325*(jumpfactor /100)
|
CA_FLOAT /CA_SLOWFALL + CA2_MULTIABILITY
|
(jumpfactor *(12*FRACUNIT ))/100*FRACUNIT =12*(jumpfactor /100)
|
(jumpfactor *(12*FRACUNIT *(117/200)))/100*FRACUNIT =(12*0.585)*(jumpfactor /100) =7.02*(jumpfactor /100)
|
(jumpfactor *(12*FRACUNIT >>1))/100*FRACUNIT =(12/2)*(jumpfactor /100) =6*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT ))/100*FRACUNIT =12*(jumpfactor /100)*1.1 =13.2*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT *(117/200)))/100*FRACUNIT =(12*0.585)*((jumpfactor *1.1)/100) =7.02*(jumpfactor /100)*1.1 =7.722*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(12*FRACUNIT >>1))/100*FRACUNIT =(12/2)*(jumpfactor /100) =6*(jumpfactor /100)*1.1 =6.6*(jumpfactor /100)
|
Default (Super)
|
(jumpfactor *(13*FRACUNIT ))/100*FRACUNIT =13*(jumpfactor /100)
|
(jumpfactor *(13*FRACUNIT *(117/200)))/100*FRACUNIT =(13*0.585)*(jumpfactor /100) =7.605*(jumpfactor /100)
|
(jumpfactor *(13*FRACUNIT >>1))/100*FRACUNIT =(13/2)*(jumpfactor /100) =6.5*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(13*FRACUNIT ))/100*FRACUNIT =13*(jumpfactor /100)*1.1 =14.3*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(13*FRACUNIT *(117/200)))/100*FRACUNIT =(13*0.585)*((jumpfactor *1.1)/100) =7.605*(jumpfactor /100)*1.1 =8.3655*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(13*FRACUNIT >>1))/100*FRACUNIT =(13/2)*(jumpfactor /100) =6.5*(jumpfactor /100)*1.1 =7.15*(jumpfactor /100)
|
CA_FLOAT (Super)
|
(jumpfactor *(28*FRACUNIT ))/100*FRACUNIT =28*(jumpfactor /100)
|
(jumpfactor *(28*FRACUNIT *(117/200)))/100*FRACUNIT =(28*0.585)*(jumpfactor /100) =16.38*(jumpfactor /100)
|
(jumpfactor *(28*FRACUNIT >>1))/100*FRACUNIT =(28/2)*(jumpfactor /100) =14*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(28*FRACUNIT ))/100*FRACUNIT =28*(jumpfactor /100)*1.1 =30.8*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(28*FRACUNIT *(117/200)))/100*FRACUNIT =(28*0.585)*((jumpfactor *1.1)/100) =16.38*(jumpfactor /100)*1.1 =18.018*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(28*FRACUNIT >>1))/100*FRACUNIT =(28/2)*(jumpfactor /100) =14*(jumpfactor /100)*1.1 =15.4*(jumpfactor /100)
|
CA_SLOWFALL (Super)
|
(jumpfactor *(37*(FRACUNIT /2)))/100*FRACUNIT =18.5*(jumpfactor /100)
|
(jumpfactor *(37*(FRACUNIT /2)*(117/200)))/100*FRACUNIT =(18.5*0.585)*(jumpfactor /100) =10.8225*(jumpfactor /100)
|
(jumpfactor *(37*(FRACUNIT /2)>>1))/100*FRACUNIT =(18.5/2)*(jumpfactor /100) =9.25*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(37*(FRACUNIT /2)))/100*FRACUNIT =18.5*(jumpfactor /100)*1.1 =20.35*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(37*(FRACUNIT /2)*(117/200)))/100*FRACUNIT =(18.5*0.585)*((jumpfactor *1.1)/100) =10.8225*(jumpfactor /100)*1.1 =11.90475*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(37*(FRACUNIT /2)>>1))/100*FRACUNIT =(18.5/2)*(jumpfactor /100) =9.25*(jumpfactor /100)*1.1 =10.175*(jumpfactor /100)
|
CA_FLOAT + CA2_MULTIABILITY (Super)
|
(jumpfactor *(30*FRACUNIT ))/100*FRACUNIT =30*(jumpfactor /100)
|
(jumpfactor *(30*FRACUNIT *(117/200)))/100*FRACUNIT =(30*0.585)*(jumpfactor /100) =17.55*(jumpfactor /100)
|
(jumpfactor *(30*FRACUNIT >>1))/100*FRACUNIT =(30/2)*(jumpfactor /100) =15*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(30*FRACUNIT ))/100*FRACUNIT =30*(jumpfactor /100)*1.1 =33*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(30*FRACUNIT *(117/200)))/100*FRACUNIT =(30*0.585)*((jumpfactor *1.1)/100) =17.55*(jumpfactor /100)*1.1 =19.305*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(30*FRACUNIT >>1))/100*FRACUNIT =(30/2)*(jumpfactor /100) =15*(jumpfactor /100)*1.1 =16.5*(jumpfactor /100)
|
CA_SLOWFALL + CA2_MULTIABILITY (Super)
|
(jumpfactor *(37*(FRACUNIT /2)+2*FRACUNIT ))/100*FRACUNIT =20.5*(jumpfactor /100)
|
(jumpfactor *((37*(FRACUNIT /2)+2*FRACUNIT )*(117/200)))/100*FRACUNIT =(20.5*0.585)*(jumpfactor /100) =11.9925*(jumpfactor /100)
|
(jumpfactor *((37*(FRACUNIT /2)+2*FRACUNIT )>>1))/100*FRACUNIT =(20.5/2)*(jumpfactor /100) =10.25*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*(37*(FRACUNIT /2)+2*FRACUNIT ))/100*FRACUNIT =20.5*(jumpfactor /100)*1.1 =22.55*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*((37*(FRACUNIT /2)+2*FRACUNIT )*(117/200)))/100*FRACUNIT =(20.5*0.585)*((jumpfactor *1.1)/100) =11.9925*(jumpfactor /100)*1.1 =13.19175*(jumpfactor /100)
|
((jumpfactor +(jumpfactor /10))*((37*(FRACUNIT /2)+2*FRACUNIT )>>1))/100*FRACUNIT =(20.5/2)*(jumpfactor /100) =10.25*(jumpfactor /100)*1.1 =11.275*(jumpfactor /100)
|
Code - P_DoJump
|
|
//
// P_DoJump
//
// Jump routine for the player
//
void P_DoJump(player_t *player, boolean soundandstate)
{
fixed_t factor;
if (player->pflags & PF_STASIS || (player->powers[pw_nocontrol] && player->powers[pw_nocontrol] < 65536))
return;
if (!player->jumpfactor)
return;
if (player->powers[pw_ingoop])
return;
if (player->climbing)
{
// Jump this high.
if (player->powers[pw_super])
player->mo->momz = 5*FRACUNIT;
else if (player->mo->eflags & MFE_UNDERWATER)
player->mo->momz = 2*FRACUNIT;
else
player->mo->momz = 15*(FRACUNIT/4);
player->mo->angle = player->mo->angle - ANGLE_180; // Turn around from the wall you were climbing.
if (player == &players[consoleplayer])
localangle = player->mo->angle; // Adjust the local control angle.
else if (splitscreen && player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
player->climbing = 0; // Stop climbing, duh!
P_InstaThrust(player->mo, player->mo->angle, FIXEDSCALE(6*FRACUNIT, player->mo->scale)); // Jump off the wall.
}
else if (!(player->pflags & PF_JUMPED)) // Spin Attack
{
if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1)
return;
// Jump this high.
if (player->pflags & PF_CARRIED)
{
player->mo->momz = 9*FRACUNIT;
player->pflags &= ~PF_CARRIED;
}
else if (player->pflags & PF_ITEMHANG)
{
player->mo->momz = 9*FRACUNIT;
player->pflags &= ~PF_ITEMHANG;
}
else if (player->pflags & PF_ROPEHANG)
{
player->mo->momz = 12*FRACUNIT;
player->pflags &= ~PF_ROPEHANG;
P_SetTarget(&player->mo->tracer, NULL);
}
else if (maptol & TOL_NIGHTS)
player->mo->momz = 24*FRACUNIT;
else if (player->powers[pw_super])
{
if (player->charability == CA_FLOAT)
player->mo->momz = 28*FRACUNIT; //Obscene jump height anyone?
else if (player->charability == CA_SLOWFALL)
player->mo->momz = 37*(FRACUNIT/2); //Less obscene because during super, floating propells oneself upward.
else // Default super jump momentum.
player->mo->momz = 13*FRACUNIT;
// Add a boost for super characters with float/slowfall and multiability.
if (player->charability2 == CA2_MULTIABILITY &&
(player->charability == CA_FLOAT || player->charability == CA_SLOWFALL))
player->mo->momz += 2*FRACUNIT;
}
else if (player->charability2 == CA2_MULTIABILITY &&
(player->charability == CA_DOUBLEJUMP || player->charability == CA_FLOAT || player->charability == CA_SLOWFALL))
{
// Multiability exceptions, since some abilities cannot effectively use it and need a boost.
if (player->charability == CA_DOUBLEJUMP)
player->mo->momz = 23*(FRACUNIT/2); // Increased jump height instead of infinite jumps.
else if (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)
player->mo->momz = 12*FRACUNIT; // Increased jump height due to ineffective repeat.
}
else
player->mo->momz = 39*(FRACUNIT/4); // Default jump momentum.
// Reduce player momz by 58.5% when underwater.
if (player->mo->eflags & MFE_UNDERWATER)
{
player->mo->momz = FixedMul(player->mo->momz, FixedDiv(117*FRACUNIT, 200*FRACUNIT));
}
// Quicksand bitshift reduction.
if (P_InQuicksand(player->mo))
player->mo->momz = player->mo->momz>>1;
player->jumping = 1;
}
factor = player->jumpfactor;
if (twodlevel || (player->mo->flags2 & MF2_TWOD))
factor += player->jumpfactor / 10;
P_SetObjectMomZ(player->mo, FixedDiv(factor*player->mo->momz,100*FRACUNIT), false); // Custom height
// set just an eensy above the ground
if (player->mo->eflags & MFE_VERTICALFLIP)
{
player->mo->z = player->mo->z + (P_GetPlayerHeight(player) - P_GetPlayerSpinHeight(player));
player->mo->z--;
}
else
player->mo->z++;
player->mo->z += player->mo->pmomz; // Solves problem of 'hitting around again after jumping on a moving platform'.
if (!(player->pflags & PF_SPINNING))
P_ResetScore(player);
if (player->pflags & PF_MINECART)
{
player->pflags &= ~PF_MINECART;
P_SetTarget(&player->mo->tracer, NULL);
}
player->pflags |= PF_JUMPED;
if (soundandstate)
{
if (!player->spectator)
S_StartSound(player->mo, sfx_jump); // Play jump sound!
if (!(player->charability2 == CA2_SPINDASH))
P_SetPlayerMobjState(player->mo, S_PLAY_PLG1);
else
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
}
}
|
|
P_DoJumpStuff
CA_THOK
/ CA_HOMINGTHOK
:
Thokking Speed
|
Abilty
|
Regular
|
Underwater
|
SRB1 Mode
|
SRB1 Mode + Underwater
|
CA_THOK
|
actionspd
|
actionspd/2
|
actionspd/2
|
actionspd/4
|
CA_HOMINGTHOK
|
actionspd/3
|
actionspd/6
|
actionspd/6
|
actionspd/12
|
CA_GLIDEANDCLIMB
:
Gliding Speed
|
|
100% Scale (Normal)
|
75% Scale
|
50% Scale
|
25% Scale
|
200% Scale
|
300% Scale
|
x% Scale
|
Normal form
|
actionspd
|
actionspd*(75/100) =actionspd*0.75
|
actionspd*(50/100) =actionspd*0.5
|
actionspd*(25/100) =actionspd*0.25
|
actionspd*(200/100) =actionspd*2
|
actionspd*(300/100) =actionspd*3
|
actionspd*(x/100)
|
Super form
|
actionspd*2
|
actionspd*(75/100)*2 =actionspd*0.75*2 =actionspd*1.5
|
actionspd*(50/100)*2 =actionspd*0.5*2 =actionspd*2
|
actionspd*(25/100)*2 =actionspd*0.25*2 =actionspd*0.5
|
actionspd*(200/100)*2 =actionspd*2*2 =actionspd*4
|
actionspd*(300/100)*2 =actionspd*3*2 =actionspd*6
|
actionspd*(x/100)*2
|
CA_SLOWFALL
:
Z momentum
|
|
Regular gravity
|
Reverse gravity
|
Normal form
|
-gravity *4
|
gravity *4
|
Super form
|
gravity *16
|
-gravity *16
|
Code - P_DoJumpStuff
|
|
//
// P_DoJumpStuff
//
// Handles player jumping
//
static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{
if (player->pflags & PF_STASIS || (player->powers[pw_nocontrol] && player->powers[pw_nocontrol] < 65536))
return;
if (cmd->buttons & BT_JUMP && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !(!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]))
{
// can't jump while in air, can't jump while jumping
if (onground || player->climbing || (player->pflags & PF_CARRIED) || (player->pflags & PF_ITEMHANG) || (player->pflags & PF_ROPEHANG) || (player->pflags & PF_MINECART))
{
P_DoJump(player, true);
player->secondjump = 0;
}
else if ((player->pflags & PF_MACESPIN) && player->mo->tracer)
{
player->pflags &= ~PF_MACESPIN;
player->powers[pw_flashing] = TICRATE/2;
}
else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag)))
{
switch (player->charability)
{
case CA_THOK:
case CA_HOMINGTHOK:
// Now it's Sonic's abilities turn!
if (player->pflags & PF_JUMPED)
{
// If you can turn super and aren't already,
// and you don't have a shield, do it!
if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super]
&& !player->powers[pw_jumpshield] && !player->powers[pw_forceshield]
&& !player->powers[pw_watershield] && !player->powers[pw_ringshield]
&& !player->powers[pw_bombshield] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels
&& ((player->skin == 0) || ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoSuperTransformation(player, false);
}
else // Otherwise, THOK!
{
if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY))
{
mobj_t *item;
// Catapult the player
if ((player->mo->eflags & MFE_UNDERWATER))
P_InstaThrust(player->mo, player->mo->angle, (player->actionspd<<FRACBITS)/2);
else
P_InstaThrust(player->mo, player->mo->angle, player->actionspd<<FRACBITS);
if (maptol & TOL_SRB1)
{
player->mo->momx /= 2;
player->mo->momy /= 2;
}
else if (player->charability == CA_HOMINGTHOK)
{
player->mo->momx /= 3;
player->mo->momy /= 3;
}
if (player->mo->info->attacksound && !player->spectator)
S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound
item = P_SpawnThokMobj(player);
if (item && (player->charflags & SF_GHOSTTHOKITEM))
{
P_SpawnGhostMobj(item);
P_SetMobjState(item, S_DISS);
}
if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED))
{
if (P_LookForEnemies(player))
{
if (player->mo->tracer)
player->homing = 3*TICRATE;
}
}
player->pflags &= ~PF_SPINNING;
player->pflags &= ~PF_STARTDASH;
player->pflags |= PF_THOKKED;
}
}
}
else if (player->powers[pw_jumpshield] && !player->powers[pw_super])
P_DoJumpShield(player);
break;
case CA_FLY:
case CA_SWIM: // Swim
// If you can turn super and aren't already,
// and you don't have a shield, do it!
if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super] && !player->powers[pw_tailsfly]
&& !player->powers[pw_jumpshield] && !player->powers[pw_forceshield]
&& !player->powers[pw_watershield] && !player->powers[pw_ringshield]
&& !player->powers[pw_bombshield] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels
&& player->pflags & PF_JUMPED
&& ((player->skin == 0) || ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoSuperTransformation(player, false);
}
// If currently in the air from a jump, and you pressed the
// button again and have the ability to fly, do so!
else if (!(player->pflags & PF_THOKKED) && !(player->powers[pw_tailsfly]) && (player->pflags & PF_JUMPED) && !(player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER)))
{
P_SetPlayerMobjState(player->mo, S_PLAY_ABL1); // Change to the flying animation
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
player->pflags &= ~PF_JUMPED;
player->pflags &= ~PF_SPINNING;
player->pflags &= ~PF_STARTDASH;
player->pflags |= PF_THOKKED;
}
// If currently flying, give an ascend boost.
else if (player->powers[pw_tailsfly] && !(player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER)))
{
if (!player->fly1)
player->fly1 = 20;
else
player->fly1 = 2;
if (player->charability == CA_SWIM)
player->fly1 /= 2;
}
else if (player->powers[pw_jumpshield] && !player->powers[pw_super])
P_DoJumpShield(player);
break;
case CA_GLIDEANDCLIMB:
// Now Knuckles-type abilities are checked.
// If you can turn super and aren't already,
// and you don't have a shield, do it!
if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super]
&& !player->powers[pw_jumpshield] && !player->powers[pw_forceshield]
&& !player->powers[pw_watershield] && !player->powers[pw_ringshield]
&& !player->powers[pw_bombshield] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels
&& player->pflags & PF_JUMPED
&& ((player->skin == 0) || ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoSuperTransformation(player, false);
}
else if ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY))
{
//INT32 glidespeed = player->actionspd;
player->pflags |= PF_GLIDING;
player->pflags |= PF_THOKKED;
player->glidetime = 0;
if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
// Glide at double speed while super.
player->actionspd = atoi(skins[player->skin].actionspd)*player->mo->scale/100 * 2;
player->pflags &= ~PF_THOKKED;
}
else
player->actionspd = atoi(skins[player->skin].actionspd)*player->mo->scale/100;
P_SetPlayerMobjState(player->mo, S_PLAY_ABL1);
P_InstaThrust(player->mo, player->mo->angle, (player->actionspd<<FRACBITS)/NEWTICRATERATIO);
player->pflags &= ~PF_SPINNING;
player->pflags &= ~PF_STARTDASH;
}
else if (player->powers[pw_jumpshield] && !player->powers[pw_super])
P_DoJumpShield(player);
break;
case CA_DOUBLEJUMP: // Double-Jump
if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super]
&& !player->powers[pw_jumpshield] && !player->powers[pw_forceshield]
&& !player->powers[pw_watershield] && !player->powers[pw_ringshield]
&& !player->powers[pw_bombshield] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels
&& player->pflags & PF_JUMPED
&& ((player->skin == 0) || ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoSuperTransformation(player, false);
}
else if ((player->pflags & PF_JUMPED) && !player->secondjump)
{
player->pflags &= ~PF_JUMPED;
P_DoJump(player, true);
// Allow infinite double jumping if super.
if (!player->powers[pw_super])
player->secondjump = 1;
}
else if (player->powers[pw_jumpshield] && !player->powers[pw_super])
P_DoJumpShield(player);
break;
case CA_FLOAT: // Float
case CA_SLOWFALL: // Slow descent hover
if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super]
&& !player->powers[pw_jumpshield] && !player->powers[pw_forceshield]
&& !player->powers[pw_watershield] && !player->powers[pw_ringshield]
&& !player->powers[pw_bombshield] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels
&& player->pflags & PF_JUMPED
&& ((player->skin == 0) || ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoSuperTransformation(player, false);
}
else if ((player->pflags & PF_JUMPED) && !player->secondjump)
{
player->secondjump = 1;
}
else if (player->powers[pw_jumpshield] && !player->powers[pw_super])
P_DoJumpShield(player);
break;
default:
break;
}
}
}
player->pflags |= PF_JUMPDOWN;
if (!(cmd->buttons & BT_JUMP))// If not pressing the jump button
{
player->pflags &= ~PF_JUMPDOWN;
// Repeat abilities, but not double jump!
if ((player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP)
|| (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])))
player->secondjump = 0;
else if ((player->charability == CA_FLOAT) && player->secondjump == 1)
player->secondjump = 2;
}
if ((gametype != GT_CTF) || (!player->gotflag))
{
if (player->secondjump == 1 && (cmd->buttons & BT_JUMP))
{
if (player->charability == CA_FLOAT)
player->mo->momz = 0;
else if (player->charability == CA_SLOWFALL)
{
if (!(player->mo->eflags & MFE_VERTICALFLIP))
{
if (!player->powers[pw_super] && player->mo->momz < -gravity*4)
player->mo->momz = -gravity*4;
else if (player->powers[pw_super] && player->mo->momz < gravity*16)
player->mo->momz = gravity*16; //Float upward 4x as fast while super.
}
else
{
if (!player->powers[pw_super] && player->mo->momz > gravity*4)
player->mo->momz = gravity*4;
else if (player->powers[pw_super] && player->mo->momz > -gravity*16)
player->mo->momz = -gravity*16; //Float "upward" 4x as fast while super.
}
}
player->pflags &= ~PF_SPINNING;
}
}
// If letting go of the jump button while still on ascent, cut the jump height.
if (!(player->pflags & PF_JUMPDOWN) && (player->pflags & PF_JUMPED) && ((player->mo->eflags & MFE_VERTICALFLIP && player->mo->momz < 0) || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->momz > 0)) && player->jumping == 1)
{
player->mo->momz >>= 1;
player->jumping = 0;
}
}
|
|
P_2dMovement
Code - P_2dMovement
|
|
// Control scheme for 2d levels.
static void P_2dMovement(player_t *player)
{
ticcmd_t *cmd;
INT32 topspeed, acceleration, thrustfactor;
fixed_t movepushforward = 0;
angle_t movepushangle = 0;
fixed_t normalspd = player->normalspeed;
cmd = &player->cmd;
if (player->exiting
|| (player->pflags & PF_STASIS)
|| (player->powers[pw_nocontrol]) || (player->powers[pw_ingoop]))
{
cmd->forwardmove = cmd->sidemove = 0;
if (player->pflags & PF_GLIDING)
player->pflags &= ~PF_GLIDING;
if (player->pflags & PF_SPINNING && !player->exiting)
{
player->pflags &= ~PF_SPINNING;
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
}
}
// cmomx/cmomy stands for the conveyor belt speed.
if (player->onconveyor == 2) // Wind/Current
{
//if (player->mo->z > player->mo->watertop || player->mo->z + player->mo->height < player->mo->waterbottom)
if (!(player->mo->eflags & MFE_UNDERWATER) && !(player->mo->eflags & MFE_TOUCHWATER))
player->cmomx = player->cmomy = 0;
}
else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt
player->cmomx = player->cmomy = 0;
else if (player->onconveyor != 2 && player->onconveyor != 4)
player->cmomx = player->cmomy = 0;
player->rmomx = player->mo->momx - player->cmomx;
player->rmomy = player->mo->momy - player->cmomy;
// Calculates player's speed based on distance-of-a-line formula
player->speed = abs(player->rmomx)>>FRACBITS;
if (player->pflags & PF_GLIDING)
{
// Angle fix.
if (player->mo->angle < ANGLE_180 && player->mo->angle > ANGLE_90)
player->mo->angle = ANGLE_180;
else if (player->mo->angle < ANGLE_90 && player->mo->angle > 0)
player->mo->angle = 0;
if (cmd->sidemove > 0 && player->mo->angle != 0 && player->mo->angle >= ANGLE_180)
player->mo->angle += (640/NEWTICRATERATIO)<<FRACBITS;
else if (cmd->sidemove < 0 && player->mo->angle != ANGLE_180 && (player->mo->angle > ANGLE_180 || player->mo->angle == 0))
player->mo->angle -= (640/NEWTICRATERATIO)<<FRACBITS;
else if (cmd->sidemove == 0)
{
if (player->mo->angle >= ANGLE_270)
player->mo->angle += (640/NEWTICRATERATIO)<<FRACBITS;
else if (player->mo->angle < ANGLE_270 && player->mo->angle > ANGLE_180)
player->mo->angle -= (640/NEWTICRATERATIO)<<FRACBITS;
}
}
else if (cmd->sidemove && !(player->climbing) && !(!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]))
{
if (cmd->sidemove > 0)
player->mo->angle = 0;
else if (cmd->sidemove < 0)
player->mo->angle = ANGLE_180;
}
if (player == &players[consoleplayer])
localangle = player->mo->angle;
else if (splitscreen && player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
if (player->pflags & PF_GLIDING)
movepushangle = player->mo->angle;
else
{
if (cmd->sidemove > 0)
movepushangle = 0;
else if (cmd->sidemove < 0)
movepushangle = ANGLE_180;
else
movepushangle = player->mo->angle;
}
// Do not let the player control movement if not onground.
onground = P_IsObjectOnGround(player->mo);
player->aiming = cmd->aiming<<FRACBITS;
// Set the player speeds.
if (maptol & TOL_SRB1)
normalspd = (normalspd / 3) * 2;
if (player->powers[pw_super] || player->powers[pw_sneakers])
{
thrustfactor = player->thrustfactor*2;
acceleration = player->accelstart/4 + player->speed*(player->acceleration/4);
if (player->powers[pw_tailsfly])
topspeed = normalspd;
else if (player->mo->eflags & MFE_UNDERWATER && !(player->pflags & PF_SLIDING))
{
topspeed = normalspd;
acceleration = (acceleration * 2) / 3;
}
else
topspeed = normalspd * 2 > 50 ? 50 : normalspd * 2;
}
else
{
thrustfactor = player->thrustfactor;
acceleration = player->accelstart + player->speed*player->acceleration;
if (player->powers[pw_tailsfly])
{
topspeed = normalspd/2;
}
else if (player->mo->eflags & MFE_UNDERWATER && !(player->pflags & PF_SLIDING))
{
topspeed = normalspd/2;
acceleration = (acceleration * 2) / 3;
}
else
{
topspeed = normalspd;
}
}
//////////////////////////////////////
if (player->climbing == 1)
{
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT,10*FRACUNIT), false);
if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
player->mo->momz *= 2;
player->mo->momx = 0;
}
if (cmd->sidemove != 0 && !(player->climbing || (player->pflags & PF_GLIDING) || player->exiting
|| (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]
&& !onground)))
{
if (player->powers[pw_sneakers] || player->powers[pw_super]) // do you have super sneakers?
movepushforward = abs(cmd->sidemove) * ((thrustfactor*2)*acceleration);
else // if not, then run normally
movepushforward = abs(cmd->sidemove) * (thrustfactor*acceleration);
// allow very small movement while in air for gameplay
if (!onground)
movepushforward >>= 1; // Proper air movement
// Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING)
{
if (!(player->pflags & PF_STARTDASH))
movepushforward = movepushforward/48;
else
movepushforward = 0;
}
if (((player->rmomx>>FRACBITS) < topspeed) && (cmd->sidemove > 0)) // Sonic's Speed
P_Thrust(player->mo, movepushangle, movepushforward);
else if (((player->rmomx>>FRACBITS) > -topspeed) && (cmd->sidemove < 0))
P_Thrust(player->mo, movepushangle, movepushforward);
}
}
|
|
P_3dMovement
Code - P_3dMovement
|
|
static void P_3dMovement(player_t *player)
{
ticcmd_t *cmd;
angle_t movepushangle, movepushsideangle; // Analog
INT32 topspeed, acceleration, thrustfactor;
fixed_t movepushforward = 0, movepushside = 0;
INT32 mforward = 0, mbackward = 0;
camera_t *thiscam;
fixed_t normalspd = player->normalspeed;
if (splitscreen && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else
thiscam = &camera;
cmd = &player->cmd;
if (player->exiting
|| (player->pflags & PF_STASIS)
|| (player->powers[pw_nocontrol]) || (player->powers[pw_ingoop]))
{
cmd->forwardmove = cmd->sidemove = 0;
if (player->pflags & PF_GLIDING)
player->pflags &= ~PF_GLIDING;
if (player->pflags & PF_SPINNING && !player->exiting)
{
player->pflags &= ~PF_SPINNING;
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
}
}
if (!netgame && ((player == &players[consoleplayer] && cv_analog.value) || (splitscreen && player == &players[secondarydisplayplayer] && cv_analog2.value)))
{
movepushangle = thiscam->angle;
movepushsideangle = thiscam->angle-ANGLE_90;
}
else
{
movepushangle = player->mo->angle;
movepushsideangle = player->mo->angle-ANGLE_90;
}
// cmomx/cmomy stands for the conveyor belt speed.
if (player->onconveyor == 2) // Wind/Current
{
//if (player->mo->z > player->mo->watertop || player->mo->z + player->mo->height < player->mo->waterbottom)
if (!(player->mo->eflags & MFE_UNDERWATER) && !(player->mo->eflags & MFE_TOUCHWATER))
player->cmomx = player->cmomy = 0;
}
else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt
player->cmomx = player->cmomy = 0;
else if (player->onconveyor != 2 && player->onconveyor != 4)
player->cmomx = player->cmomy = 0;
player->rmomx = player->mo->momx - player->cmomx;
player->rmomy = player->mo->momy - player->cmomy;
// Calculates player's speed based on distance-of-a-line formula
player->speed = P_AproxDistance(player->rmomx, player->rmomy)>>FRACBITS;
// This determines if the player is facing the direction they are travelling or not.
// Didn't your teacher say to pay attention in Geometry/Trigonometry class? ;)
// forward
if ((player->rmomx > 0 && player->rmomy > 0) && (/*player->mo->angle >= 0 &&*/ player->mo->angle < ANGLE_90)) // Quadrant 1
mforward = 1;
else if ((player->rmomx < 0 && player->rmomy > 0) && (player->mo->angle >= ANGLE_90 && player->mo->angle < ANGLE_180)) // Quadrant 2
mforward = 1;
else if ((player->rmomx < 0 && player->rmomy < 0) && (player->mo->angle >= ANGLE_180 && player->mo->angle < ANGLE_270)) // Quadrant 3
mforward = 1;
else if ((player->rmomx > 0 && player->rmomy < 0) && ((player->mo->angle >= ANGLE_270 /*&& (player->mo->angle <= ANGLE_MAX)*/) || (/*player->mo->angle >= 0 &&*/ player->mo->angle <= ANGLE_45))) // Quadrant 4
mforward = 1;
else if (player->rmomx > 0 && ((player->mo->angle >= ANGLE_315 /*&& player->mo->angle <= ANGLE_MAX*/)))
mforward = 1;
else if (player->rmomx < 0 && (player->mo->angle >= ANGLE_135 && player->mo->angle <= ANGLE_225))
mforward = 1;
else if (player->rmomy > 0 && (player->mo->angle >= ANGLE_45 && player->mo->angle <= ANGLE_135))
mforward = 1;
else if (player->rmomy < 0 && (player->mo->angle >= ANGLE_225 && player->mo->angle <= ANGLE_315))
mforward = 1;
else
mforward = 0;
// backward
if ((player->rmomx > 0 && player->rmomy > 0) && (player->mo->angle >= ANGLE_180 && player->mo->angle < ANGLE_270)) // Quadrant 3
mbackward = 1;
else if ((player->rmomx < 0 && player->rmomy > 0) && (player->mo->angle >= ANGLE_270 /*&& (player->mo->angle <= ANGLE_MAX)*/)) // Quadrant 4
mbackward = 1;
else if ((player->rmomx < 0 && player->rmomy < 0) && (/*player->mo->angle >= 0 &&*/ player->mo->angle < ANGLE_90)) // Quadrant 1
mbackward = 1;
else if ((player->rmomx > 0 && player->rmomy < 0) && (player->mo->angle >= ANGLE_90 && player->mo->angle < ANGLE_180)) // Quadrant 2
mbackward = 1;
else if (player->rmomx < 0 && ((player->mo->angle >= ANGLE_315 /*&& player->mo->angle <= ANGLE_MAX*/) || (/*player->mo->angle >= 0 &&*/ player->mo->angle <= ANGLE_45)))
mbackward = 1;
else if (player->rmomx > 0 && (player->mo->angle >= ANGLE_135 && player->mo->angle <= ANGLE_225))
mbackward = 1;
else if (player->rmomy < 0 && (player->mo->angle >= ANGLE_45 && player->mo->angle <= ANGLE_135))
mbackward = 1;
else if (player->rmomy > 0 && (player->mo->angle >= ANGLE_225 && player->mo->angle <= ANGLE_315))
mbackward = 1;
else // Put in 'or' checks here!
mbackward = 0;
// When sliding, don't allow forward/back
if (player->pflags & PF_SLIDING)
cmd->forwardmove = 0;
// Do not let the player control movement if not onground.
onground = P_IsObjectOnGround(player->mo);
player->aiming = cmd->aiming<<FRACBITS;
// Set the player speeds.
if (maptol & TOL_SRB1)
normalspd = (normalspd / 3) * 2;
if (player->powers[pw_super] || player->powers[pw_sneakers])
{
thrustfactor = player->thrustfactor*2;
acceleration = player->accelstart/4 + player->speed*(player->acceleration/4);
if (player->powers[pw_tailsfly])
topspeed = normalspd;
else if (player->mo->eflags & MFE_UNDERWATER && !(player->pflags & PF_SLIDING))
{
topspeed = normalspd;
acceleration = (acceleration * 2) / 3;
}
else
topspeed = normalspd * 2 > 50 ? 50 : normalspd * 2;
}
else
{
thrustfactor = player->thrustfactor;
acceleration = player->accelstart + player->speed*player->acceleration;
if (player->powers[pw_tailsfly])
topspeed = normalspd/2;
else if (player->mo->eflags & MFE_UNDERWATER && !(player->pflags & PF_SLIDING))
{
topspeed = normalspd/2;
acceleration = (acceleration * 2) / 3;
}
else
topspeed = normalspd;
}
// Better maneuverability while flying
if(player->powers[pw_tailsfly])
{
thrustfactor = player->thrustfactor*2;
acceleration = player->accelstart + player->speed*player->acceleration;
}
if ((netgame || (player == &players[consoleplayer] && !cv_analog.value)
|| (splitscreen && player == &players[secondarydisplayplayer] && !cv_analog2.value))
&& cmd->forwardmove != 0 && !((player->pflags & PF_GLIDING) || player->exiting
|| (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]
&& !onground)))
{
if (player->climbing)
{
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT,10*FRACUNIT), false);
if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
player->mo->momz *= 2;
}
else if (player->powers[pw_sneakers] || player->powers[pw_super]) // super sneakers?
movepushforward = cmd->forwardmove * ((thrustfactor*2)*acceleration);
else // if not, then run normally
movepushforward = cmd->forwardmove * (thrustfactor*acceleration);
// allow very small movement while in air for gameplay
if (!onground)
movepushforward >>= 2; // proper air movement
// Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING)
{
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0))
movepushforward = 0;
else if (!(player->pflags & PF_STARTDASH))
movepushforward = FixedDiv(movepushforward,16*FRACUNIT);
else
movepushforward = 0;
}
if ((player->speed < topspeed) && (mforward) && (cmd->forwardmove > 0)) // Sonic's Speed
P_Thrust(player->mo, movepushangle, movepushforward);
else if ((mforward) && (cmd->forwardmove < 0))
P_Thrust(player->mo, movepushangle, movepushforward);
else if ((player->speed < topspeed) && (mbackward) && (cmd->forwardmove < 0))
P_Thrust(player->mo, movepushangle, movepushforward);
else if ((mbackward) && (cmd->forwardmove > 0))
P_Thrust(player->mo, movepushangle, movepushforward);
else if (!mforward && !mbackward)
P_Thrust(player->mo, movepushangle, movepushforward);
}
// Analog movement control
if (!netgame && ((player == &players[consoleplayer] && cv_analog.value)
|| (splitscreen && player == &players[secondarydisplayplayer]
&& cv_analog2.value)) && thiscam->chase)
{
if (!((player->pflags & PF_GLIDING) || player->exiting || (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]
&& player->powers[pw_flashing])))
{
angle_t controldirection, controllerdirection, controlplayerdirection;
fixed_t tempx, tempy;
angle_t tempangle;
boolean cforward; // controls pointing forward from the player
boolean cbackward; // controls pointing backward from the player
tempx = tempy = 0;
cforward = cbackward = false;
// Calculate the angle at which the controls are pointing
// to figure out the proper mforward and mbackward.
tempangle = thiscam->angle;
tempangle >>= ANGLETOFINESHIFT;
tempx += FixedMul(cmd->forwardmove,FINECOSINE(tempangle));
tempy += FixedMul(cmd->forwardmove,FINESINE(tempangle));
tempangle = thiscam->angle-ANGLE_90;
tempangle >>= ANGLETOFINESHIFT;
tempx += FixedMul(cmd->sidemove,FINECOSINE(tempangle));
tempy += FixedMul(cmd->sidemove,FINESINE(tempangle));
tempx = tempx*FRACUNIT;
tempy = tempy*FRACUNIT;
controldirection = controllerdirection =
R_PointToAngle2(player->mo->x, player->mo->y, player->mo->x + tempx,
player->mo->y + tempy);
controlplayerdirection = player->mo->angle;
if (controlplayerdirection < ANGLE_90)
{
controlplayerdirection += ANGLE_90;
controllerdirection += ANGLE_90;
}
else if (controlplayerdirection >= ANGLE_270)
{
controlplayerdirection -= ANGLE_90;
controllerdirection -= ANGLE_90;
}
// Controls pointing backwards from player
if (controllerdirection > controlplayerdirection + ANGLE_90
&& controllerdirection < controlplayerdirection - ANGLE_90)
{
cbackward = true;
}
else // Controls pointing in player's general direction
cforward = true;
if (player->climbing)
{
fixed_t value = 10*FRACUNIT;
// Thrust in the direction of the controls
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT,10*FRACUNIT), false);
if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
player->mo->momz *= 2;
value /= 2;
}
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*FRACUNIT,value));
}
else if (player->powers[pw_sneakers] || player->powers[pw_super]) // super sneakers?
movepushforward = FixedMul(FixedHypot(cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT), ((thrustfactor*2)*acceleration));
else // if not, then run normally
movepushforward = FixedMul(FixedHypot(cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT), ((thrustfactor*1)*acceleration));
// allow very small movement while in air for gameplay
if (!onground)
movepushforward >>= 2; // proper air movement
// Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING)
{
// Stupid little movement prohibitor hack
// that REALLY shouldn't belong in analog code.
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0))
movepushforward = 0;
else if (!(player->pflags & PF_STARTDASH))
movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
else
movepushforward = 0;
}
movepushsideangle = controldirection;
if (player->speed < topspeed)
P_Thrust(player->mo, controldirection, movepushforward);
else if ((mforward) && (cbackward))
P_Thrust(player->mo, controldirection, movepushforward);
else if ((mbackward) && (cforward))
P_Thrust(player->mo, controldirection, movepushforward);
}
}
else if (netgame || (player == &players[consoleplayer] && !cv_analog.value)
|| (splitscreen && player == &players[secondarydisplayplayer]
&& !cv_analog2.value))
{
if (player->climbing)
{
if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FIXEDSCALE((cmd->sidemove/5)*FRACUNIT, player->mo->scale));
else
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FIXEDSCALE((cmd->sidemove/10)*FRACUNIT, player->mo->scale));
player->mo->momx = FIXEDSCALE(player->mo->momx,player->mo->scale);
player->mo->momy = FIXEDSCALE(player->mo->momy,player->mo->scale);
}
else if (cmd->sidemove && !(player->pflags & PF_GLIDING) && !player->exiting && !player->climbing && !(!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]))
{
boolean mright;
boolean mleft;
angle_t sideangle;
sideangle = player->mo->angle - ANGLE_90;
// forward
if ((player->rmomx > 0 && player->rmomy > 0) && (/*sideangle >= 0 &&*/ sideangle < ANGLE_90)) // Quadrant 1
mright = 1;
else if ((player->rmomx < 0 && player->rmomy > 0) && (sideangle >= ANGLE_90 && sideangle < ANGLE_180)) // Quadrant 2
mright = 1;
else if ((player->rmomx < 0 && player->rmomy < 0) && (sideangle >= ANGLE_180 && sideangle < ANGLE_270)) // Quadrant 3
mright = 1;
else if ((player->rmomx > 0 && player->rmomy < 0) && ((sideangle >= ANGLE_270 /*&& (sideangle <= ANGLE_MAX)*/) || (/*sideangle >= 0 &&*/ sideangle <= ANGLE_45))) // Quadrant 4
mright = 1;
else if (player->rmomx > 0 && ((sideangle >= ANGLE_315 /*&& sideangle <= ANGLE_MAX*/)))
mright = 1;
else if (player->rmomx < 0 && (sideangle >= ANGLE_135 && sideangle <= ANGLE_225))
mright = 1;
else if (player->rmomy > 0 && (sideangle >= ANGLE_45 && sideangle <= ANGLE_135))
mright = 1;
else if (player->rmomy < 0 && (sideangle >= ANGLE_225 && sideangle <= ANGLE_315))
mright = 1;
else
mright = 0;
// backward
if ((player->rmomx > 0 && player->rmomy > 0) && (sideangle >= ANGLE_180 && sideangle < ANGLE_270)) // Quadrant 3
mleft = 1;
else if ((player->rmomx < 0 && player->rmomy > 0) && (sideangle >= ANGLE_270 /*&& (sideangle <= ANGLE_MAX)*/)) // Quadrant 4
mleft = 1;
else if ((player->rmomx < 0 && player->rmomy < 0) && (/*sideangle >= 0 &&*/ sideangle < ANGLE_90)) // Quadrant 1
mleft = 1;
else if ((player->rmomx > 0 && player->rmomy < 0) && (sideangle >= ANGLE_90 && sideangle < ANGLE_180)) // Quadrant 2
mleft = 1;
else if (player->rmomx < 0 && ((sideangle >= ANGLE_315 /*&& sideangle <= ANGLE_MAX*/) || (/*sideangle >= 0 &&*/ sideangle <= ANGLE_45)))
mleft = 1;
else if (player->rmomx > 0 && (sideangle >= ANGLE_135 && sideangle <= ANGLE_225))
mleft = 1;
else if (player->rmomy < 0 && (sideangle >= ANGLE_45 && sideangle <= ANGLE_135))
mleft = 1;
else if (player->rmomy > 0 && (sideangle >= ANGLE_225 && sideangle <= ANGLE_315))
mleft = 1;
else // Put in 'or' checks here!
mleft = 0;
movepushside = cmd->sidemove * (thrustfactor*acceleration);
if (player->powers[pw_sneakers] || player->powers[pw_super])
movepushside *= 2;
if (!onground)
{
movepushside >>= 2;
//Lower speed if over "max" flight speed and greatly reduce movepushslide.
if (player->powers[pw_tailsfly] && player->speed > topspeed)
{
player->speed = topspeed - 1;
movepushside /= 8;
}
}
// Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING)
{
if (!(player->pflags & PF_STARTDASH))
movepushside = FixedDiv(movepushside,16*FRACUNIT);
else
movepushside = 0;
}
// Finally move the player now that his speed/direction has been decided.
if (player->speed < topspeed)
P_Thrust(player->mo, movepushsideangle, movepushside);
else if ((mright) && (cmd->sidemove < 0))
P_Thrust(player->mo, movepushsideangle, movepushside);
else if ((mleft) && (cmd->sidemove > 0))
P_Thrust(player->mo, movepushsideangle, movepushside);
}
}
}
|
|
P_ObjectplaceMovement
Code - P_ObjectplaceMovement
|
|
//
// P_ObjectplaceMovement
//
// Control code for Objectplace mode
//
static void P_ObjectplaceMovement(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
mobj_t *currentitem;
if (!player->climbing && (netgame || (player == &players[consoleplayer]
&& !cv_analog.value) || (splitscreen
&& player == &players[secondarydisplayplayer] && !cv_analog2.value)
|| (player->pflags & PF_SPINNING)))
{
player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */);
}
ticruned++;
if (!(cmd->angleturn & TICCMD_RECEIVED))
ticmiss++;
if (cmd->buttons & BT_JUMP)
player->mo->z += FRACUNIT*cv_speed.value;
else if (cmd->buttons & BT_USE)
player->mo->z -= FRACUNIT*cv_speed.value;
if (player->mo->target && player->mo->z > player->mo->ceilingz - player->mo->target->height)
player->mo->z = player->mo->ceilingz - player->mo->target->height;
else if (!player->mo->target && player->mo->z > player->mo->ceilingz - player->mo->height)
player->mo->z = player->mo->ceilingz - player->mo->height;
if (player->mo->z < player->mo->floorz)
player->mo->z = player->mo->floorz;
if (cmd->forwardmove != 0)
{
P_Thrust(player->mo, player->mo->angle, cmd->forwardmove*(FRACUNIT/4));
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}
if (cmd->sidemove != 0)
{
P_Thrust(player->mo, player->mo->angle-ANGLE_90, cmd->sidemove*(FRACUNIT/4));
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}
if (cmd->buttons & BT_CAMLEFT && !(player->pflags & PF_SKIDDOWN))
{
do
{
player->currentthing--;
if (player->currentthing <= 0)
player->currentthing = NUMMOBJTYPES-1;
}while (mobjinfo[player->currentthing].doomednum == -1
|| player->currentthing == MT_NIGHTSDRONE
|| mobjinfo[player->currentthing].flags & MF_AMBIENT
|| mobjinfo[player->currentthing].flags & MF_NOSECTOR
|| mobjinfo[player->currentthing].flags & MF_BOSS
|| (states[mobjinfo[player->currentthing].spawnstate].sprite == SPR_DISS && player->currentthing != MT_MINUS));
CONS_Printf("Current mapthing is %d\n", mobjinfo[player->currentthing].doomednum);
player->pflags |= PF_SKIDDOWN;
}
else if (cmd->buttons & BT_CAMRIGHT && !(player->pflags & PF_JUMPDOWN))
{
do
{
player->currentthing++;
if (player->currentthing >= NUMMOBJTYPES)
player->currentthing = 0;
}while (mobjinfo[player->currentthing].doomednum == -1
|| player->currentthing == MT_NIGHTSDRONE
|| mobjinfo[player->currentthing].flags & MF_AMBIENT
|| mobjinfo[player->currentthing].flags & MF_NOSECTOR
|| mobjinfo[player->currentthing].flags & MF_BOSS
|| (states[mobjinfo[player->currentthing].spawnstate].sprite == SPR_DISS && player->currentthing != MT_MINUS));
CONS_Printf("Current mapthing is %d\n", mobjinfo[player->currentthing].doomednum);
player->pflags |= PF_JUMPDOWN;
}
// Place an object and add it to the maplist
if (player->mo->target)
if (cmd->buttons & BT_ATTACK && !(player->pflags & PF_ATTACKDOWN))
{
mapthing_t *mt;
mapthing_t *oldmapthings;
mobj_t *newthing;
INT16 x,y,z = 0;
UINT8 zshift;
if (player->mo->target->flags & MF_SPAWNCEILING)
{
// Move down from the ceiling
if (cv_snapto.value)
{
if (cv_snapto.value == 1) // Snap to floor
z = (INT16)((player->mo->subsector->sector->ceilingheight - player->mo->floorz)>>FRACBITS);
else if (cv_snapto.value == 2) // Snap to ceiling
z = (INT16)((player->mo->subsector->sector->ceilingheight - player->mo->ceilingz - player->mo->target->height)>>FRACBITS);
else if (cv_snapto.value == 3) // Snap to middle
z = (INT16)((player->mo->subsector->sector->ceilingheight - (player->mo->ceilingz - player->mo->floorz)/2 - player->mo->target->height/2)>>FRACBITS);
}
else
{
if (cv_grid.value)
{
INT32 adjust;
adjust = cv_grid.value - (((player->mo->subsector->sector->ceilingheight -
player->mo->subsector->sector->floorheight)>>FRACBITS) % cv_grid.value);
z = (INT16)(((player->mo->subsector->sector->ceilingheight - player->mo->z))>>FRACBITS);
z = (INT16)(z + (INT16)adjust);
// round to the nearest cv_grid.value
z = (INT16)((z + cv_grid.value/2) % cv_grid.value);
z = (INT16)(z - (INT16)adjust);
}
else
z = (INT16)((player->mo->subsector->sector->ceilingheight - player->mo->z)>>FRACBITS);
}
}
else
{
if (cv_snapto.value)
{
if (cv_snapto.value == 1) // Snap to floor
z = (INT16)((player->mo->floorz - player->mo->subsector->sector->floorheight)>>FRACBITS);
else if (cv_snapto.value == 2) // Snap to ceiling
z = (INT16)((player->mo->ceilingz - player->mo->target->height - player->mo->subsector->sector->floorheight)>>FRACBITS);
else if (cv_snapto.value == 3) // Snap to middle
z = (INT16)((((player->mo->ceilingz - player->mo->floorz)/2)-(player->mo->target->height/2)-player->mo->subsector->sector->floorheight)>>FRACBITS);
}
else
{
if (cv_grid.value)
{
z = (INT16)(((player->mo->subsector->sector->ceilingheight - player->mo->z))>>FRACBITS);
// round to the nearest cv_grid.value
z = (INT16)((z + cv_grid.value/2) % cv_grid.value);
}
else
z = (INT16)((player->mo->z - player->mo->subsector->sector->floorheight)>>FRACBITS);
}
}
// Starts have height limitations for some reason.
if (cv_mapthingnum.value >= 1 && cv_mapthingnum.value <= 99)
{
if (z >= (1 << (16-(ZSHIFT+1))))
{
CONS_Printf("Sorry, you're too %s to place this object (max: %d %s).\n",
player->mo->target->flags & MF_SPAWNCEILING ? "low" : "high",
(1 << (16-(ZSHIFT+1))),
player->mo->target->flags & MF_SPAWNCEILING ? "below top ceiling" : "above bottom floor");
return;
}
zshift = ZSHIFT+1; // Shift it over 5 bits to make room for the flag info.
}
else
{
if (z >= (1 << (16-ZSHIFT)))
{
CONS_Printf("Sorry, you're too %s to place this object (max: %d %s).\n",
player->mo->target->flags & MF_SPAWNCEILING ? "low" : "high",
(1 << (16-ZSHIFT)),
player->mo->target->flags & MF_SPAWNCEILING ? "below top ceiling" : "above bottom floor");
return;
}
zshift = ZSHIFT;
}
z <<= zshift;
// Currently only the Starpost uses this
if (player->mo->target->flags & MF_SPECIALFLAGS)
{
if (player->mo->target->type == MT_STARPOST)
z = (INT16)z;
}
else
z = (INT16)(z + (INT16)cv_objflags.value); // Easy/med/hard/ambush/etc.
oldmapthings = mapthings;
nummapthings++;
#if 0
mapthings = M_Memcpy(Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL), oldmapthings, sizeof (mapthing_t)*(nummapthings-1));
Z_Free(oldmapthings);
#else
mapthings = Z_Realloc(oldmapthings, nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
#endif
mt = mapthings + nummapthings-1;
if (cv_grid.value)
{
x = (INT16)(P_GridSnap(player->mo->x)>>FRACBITS);
y = (INT16)(P_GridSnap(player->mo->y)>>FRACBITS);
}
else
{
x = (INT16)(player->mo->x>>FRACBITS);
y = (INT16)(player->mo->y>>FRACBITS);
}
mt->x = x;
mt->y = y;
mt->angle = (INT16)FixedInt(AngleFixed(player->mo->angle));
if (cv_mapthingnum.value != 0)
{
mt->type = (INT16)cv_mapthingnum.value;
CONS_Printf("Placed object mapthingum %d, not the one below.\n", mt->type);
}
else
mt->type = (INT16)mobjinfo[player->currentthing].doomednum;
mt->options = z;
newthing = P_SpawnMobj(x << FRACBITS, y << FRACBITS, player->mo->target->flags & MF_SPAWNCEILING ? player->mo->subsector->sector->ceilingheight - ((z>>zshift)<<FRACBITS) : player->mo->subsector->sector->floorheight + ((z>>zshift)<<FRACBITS), player->currentthing);
newthing->angle = player->mo->angle;
newthing->spawnpoint = mt;
CONS_Printf("Placed object type %d at %d, %d, %d, %d\n", newthing->info->doomednum, mt->x, mt->y, newthing->z>>FRACBITS, mt->angle);
player->pflags |= PF_ATTACKDOWN;
}
if (cmd->buttons & BT_TAUNT) // Remove any objects near you
{
thinker_t *th;
mobj_t *mo2;
boolean done = false;
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == player->mo->target)
continue;
if (mo2 == player->mo)
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - player->mo->x, mo2->y - player->mo->y), mo2->z - player->mo->z) < player->mo->radius)
{
if (mo2->spawnpoint)
{
mapthing_t *mt;
size_t i;
P_SetMobjState(mo2, S_DISS);
mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++)
{
if (done)
continue;
if (mt->mobj == mo2) // Found it! Now to delete...
{
mapthing_t *oldmapthings;
mapthing_t *oldmt;
mapthing_t *newmt;
size_t z;
CONS_Printf("Deleting...\n");
oldmapthings = mapthings;
nummapthings--;
mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
// Gotta rebuild the WHOLE MAPTHING LIST,
// otherwise it doesn't work!
oldmt = oldmapthings;
newmt = mapthings;
for (z = 0; z < nummapthings+1; z++, oldmt++, newmt++)
{
if (oldmt->mobj == mo2)
{
CONS_Printf("Deleted.\n");
newmt--;
continue;
}
newmt->x = oldmt->x;
newmt->y = oldmt->y;
newmt->angle = oldmt->angle;
newmt->type = oldmt->type;
newmt->options = oldmt->options;
newmt->z = oldmt->z;
newmt->mobj = oldmt->mobj;
}
Z_Free(oldmapthings);
done = true;
}
}
}
else
CONS_Printf("You cannot delete this item because it doesn't have a mapthing!\n");
}
done = false;
}
}
if (!(cmd->buttons & BT_ATTACK))
player->pflags &= ~PF_ATTACKDOWN;
if (!(cmd->buttons & BT_CAMLEFT))
player->pflags &= ~PF_SKIDDOWN;
if (!(cmd->buttons & BT_CAMRIGHT))
player->pflags &= ~PF_JUMPDOWN;
if (!player->mo->target || player->currentthing != player->mo->target->type)
{
if (player->mo->target)
P_RemoveMobj(player->mo->target); // The object has MF_NOTHINK, so S_DISS would never pass.
currentitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, player->currentthing);
currentitem->flags |= MF_NOTHINK;
currentitem->angle = player->mo->angle;
currentitem->tics = -1;
P_SetTarget(&player->mo->target, currentitem);
P_UnsetThingPosition(currentitem);
currentitem->flags |= MF_NOBLOCKMAP;
currentitem->flags |= MF_NOCLIP;
P_SetThingPosition(currentitem);
currentitem->floorz = player->mo->floorz;
currentitem->ceilingz = player->mo->ceilingz;
}
else if (player->mo->target)
{
P_UnsetThingPosition(player->mo->target);
player->mo->target->x = player->mo->x;
player->mo->target->y = player->mo->y;
player->mo->target->z = player->mo->z;
P_SetThingPosition(player->mo->target);
player->mo->target->angle = player->mo->angle;
player->mo->target->floorz = player->mo->floorz;
player->mo->target->ceilingz = player->mo->ceilingz;
}
}
|
|
P_NukeEnemies
Range of Armageddon Shield's explosion = dist
= 1536 << FRACBITS
- = 1536*
FRACUNIT
- = 1536 fracunits
Code - P_NukeEnemies
|
|
//
// P_NukeEnemies
// Looks for something you can hit - Used for bomb shield
//
void P_NukeEnemies(player_t *player)
{
const fixed_t dist = 1536 << FRACBITS;
const fixed_t ns = 60 << FRACBITS;
mobj_t *mo;
angle_t fa;
thinker_t *think;
INT32 i;
for (i = 0; i < 16; i++)
{
fa = (i*(FINEANGLES/16));
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK);
mo->momx = FixedMul(FINESINE(fa),ns)/NEWTICRATERATIO;
mo->momy = FixedMul(FINECOSINE(fa),ns)/NEWTICRATERATIO;
}
for (think = thinkercap.next; think != &thinkercap; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & MF_SHOOTABLE))
continue;
if (mo->flags & MF_MONITOR)
continue; // Monitors cannot be 'nuked'.
if ((gametype == GT_COOP || gametype == GT_RACE) && mo->type == MT_PLAYER)
continue; // Don't hurt players in Co-Op!
if (P_AproxDistance(P_AproxDistance(player->mo->x - mo->x, player->mo->y - mo->y), player->mo->z - mo->z) > dist)
continue;
if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players!
P_DamageMobj(mo, player->mo, player->mo, 1);
else
P_DamageMobj(mo, player->mo, player->mo, 1000);
}
}
|
|
P_LookForEnemies
Max distance target can be from player = RING_DIST
- = 512*
FRACUNIT
- = 512 fracunits
Code - P_LookForEnemies
|
|
//
// P_LookForEnemies
// Looks for something you can hit - Used for homing attack
// Includes monitors and springs!
//
boolean P_LookForEnemies(player_t *player)
{
mobj_t *mo;
thinker_t *think;
mobj_t *closestmo = NULL;
angle_t an;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->flags & MF_MONITOR
|| mo->flags & MF_SPRING))
{
continue; // not a valid enemy
}
if (mo->health <= 0) // dead
continue;
if (mo == player->mo)
continue;
if (mo->flags2 & MF2_FRET)
continue;
if (mo->type == MT_DETON) // Don't be STUPID, Sonic!
continue;
if (mo->flags & MF_MONITOR && mo->state == &states[S_MONITOREXPLOSION5])
continue;
if (mo->z > player->mo->z+MAXSTEPMOVE)
continue; // Don't home upwards!
if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y),
player->mo->z-mo->z) > RING_DIST)
continue; // out of range
if (mo->type == MT_PLAYER) // Don't chase after other players!
continue;
if (closestmo && P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y),
player->mo->z-mo->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closestmo->x,
player->mo->y-closestmo->y), player->mo->z-closestmo->z))
continue;
an = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y) - player->mo->angle;
if (an > ANGLE_90 && an < ANGLE_270)
continue; // behind back
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y);
if (!P_CheckSight(player->mo, mo))
continue; // out of sight
closestmo = mo;
}
if (closestmo)
{
// Found a target monster
P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, closestmo));
return true;
}
return false;
}
|
|
P_HomingAttack
const fixed_t ns = source->player->actionspd * FRACUNIT;
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), FixedDiv(ns,3*FRACUNIT/2));
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), FixedDiv(ns,3*FRACUNIT/2));
source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), FixedDiv(ns,3*FRACUNIT/2));
Speed a player with CA_HOMINGTHOK
will home to its target:
- = Distance from target * (actionspd/1.5)
Code - P_HomingAttack
|
|
void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
{
fixed_t dist;
if (!enemy)
return;
if (!(enemy->health))
return;
// change angle
source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y);
if (source->player)
{
if (source->player == &players[consoleplayer])
localangle = source->angle;
else if (splitscreen && source->player == &players[secondarydisplayplayer])
localangle2 = source->angle;
}
// change slope
dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y),
enemy->z - source->z);
if (dist < 1)
dist = 1;
if (source->type == MT_DETON && enemy->player) // For Deton Chase
{
fixed_t ns = FixedDiv(enemy->player->normalspeed*FRACUNIT, FixedDiv(20*FRACUNIT,17*FRACUNIT));
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns);
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns);
source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), ns);
}
else if (source->type != MT_PLAYER)
{
if (source->threshold == 32000)
{
fixed_t ns = source->info->speed/2;
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns);
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns);
source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), ns);
}
else
{
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), source->info->speed);
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), source->info->speed);
source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), source->info->speed);
}
}
else if (source->player)
{
const fixed_t ns = source->player->actionspd * FRACUNIT;
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), FixedDiv(ns,3*FRACUNIT/2));
source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), FixedDiv(ns,3*FRACUNIT/2));
source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), FixedDiv(ns,3*FRACUNIT/2));
}
}
|
|
sinkspeed
= Speed the player sinks into the quicksand
friction
= Multiplied by the player's current momx/momy to set the "sludginess" of the player's movement
sinkspeed
= abs(rover->master->v1->x - rover->master->v2->x)>>1;
sinkspeed
= Linedef X distance/2
sinkspeed
= FixedDiv(sinkspeed
,TICRATE
*FRACUNIT
);
- =
sinkspeed
/(35*65536)
- =
sinkspeed
/2293760
sinkspeed
= (Linedef X distance/2)/2293760
sinkspeed
= Linedef X distance/4587520
sinkspeed
= Linedef X distance/(1 fracunit/70 tics)
friction
= abs(rover->master->v1->y - rover->master->v2->y)>>6
friction
= Linedef Y distance/64
Linedef X distance (fracunits)
|
sinkspeed
|
0
|
0
|
1
|
1/4587520 = 1 fracunit/70 tics
|
2
|
2/4587520 = 2 fracunits/70 tics = 1 fracunit/35 tics
|
7
|
7/4587520 = 0.00000152587890625 = 7 fracunits/70 tics = 1 fracunit/10 tics
|
35
|
35/4587520 = 0.00000762939453125 = 35 fracunits/70 tics = 1 fracunit/2 tics
|
70
|
70/4587520 = 0.0000152587890625 = 70 fracunits/70 tics = 1 fracunit/1 tic
|
140
|
140/4587520 = 0.000030517578125 = 140 fracunits/70 tics = 1 fracunit/0.5 tics
|
Linedef Y distance (fracunits)
|
friction
|
0
|
0 = 0% of Player's speed
|
1
|
1/64 = 0.015625 = 1.5625% of Player's speed
|
2
|
2/64 = 1/32 = 0.03125 = 3.125% of Player's speed
|
16
|
16/64 = 1/4 = 0.25 = 25% of Player's speed
|
32
|
32/64 = 1/2 = 0.5 = 50% of Player's speed
|
48
|
48/64 = 3/4 = 0.75 = 75% of Player's speed
|
64
|
64/64 = 1 = 100% of Player's speed
|
128
|
128/64 = 2 = 200% of Player's speed
|
MAXCAMERADIST
= 140*FRACUNIT
- = 140 fracunits (Max distance the camera can be in front of the player, in 2D mode)
r_things.h
MAXSPRITELUMPS
= 8192
MAXVISSPRITES
= 2048
SKINNAMESIZE
= 16
DEFAULTSKIN
= "sonic\0\0\0\0\0\0\0\0\0\0"
s_sound.c/s_sound.h
S_MAX_VOLUME
= 127
S_CLIPPING_DIST
= 1536*0x10000
- = 1536*
FRACUNIT
- = 1536 fracunits (when to clip out sounds)
S_CLOSE_DIST
= 160*0x10000
- = 160*
FRACUNIT
- = 160 fracunits (Distance to origin when sounds should be maxed out)
S_ATTENUATOR
= ((S_CLIPPING_DIST
-S_CLOSE_DIST
)>>(FRACBITS
+4))
- = ((1536*
FRACUNIT
-160*FRACUNIT
)>>(20))
- = (1376*
FRACUNIT
)/ 2^20
- = 90177536/1048576
- = 86
NORM_VOLUME
= snd_MaxVolume
NORM_PITCH
= 128
NORM_PRIORITY
= 64
NORM_SEP
= 128
S_PITCH_PERTURB
= 1
S_STEREO_SWING
= 96*0x10000
- = 96*
FRACUNIT
- = 96 fracunits
SURROUND_SEP
= -128
S_IFRACVOL
= 30
Mario Mode Sounds
The following sounds change in Mario mode:
Replaced Sound(s)
|
Mario Mode sound
|
6 - sfx_altow1 7 - sfx_altow2 8 - sfx_altow3 9 - sfx_altow4
|
100 - sfx_mario8
|
228 - sfx_thok
|
99 - sfx_mario7
|
119 - sfx_pop
|
97 - sfx_mario5
|
84 - sfx_jump
|
98 - sfx_mario6
|
208 - sfx_shield
|
95 - sfx_mario3
|
83 - sfx_itemup
|
96 - sfx_mario4
|
230 - sfx_tink
|
93 - sfx_mario1
|
41 - sfx_cgot
|
101 - sfx_mario9
|
91 - sfx_lose
|
94 - sfx_mario2
|
MAXNEWSOUNDS
= 10
PICKUP_SOUND
= 0x8000
- = 32768 (mask used to indicate sound origin is player item pickup)
sounds.h
NUMSKINSOUNDS
= 25 (Total number of sounds for characters)
NUMMUSIC
= 1049 (Total number of musicslots, including reserved tunes)
NUMSFX
= 1090 (Total number of sounds, including freeslots)
NUMSFXFREESLOTS
= 800
NUMSKINSFXSLOTS
= 32*NUMSKINSOUNDS
= 800
st_stuff.c/st_stuff.h
STARTBONUSPALS
= 9
NUMBONUSPALS
= 4
NUMHUDITEMS
= 35 (Total number of HUD Items)
ST_drawDebugInfo
Code - ST_drawDebugInfo
|
|
static void ST_drawDebugInfo(void)
{
char smomx[33];
char smomy[33];
char smomz[33];
char sspeed[33];
char sfloorz[33];
char spmomz[33];
char scability[33];
char scability2[33];
char scharsped[33];
char scharflags[33];
char sstrcolor[33];
char sdedtimer[33];
char sjumpfact[33];
char sx[33];
char sy[33];
char sz[33];
char sangle[33];
char sunderwater[33];
char smfjumped[33];
char smfspinning[33];
char smfstartdash[33];
char sjumping[33];
char sscoreadd[33];
if (!stplyr->mo)
return;
sprintf(smomx, "%d", stplyr->rmomx>>FRACBITS);
sprintf(smomy, "%d", stplyr->rmomy>>FRACBITS);
sprintf(smomz, "%d", stplyr->mo->momz>>FRACBITS);
sprintf(sspeed, "%d", stplyr->speed);
sprintf(sfloorz, "%d", stplyr->mo->floorz>>FRACBITS);
sprintf(spmomz, "%d", stplyr->mo->ceilingz>>FRACBITS);
sprintf(scability, "%d", stplyr->charability);
sprintf(scability2, "%d", stplyr->charability2);
sprintf(scharsped, "%d", stplyr->normalspeed);
sprintf(scharflags, "%d", stplyr->charflags);
#ifdef TRANSFIX
sprintf(sstrcolor, "%d", atoi(skins[stplyr->skin].starttranscolor));
#else
sprintf(sstrcolor, "%d", stplyr->starttranscolor);
#endif
sprintf(sdedtimer, "%d", stplyr->deadtimer);
sprintf(sjumpfact, "%d", stplyr->jumpfactor);
sprintf(sx, "%d", stplyr->mo->x>>FRACBITS);
sprintf(sy, "%d", stplyr->mo->y>>FRACBITS);
sprintf(sz, "%d", stplyr->mo->z>>FRACBITS);
sprintf(sangle, "%d", stplyr->mo->angle>>FRACBITS);
sprintf(sunderwater, "%d", stplyr->powers[pw_underwater]);
sprintf(smfjumped, "%u", (stplyr->pflags & PF_JUMPED));
sprintf(smfspinning, "%u", (stplyr->pflags & PF_SPINNING));
sprintf(smfstartdash, "%u", (stplyr->pflags & PF_STARTDASH));
sprintf(sjumping, "%d", stplyr->jumping);
sprintf(sscoreadd, "%d", stplyr->scoreadd);
V_DrawString(248, 0, 0, "MOMX =");
V_DrawString(296, 0, 0, smomx);
V_DrawString(248, 8, 0, "MOMY =");
V_DrawString(296, 8, 0, smomy);
V_DrawString(248, 16, 0, "MOMZ =");
V_DrawString(296, 16, 0, smomz);
V_DrawString(240, 24, 0, "SPEED =");
V_DrawString(296, 24, 0, sspeed);
V_DrawString(232, 32, 0, "FLOORZ=");
V_DrawString(288, 32, 0, sfloorz);
V_DrawString(240, 40, 0, "CEILZ =");
V_DrawString(296, 40, 0, spmomz);
V_DrawString(216, 48, 0, "CA =");
V_DrawString(248, 48, 0, scability);
V_DrawString(264, 48, 0, "CA2 =");
V_DrawString(304, 48, 0, scability2);
V_DrawString(216, 56, 0, "CHARSPED =");
V_DrawString(296, 56, 0, scharsped);
V_DrawString(216, 64, 0, "CHARFLGS =");
V_DrawString(296, 64, 0, scharflags);
V_DrawString(216, 72, 0, "STRCOLOR =");
V_DrawString(296, 72, 0, sstrcolor);
V_DrawString(216, 88, 0, "DEDTIMER =");
V_DrawString(296, 88, 0, sdedtimer);
V_DrawString(216, 96, 0, "JUMPFACT =");
V_DrawString(296, 96, 0, sjumpfact);
V_DrawString(240, 104, 0, "X =");
V_DrawString(264, 104, 0, sx);
V_DrawString(240, 112, 0, "Y =");
V_DrawString(264, 112, 0, sy);
V_DrawString(240, 120, 0, "Z =");
V_DrawString(264, 120, 0, sz);
V_DrawString(216, 128, 0, "Angle =");
V_DrawString(272, 128, 0, sangle);
V_DrawString(192, 152, 0, "Underwater =");
V_DrawString(288, 152, 0, sunderwater);
V_DrawString(192, 160, 0, "MF_JUMPED =");
V_DrawString(288, 160, 0, smfjumped);
V_DrawString(192, 168, 0, "MF_SPINNING =");
V_DrawString(296, 168, 0, smfspinning);
V_DrawString(192, 176, 0, "MF_STARDASH =");
V_DrawString(296, 176, 0, smfstartdash);
V_DrawString(192, 184, 0, "Jumping =");
V_DrawString(288, 184, 0, sjumping);
V_DrawString(192, 192, 0, "Scoreadd =");
V_DrawString(288, 192, 0, sscoreadd);
}
|
|
ST_drawContinueHUD
Code - ST_drawContinueHUD
|
|
static void ST_drawContinueHUD(void)
{
char stimeleft[33];
patch_t *contsonic;
// Do continue screen here.
// Initialize music
// For some reason the code doesn't like a simple ==...
if (stplyr->deadtimer < gameovertics && stplyr->deadtimer > gameovertics - 2)
{
// Force a screen wipe
stplyr->deadtimer--;
S_ChangeMusic(mus_contsc, false);
S_StopSounds();
oncontinuescreen = true;
if (rendermode != render_none)
{
// First, read the current screen
F_WipeStartScreen();
// Then, draw what the new screen will look like.
V_DrawFill(0, 0, vid.width, vid.height, 31);
contsonic = W_CachePatchName("CONT1", PU_CACHE);
V_DrawScaledPatch((BASEVIDWIDTH-SHORT(contsonic->width))/2, 64, 0, contsonic);
V_DrawString(128,128,0, "CONTINUE?");
sprintf(stimeleft, "%d", (stplyr->deadtimer - (gameovertics-11*TICRATE))/TICRATE);
V_DrawString(stplyr->deadtimer >= (gameovertics-TICRATE) ? 152 : 160,144,0, stimeleft);
// Now, read the end screen we want to fade to.
F_WipeEndScreen(0, 0, vid.width, vid.height);
// Do the wipe-io!
F_RunWipe(2*TICRATE, true);
}
}
V_DrawFill(0, 0, vid.width, vid.height, 31);
V_DrawString(128, 128, 0, "CONTINUE?");
// Draw a Sonic!
contsonic = W_CachePatchName("CONT1", PU_CACHE);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 64, 0, contsonic);
sprintf(stimeleft, "%d", (stplyr->deadtimer - (gameovertics-11*TICRATE))/TICRATE);
V_DrawString(stplyr->deadtimer >= (gameovertics-TICRATE) ? 152 : 160, 144, 0, stimeleft);
if (stplyr->deadtimer < (gameovertics-10*TICRATE))
Command_ExitGame_f();
if (stplyr->deadtimer < gameovertics-TICRATE && (stplyr->cmd.buttons & BT_JUMP || stplyr->cmd.buttons & BT_USE))
{
if (stplyr->continues != -1)
stplyr->continues--;
// Reset score
stplyr->score = 0;
// Allow tokens to come back if not a netgame.
if (!(netgame || multiplayer))
{
tokenlist = 0;
token = 0;
imcontinuing = true;
}
// Reset # of lives
if (ultimatemode)
stplyr->lives = 1;
else
stplyr->lives = 3;
// Clear any starpost data
stplyr->starpostangle = 0;
stplyr->starpostbit = 0;
stplyr->starpostnum = 0;
stplyr->starposttime = 0;
stplyr->starpostx = 0;
stplyr->starposty = 0;
stplyr->starpostz = 0;
contsonic = W_CachePatchName("CONT2", PU_CACHE);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 64, 0, contsonic);
}
}
|
|
ST_drawEmeraldHuntIcon
Distance from Emerald
|
Radar Color
|
Beeping interval
|
0 - 128 fracunits
|
Red
|
5 tics
|
128 - 512 fracunits
|
Orange
|
10 tics
|
512 - 1024 fracunits
|
Yellow
|
20 tics
|
1024 - 2048 fracunits
|
Green
|
30 tics
|
2048 - 3072 fracunits
|
Blue
|
35 tics (1 second)
|
3072 fracunits or more
|
Grey
|
None
|
Code - ST_drawEmeraldHuntIcon
|
|
static void ST_drawEmeraldHuntIcon(mobj_t *hunt, INT32 graphic)
{
patch_t *p;
INT32 interval;
fixed_t dist = P_AproxDistance(P_AproxDistance(stplyr->mo->x - hunt->x, stplyr->mo->y - hunt->y),
stplyr->mo->z - hunt->z);
if (dist < 128<<FRACBITS)
{
p = homing6;
interval = 5;
}
else if (dist < 512<<FRACBITS)
{
p = homing5;
interval = 10;
}
else if (dist < 1024<<FRACBITS)
{
p = homing4;
interval = 20;
}
else if (dist < 2048<<FRACBITS)
{
p = homing3;
interval = 30;
}
else if (dist < 3072<<FRACBITS)
{
p = homing2;
interval = 35;
}
else
{
p = homing1;
interval = 0;
}
V_DrawScaledPatch(hudinfo[graphic].x, STRINGY(hudinfo[graphic].y), V_TRANSLUCENT, p);
if (interval > 0 && leveltime % interval == 0)
S_StartSound(NULL, sfx_emfind);
}
|
|
Other
Var1 >> 16
or Var2 >> 16
= Upper 16 bits
Var1 & 65535
or Var2 & 65535
= Lower 16 bits
Reaction time
(Not to be confused with the Object Info property called ReactionTime
- that value is actually the starting value for the actor's reaction time, and doesn't change)
Actions that lower the actor's reaction time by 1 each time they are used:
Actions that perform effects when the actor's reaction time = 0:
Actions that set a new reaction time:
This value is set by adding a multiple of 4096 to the Thing Type number of the specified object.
- There are 16 possible values you can have for each Thing Type number (note that SRB2DB does not recognise
extrainfo
at all, and so will generally display Things with extrainfo
values of more than 0 as Unknown Thing Types):
- 0: +0 (Regular Thing Type number)
- 1: +4096
- 2: +8192
- 3: +12288
- 4: +16384
- 5: +20480
- 6: +24576
- 7: +28672
- 8: +32768
- 9: +36864
- 10: +40960
- 11: +45056
- 12: +49152
- 13: +53248
- 14: +57344
- 15: +61440
List of SRB2 Thing Types that use extrainfo
:
- Vanilla:
- XSRB2:
- Objects with
MF_ENEMY
- sets the starting size of the object:
extrainfo
= 1: destscale = 50 (half regular size)
extrainfo
= 2: destscale = 200 (double regular size)
extrainfo
= 1: destscale = 50 (half regular size)
Flame Jets
Shooting strength
|
Map Thing Number added
|
extrainfo / movedir value
|
Shooting strength
|
+0 (Regular Map Thing number)
|
0
|
20*FRACUNIT
|
+4096
|
1
|
20*FRACUNIT - (20*FRACUNIT /16)*1 = 20*FRACUNIT - 1.25*FRACUNIT = 18.75*FRACUNIT
|
+8192
|
2
|
20*FRACUNIT - (20*FRACUNIT /16)*2 = 20*FRACUNIT - 2.5*FRACUNIT = 17.5*FRACUNIT
|
+12288
|
3
|
20*FRACUNIT - (20*FRACUNIT /16)*3 = 20*FRACUNIT - 3.75*FRACUNIT = 16.25*FRACUNIT
|
+16384
|
4
|
20*FRACUNIT - (20*FRACUNIT /16)*4 = 20*FRACUNIT - 5*FRACUNIT = 15*FRACUNIT
|
+20480
|
5
|
20*FRACUNIT - (20*FRACUNIT /16)*5 = 20*FRACUNIT - 6.25*FRACUNIT = 13.75*FRACUNIT
|
+24576
|
6
|
20*FRACUNIT - (20*FRACUNIT /16)*6 = 20*FRACUNIT - 7.5*FRACUNIT = 12.5*FRACUNIT
|
+28672
|
7
|
20*FRACUNIT - (20*FRACUNIT /16)*7 = 20*FRACUNIT - 8.75*FRACUNIT = 11.25*FRACUNIT
|
+32768
|
8
|
20*FRACUNIT - (20*FRACUNIT /16)*8 = 20*FRACUNIT - 10*FRACUNIT = 10*FRACUNIT
|
+36864
|
9
|
20*FRACUNIT - (20*FRACUNIT /16)*9 = 20*FRACUNIT - 11.25*FRACUNIT = 8.75*FRACUNIT
|
+40960
|
10
|
20*FRACUNIT - (20*FRACUNIT /16)*10 = 20*FRACUNIT - 12.5*FRACUNIT = 7.5*FRACUNIT
|
+45056
|
11
|
20*FRACUNIT - (20*FRACUNIT /16)*11 = 20*FRACUNIT - 13.75*FRACUNIT = 6.25*FRACUNIT
|
+49152
|
12
|
20*FRACUNIT - (20*FRACUNIT /16)*12 = 20*FRACUNIT - 15*FRACUNIT = 5*FRACUNIT
|
+53248
|
13
|
20*FRACUNIT - (20*FRACUNIT /16)*13 = 20*FRACUNIT - 16.25*FRACUNIT = 3.75*FRACUNIT
|
+57344
|
14
|
20*FRACUNIT - (20*FRACUNIT /16)*14 = 20*FRACUNIT - 17.5*FRACUNIT = 2.5*FRACUNIT
|
+61440
|
15
|
20*FRACUNIT - (20*FRACUNIT /16)*15 =20*FRACUNIT - 18.75*FRACUNIT = 1.25*FRACUNIT
|
Off time
|
Angle ranges
|
threshold value
|
Off time
|
0 - 1023 or 8192 - 9215 or 16384 - 17407 or 24576 - 25599
|
0
|
2*TICRATE (Duration of S_FLAMEJETSTND ) + 1 (Duration of S_FLAMEJETSTOP ) = 70 + 1 = 71 tics = 2 seconds + 1 tic (Default time)
|
1024 - 2047 or 9216 - 10239 or 17408 - 18431 or 25600 - 26623
|
1
|
2*TICRATE + 1*(TICRATE /2) = 70 + 17.5 = 87.5 tics = 2.5 seconds
|
2048 - 3071 or 10240 - 11263 or 18432 - 19455 or 26624 - 27647
|
2
|
2*TICRATE + 2*(TICRATE /2) = 70 + 35 = 105 tics = 3 seconds
|
3072 - 4095 or 11264 - 12287 or 19456 - 20479 or 27648 - 28671
|
3
|
2*TICRATE + 3*(TICRATE /2) = 70 + 52.5 = 122.5 tics = 3.5 seconds
|
4096 - 5119 or 12288 - 13311 or 20480 - 21503 or 28672 - 29695
|
4
|
2*TICRATE + 4*(TICRATE /2) = 70 + 70 = 140 tics = 4 seconds
|
5120 - 6143 or 13312 - 14335 or 21504 - 22527 or 29696 - 30719
|
5
|
2*TICRATE + 5*(TICRATE /2) = 70 + 87.5 = 157.5 tics = 4.5 seconds
|
6144 - 7167 or 14336 - 15359 or 22528 - 23551 or 30720 - 31743
|
6
|
2*TICRATE + 6*(TICRATE /2) = 70 + 105 = 175 tics = 5 seconds
|
7168 - 8191 or 15360 - 16383 or 23552 - 24575 or 31744 - 32767
|
7
|
2*TICRATE + 7*(TICRATE /2) = 70 + 122.5 = 192.5 tics = 5.5 seconds
|
On time
|
Angle range
|
movecount value
|
On time
|
0 - 8191
|
0
|
3*TICRATE (Duration of S_FLAMEJETSTART ) = 105 tics = 3 seconds (Default time)
|
8192 - 16383
|
1
|
1*(TICRATE /2) = 17.5 tics = 0.5 seconds
|
16384 - 24575
|
2
|
2*(TICRATE /2) = 35 tics = 1 second
|
24576 - 32767
|
3
|
3*(TICRATE /2) = 52.5 tics = 1.5 seconds
|
Fan Particle Generator/A_ParticleSpawn
Time interval
|
Map Thing Number added
|
extrainfo value
|
Time interval (tics)
|
+0 (Regular Map Thing number)
|
0
|
1
|
+4096
|
1
|
2
|
+8192
|
2
|
3
|
+12288
|
3
|
4
|
+16384
|
4
|
5
|
+20480
|
5
|
6
|
+24576
|
6
|
7
|
+28672
|
7
|
8
|
+32768
|
8
|
9
|
+36864
|
9
|
10
|
+40960
|
10
|
11
|
+45056
|
11
|
12
|
+49152
|
12
|
13
|
+53248
|
13
|
14
|
+57344
|
14
|
15
|
+61440
|
15
|
16
|
Particle rising speed
|
Angle range
|
Speed (Fracunits)
|
-32768 - -28673
|
-8
|
-28672 - -24577
|
-7
|
-24576 - -20481
|
-6
|
-20480 - -16385
|
-5
|
-16384 - -12289
|
-4
|
-12288 - -8193
|
-3
|
-8192 - -4097
|
-2
|
-4096 - -1
|
-1
|
0 - 4095
|
0
|
4096 - 8191
|
1
|
8192 - 12287
|
2
|
12288 - 16383
|
3
|
16384 - 20479
|
4
|
20480 - 24575
|
5
|
24576 - 28671
|
6
|
28672 - 32767
|
7
|
Particle shrinking speed
|
Angle ranges
|
Shrinking Speed (scalespeed )
|
0 - 255 or 16384 - 16639 or -16384 - -16129 or -32768 - -32513
|
0
|
256 - 511 or 16640 - 16895 or -16128 - -15873 or -32512 - -32257
|
1
|
512 - 767 or 16896 - 17151 or -15872 - -15617 or -32256 - -32001
|
2
|
768 - 1023 or 17152 - 17407 or -15616 - -15361 or -32000 - -31745
|
3
|
1024 - 1279 or 17408 - 17663 or -15360 - -15105 or -31744 - -31489
|
4
|
1280 - 1535 or 17664 - 17919 or -15104 - -14849 or -31488 - -31233
|
5
|
1536 - 1791 or 17920 - 18175 or -14848 - -14593 or -31232 - -30977
|
6
|
1792 - 2047 or 18176 - 18431 or -14592 - -14337 or -30976 - -30721
|
7
|
2048 - 2303 or 18432 - 18687 or -14336 - -14081 or -30720 - -30465
|
8
|
2304 - 2559 or 18688 - 18943 or -14080 - -13825 or -30464 - -30209
|
9
|
2560 - 2815 or 18944 - 19199 or -13824 - -13569 or -30208 - -29953
|
10
|
2816 - 3071 or 19200 - 19455 or -13568 - -13313 or -29952 - -29697
|
11
|
3072 - 3327 or 19456 - 19711 or -13312 - -13057 or -29696 - -29441
|
12
|
3328 - 3583 or 19712 - 19967 or -13056 - -12801 or -29440 - -29185
|
13
|
3584 - 3839 or 19968 - 20223 or -12800 - -12545 or -29184 - -28929
|
14
|
3840 - 4095 or 20224 - 20479 or -12544 - -12289 or -28928 - -28673
|
15
|
4096 - 4351 or 20480 - 20735 or -12288 - -12033 or -28672 - -28417
|
16
|
4352 - 4607 or 20736 - 20991 or -12032 - -11777 or -28416 - -28161
|
17
|
4608 - 4863 or 20992 - 21247 or -11776 - -11521 or -28160 - -27905
|
18
|
4864 - 5119 or 21248 - 21503 or -11520 - -11265 or -27904 - -27649
|
19
|
5120 - 5375 or 21504 - 21759 or -11264 - -11009 or -27648 - -27393
|
20
|
5376 - 5631 or 21760 - 22015 or -11008 - -10753 or -27392 - -27137
|
21
|
5632 - 5887 or 22016 - 22271 or -10752 - -10497 or -27136 - -26881
|
22
|
5888 - 6143 or 22272 - 22527 or -10496 - -10241 or -26880 - -26625
|
23
|
6144 - 6399 or 22528 - 22783 or -10240 - -9985 or -26624 - -26369
|
24
|
6400 - 6655 or 22784 - 23039 or -9984 - -9729 or -26368 - -26113
|
25
|
6656 - 6911 or 23040 - 23295 or -9728 - -9473 or -26112 - -25857
|
26
|
6912 - 7167 or 23296 - 23551 or -9472 - -9217 or -25856 - -25601
|
27
|
7168 - 7423 or 23552 - 23807 or -9216 - -8961 or -25600 - -25345
|
28
|
7424 - 7679 or 23808 - 24063 or -8960 - -8705 or -25344 - -25089
|
29
|
7680 - 7935 or 24064 - 24319 or -8704 - -8449 or -25088 - -24833
|
30
|
7936 - 8191 or 24320 - 24575 or -8448 - -8193 or -24832 - -24577
|
31
|
8192 - 8447 or 24576 - 24831 or -8192 - -7937 or -24576 - -24321
|
32
|
8448 - 8703 or 24832 - 25087 or -7936 - -7681 or -24320 - -24065
|
33
|
8704 - 8959 or 25088 - 25343 or -7680 - -7425 or -24064 - -23809
|
34
|
8960 - 9215 or 25344 - 25599 or -7424 - -7169 or -23808 - -23553
|
35
|
9216 - 9471 or 25600 - 25855 or -7168 - -6913 or -23552 - -23297
|
36
|
9472 - 9727 or 25856 - 26111 or -6912 - -6657 or -23296 - -23041
|
37
|
9728 - 9983 or 26112 - 26367 or -6656 - -6401 or -23040 - -22785
|
38
|
9984 - 10239 or 26368 - 26623 or -6400 - -6145 or -22784 - -22529
|
39
|
10240 - 10495 or 26624 - 26879 or -6144 - -5889 or -22528 - -22273
|
40
|
10496 - 10751 or 26880 - 27135 or -5888 - -5633 or -22272 - -22017
|
41
|
10752 - 11007 or 27136 - 27391 or -5632 - -5377 or -22016 - -21761
|
42
|
11008 - 11263 or 27392 - 27647 or -5376 - -5121 or -21760 - -21505
|
43
|
11264 - 11519 or 27648 - 27903 or -5120 - -4865 or -21504 - -21249
|
44
|
11520 - 11775 or 27904 - 28159 or -4864 - -4609 or -21248 - -20993
|
45
|
11776 - 12031 or 28160 - 28415 or -4608 - -4353 or -20992 - -20737
|
46
|
12032 - 12287 or 28416 - 28671 or -4352 - -4097 or -20736 - -20481
|
47
|
12288 - 12543 or 28672 - 28927 or -4096 - -3841 or -20480 - -20225
|
48
|
12544 - 12799 or 28928 - 29183 or -3840 - -3585 or -20224 - -19969
|
49
|
12800 - 13055 or 29184 - 29439 or -3584 - -3328 or -19968 - -19713
|
50
|
13056 - 13311 or 29440 - 29695 or -3328 - -3073 or -19712 - -19457
|
51
|
13312 - 13567 or 29696 - 29551 or -3072 - -2817 or -19456 - -19201
|
52
|
13568 - 13823 or 29552 - 30207 or -2816 - -2561 or -19200 - -18945
|
53
|
13824 - 14079 or 30208 - 30463 or -2560 - -2305 or -18944 - -18689
|
54
|
14080 - 14335 or 30464 - 30719 or -2304 - -2049 or -18688 - -18433
|
55
|
14336 - 14591 or 30720 - 30975 or -2048 - -1793 or -18432 - -18177
|
56
|
14592 - 14847 or 30976 - 31231 or -1792 - -1537 or -18176 - -17921
|
57
|
14848 - 15103 or 31232 - 31487 or -1536 - -1281 or -17920 - -17665
|
58
|
15104 - 15359 or 31488 - 31743 or -1280 - -1025 or -17664 - -17409
|
59
|
15360 - 15615 or 31743 - 31999 or -1024 - -769 or -17408 - -17153
|
60
|
15616 - 15871 or 32000 - 32255 or -768 - -513 or -17152 - -16897
|
61
|
15872 - 16127 or 32256 - 32511 or -512 - -257 or -16896 - -16641
|
62
|
16128 - 16383 or 32512 - 32767 or -256 - -1 or -16640 - -16385
|
63
|
Linedef Type Speeds
- Linedef type 3 - Zoom Tube Parameters: 1/8 FU/tic * FU X distance
- Linedef type 4 - Speed Pad: 1 FU/tic * FU length
- Linedef type 9 - Chain Parameters: ? FU/tic * FU Y distance
- Linedef type 11 - Rope Parameters: 1/8 FU/tic * FU X distance
- Linedef type 12 - Rock Parameters: 1/16 FU/tic * FU length
- Linedef type 30 - Waving Flag: 1 FU/tic * FU length
- Linedef type 52 - Continuously Falling Sector: 1 FU/tic * FU length
- Linedef Types 53, 54, 55: 1/4 FU/tic * FU length
- Linedef Types 56, 57, 58: 1/4 FU/tic * FU X distance/Y distance
- Linedef type 59 - Activate Floating Platform: 2 FU/tic
- Linedef type 60 - Activate Floating Platform (Adjustable Speed): 1/4 FU/tic * FU length
- Linedef type 61 - Crusher (Ceiling to Floor):
- Without Effect 4: 1/8 FU/tic * FU length
- With Effect 4: 1/4 FU/tic * FU X distance
- Linedef type 62 - Crusher (Floor to Ceiling):
- Without Effect 4: 1/16 FU/tic * FU length
- With Effect 4: 1/8 FU/tic * FU X distance
- Linedef Types 190, 191, 192, 193, 194, 195: 1/4 FU/tic * FU length
- Linedef type 257 - Quicksand: 1/70 FU/tic (or 1/2 FU/second) * FU X distance
- Linedef type 259 - Custom FOF: (
FF_QUICKSAND
) 1/70 FU/tic (or 1/2 FU/second) * FU X distance
- Linedef Types 403, 404: 1/8 FU/tic * FU length
- Linedef Types 405, 407: 1/8 FU/tic * FU X distance
- Linedef type 428 - Start Platform Movement: 1/4 FU/tic * FU length
- Linedef Types 429, 431:
- Without Effect 4: 1/8 FU/tic * FU length
- With Effect 4: 1/4 FU/tic * FU X distance
- Linedef type 430 - Crush Floor Once: 1/4 FU/tic * FU X distance
- Linedef type 480 - PolyObject Door Slide: 1/8 FU/tic * Front Texture X offset units
- Linedef type 481 - PolyObject Door Swing: ? FU/tic * Front Texture X offset units
- Linedef Types 482, 483: 1/8 FU/tic * Front Texture X offset units
- Linedef Types 484, 485, 486, 487: ? FU/tic * Front Texture X offset units
- Linedef type 488 - PolyObject Move By Waypoints: 1/8 FU/tic * Front Texture X offset units
- Linedef Types 500, 501: 1 FU/tic
- Linedef type 502 - Scroll Wall According To Linedef: 1/32 FU/tic * FU length
- Linedef Types 503, 504: (Base speed) 1/32 FU/tic * FU length
- Linedef type 505 - Scroll Texture By Front Side Offsets: 1 FU/tic * Front Texture offset units
- Linedef type 506 - Scroll Texture By Back Side Offsets: 1 FU/tic * Back Texture offset units
Character Skin Color Reference Sheets
Vanilla SRB2
Value
|
Color Name
|
#1
|
#2
|
#3
|
#4
|
#5
|
#6
|
#7
|
#8
|
#9
|
#10
|
#11
|
#12
|
#13
|
#14
|
#15
|
#16
|
1
|
Cyan
|
208
|
209
|
210
|
211
|
212
|
213
|
214
|
215
|
216
|
217
|
218
|
219
|
220
|
221
|
222
|
223
|
2
|
Peach
|
64
|
65
|
66
|
67
|
68
|
69
|
70
|
71
|
72
|
73
|
74
|
75
|
76
|
77
|
78
|
79
|
3
|
Lavender
|
248
|
249
|
250
|
251
|
252
|
253
|
254
|
255
|
4
|
Silver
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
5
|
Orange
|
80
|
81
|
82
|
83
|
84
|
85
|
86
|
87
|
88
|
89
|
90
|
91
|
92
|
93
|
94
|
95
|
6
|
Red
|
125
|
126
|
127
|
128
|
129
|
130
|
131
|
132
|
133
|
134
|
135
|
136
|
137
|
138
|
139
|
140
|
7
|
Blue
|
224
|
225
|
226
|
227
|
228
|
229
|
230
|
231
|
232
|
233
|
234
|
235
|
236
|
237
|
238
|
239
|
8
|
Steel Blue
|
200
|
201
|
202
|
203
|
204
|
205
|
206
|
207
|
9
|
Pink
|
144
|
145
|
146
|
147
|
148
|
149
|
150
|
151
|
10
|
Beige
|
32
|
33
|
34
|
35
|
36
|
37
|
38
|
39
|
40
|
41
|
42
|
43
|
44
|
45
|
46
|
47
|
11
|
Purple
|
192
|
193
|
194
|
195
|
196
|
197
|
198
|
199
|
12
|
Green
|
160
|
161
|
162
|
163
|
164
|
165
|
166
|
167
|
168
|
169
|
170
|
171
|
172
|
173
|
174
|
175
|
13
|
White
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
14
|
Gold
|
112
|
113
|
114
|
115
|
116
|
117
|
118
|
119
|
15
|
Yellow
|
97
|
98
|
99
|
100
|
101
|
102
|
103
|
104
|
113
|
114
|
115
|
116
|
117
|
SRB2CB
Value
|
Color Name
|
#1
|
#2
|
#3
|
#4
|
#5
|
#6
|
#7
|
#8
|
#9
|
#10
|
#11
|
#12
|
#13
|
#14
|
#15
|
#16
|
1
|
Cyan
|
208
|
209
|
210
|
211
|
212
|
213
|
214
|
215
|
216
|
217
|
218
|
219
|
220
|
221
|
222
|
223
|
2
|
Peach
|
64
|
65
|
66
|
67
|
68
|
69
|
70
|
71
|
72
|
73
|
74
|
75
|
76
|
77
|
78
|
79
|
3
|
Lavender
|
248
|
249
|
250
|
251
|
252
|
253
|
254
|
255
|
4
|
Silver
|
0
|
2
|
4
|
6
|
8
|
10
|
12
|
14
|
16
|
18
|
20
|
22
|
24
|
26
|
28
|
30
|
5
|
Orange
|
80
|
81
|
82
|
83
|
84
|
85
|
86
|
87
|
88
|
89
|
90
|
91
|
92
|
93
|
94
|
95
|
6
|
Red
|
125
|
126
|
127
|
128
|
129
|
130
|
131
|
132
|
133
|
134
|
135
|
136
|
137
|
138
|
139
|
140
|
7
|
Blue
|
224
|
225
|
226
|
227
|
228
|
229
|
230
|
231
|
232
|
233
|
234
|
235
|
236
|
237
|
238
|
239
|
8
|
Steel Blue
|
200
|
201
|
202
|
203
|
204
|
205
|
206
|
207
|
9
|
Pink
|
144
|
145
|
146
|
147
|
148
|
149
|
150
|
151
|
10
|
Beige
|
32
|
33
|
34
|
35
|
36
|
37
|
38
|
39
|
40
|
41
|
42
|
43
|
44
|
45
|
46
|
47
|
11
|
Purple
|
192
|
193
|
194
|
195
|
196
|
197
|
198
|
199
|
12
|
Green
|
160
|
161
|
162
|
163
|
164
|
165
|
166
|
167
|
168
|
169
|
170
|
171
|
172
|
173
|
174
|
175
|
13
|
White
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
14
|
Gold
|
112
|
113
|
114
|
115
|
116
|
117
|
118
|
119
|
15
|
Yellow
|
97
|
98
|
99
|
100
|
101
|
102
|
103
|
104
|
113
|
114
|
115
|
116
|
117
|
16
|
Black
|
16
|
17
|
18
|
19
|
20
|
21
|
22
|
23
|
24
|
25
|
26
|
27
|
28
|
29
|
30
|
31
|
17
|
Dark Red
|
136
|
137
|
138
|
139
|
140
|
141
|
142
|
143
|
18
|
Dark Blue
|
231
|
232
|
233
|
234
|
235
|
236
|
237
|
238
|
239
|
240
|
241
|
242
|
243
|
244
|
245
|
246
|
19
|
Neon Green
|
184
|
185
|
186
|
187
|
20
|
Hot Pink
|
120
|
121
|
122
|
123
|
124
|
125
|
126
|
127
|
128
|
129
|
130
|
131
|
132
|
133
|
134
|
135
|
21
|
Brown
|
48
|
49
|
50
|
51
|
52
|
53
|
54
|
55
|
56
|
57
|
58
|
59
|
60
|
61
|
62
|
63
|
SRB2 Riders
Value
|
Color Name
|
#1
|
#2
|
#3
|
#4
|
#5
|
#6
|
#7
|
#8
|
#9
|
#10
|
#11
|
#12
|
#13
|
#14
|
#15
|
#16
|
1
|
Black
|
16
|
17
|
18
|
19
|
20
|
21
|
22
|
23
|
24
|
25
|
26
|
27
|
28
|
29
|
30
|
31
|
2
|
Grey
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
16
|
17
|
18
|
19
|
20
|
21
|
22
|
23
|
3
|
Silver
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
4
|
White
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
5
|
Pink
|
144
|
145
|
146
|
147
|
148
|
149
|
150
|
151
|
6
|
Light Red
|
120
|
121
|
122
|
123
|
124
|
125
|
126
|
127
|
128
|
129
|
130
|
131
|
132
|
133
|
134
|
135
|
7
|
Red
|
125
|
126
|
127
|
128
|
129
|
130
|
131
|
132
|
133
|
134
|
135
|
136
|
137
|
138
|
139
|
140
|
8
|
Dark Red
|
136
|
137
|
138
|
139
|
140
|
141
|
142
|
143
|
9
|
Purple
|
192
|
193
|
194
|
195
|
196
|
197
|
198
|
199
|
10
|
Lavender
|
248
|
249
|
250
|
251
|
252
|
253
|
254
|
255
|
11
|
Steel Blue
|
200
|
201
|
202
|
203
|
204
|
205
|
206
|
207
|
12
|
Dark Blue
|
231
|
232
|
233
|
234
|
235
|
236
|
237
|
238
|
239
|
240
|
241
|
242
|
243
|
244
|
245
|
246
|
13
|
Blue
|
224
|
225
|
226
|
227
|
228
|
229
|
230
|
231
|
232
|
233
|
234
|
235
|
236
|
237
|
238
|
239
|
14
|
Light Blue
|
224
|
225
|
226
|
227
|
228
|
229
|
230
|
231
|
15
|
Cyan
|
208
|
209
|
210
|
211
|
212
|
213
|
214
|
215
|
216
|
217
|
218
|
219
|
220
|
221
|
222
|
223
|
16
|
Neon Green
|
184
|
185
|
186
|
187
|
17
|
Green
|
160
|
161
|
162
|
163
|
164
|
165
|
166
|
167
|
168
|
169
|
170
|
171
|
172
|
173
|
174
|
175
|
18
|
Army
|
176
|
177
|
178
|
179
|
180
|
181
|
182
|
183
|
19
|
Yellow
|
97
|
98
|
99
|
100
|
101
|
102
|
103
|
104
|
113
|
114
|
115
|
116
|
117
|
20
|
Gold
|
112
|
113
|
114
|
115
|
116
|
117
|
118
|
119
|
21
|
Orange
|
80
|
81
|
82
|
83
|
84
|
85
|
86
|
87
|
88
|
89
|
90
|
91
|
92
|
93
|
94
|
95
|
22
|
Peach
|
64
|
65
|
66
|
67
|
68
|
69
|
70
|
71
|
72
|
73
|
74
|
75
|
76
|
77
|
78
|
79
|
23
|
Beige
|
32
|
33
|
34
|
35
|
36
|
37
|
38
|
39
|
40
|
41
|
42
|
43
|
44
|
45
|
46
|
47
|
24
|
Brown
|
48
|
49
|
50
|
51
|
52
|
53
|
54
|
55
|
56
|
57
|
58
|
59
|
60
|
61
|
62
|
63
|
25
|
Rosewood
|
152
|
153
|
154
|
155
|
156
|
157
|
158
|
159
|
Custom Skin Color Ideas
Value
|
Color Name
|
#1
|
#2
|
#3
|
#4
|
#5
|
#6
|
#7
|
#8
|
#9
|
#10
|
#11
|
#12
|
#13
|
#14
|
#15
|
#16
|
16
|
Cyan (Fixed)
|
208
|
209
|
210
|
211
|
212
|
213
|
214
|
215
|
216
|
217
|
218
|
219
|
17
|
Dark Orange
|
88
|
89
|
90
|
91
|
92
|
93
|
94
|
95
|
152
|
153
|
154
|
155
|
156
|
157
|
158
|
159
|
18
|
Dark Green
|
168
|
169
|
170
|
171
|
172
|
173
|
174
|
175
|
19
|
Dark Pink
|
144
|
145
|
146
|
147
|
148
|
149
|
150
|
151
|
134
|
135
|
136
|
137
|
138
|
139
|
140
|
141
|
20
|
Peach-Brown
|
72
|
73
|
74
|
75
|
76
|
77
|
78
|
79
|
48
|
49
|
50
|
51
|
52
|
53
|
54
|
55
|
21
|
Olive
|
105
|
106
|
107
|
108
|
109
|
110
|
111
|
31
|
22
|
Neon Green
|
184
|
185
|
186
|
187
|
188
|
189
|
190
|
191
|
23
|
Full-range Red
|
120
|
121
|
123
|
124
|
126
|
127
|
129
|
130
|
132
|
133
|
135
|
136
|
138
|
139
|
141
|
143
|
24
|
Full-range Blue
|
224
|
225
|
226
|
228
|
229
|
231
|
232
|
234
|
235
|
237
|
238
|
240
|
241
|
243
|
244
|
246
|
25
|
Full-range Orange
|
80
|
81
|
83
|
85
|
86
|
88
|
90
|
91
|
93
|
95
|
152
|
153
|
154
|
156
|
157
|
159
|
26
|
Full-range Peach-Brown
|
64
|
66
|
68
|
70
|
72
|
74
|
76
|
78
|
48
|
50
|
52
|
54
|
56
|
58
|
60
|
62
|
27
|
Robo-Hood Green
|
177
|
178
|
165
|
167
|
182
|
171
|
183
|
173
|
28
|
Light Green
|
160
|
161
|
162
|
163
|
164
|
165
|
166
|
167
|
29
|
Light Orange
|
80
|
81
|
82
|
83
|
84
|
85
|
86
|
87
|
30
|
Light Steel Blue
|
200
|
201
|
202
|
203
|
31
|
Light Army
|
176
|
177
|
178
|
179
|
32
|
Teal
|
220
|
221
|
222
|
223
|
33
|
Cerulean
|
216
|
217
|
218
|
219
|
34
|
Salmon
|
120
|
121
|
122
|
123
|
124
|
125
|
126
|
127
|
35
|
Golden Brown
|
112
|
113
|
114
|
115
|
116
|
117
|
118
|
119
|
156
|
157
|
158
|
159
|
36
|
Dark Army
|
176
|
177
|
178
|
179
|
180
|
181
|
182
|
183
|
173
|
174
|
175
|
31
|
37
|
Dark Steel Blue
|
200
|
201
|
202
|
203
|
204
|
205
|
206
|
238
|
239
|
240
|
241
|
242
|
243
|
244
|
245
|
246
|
38
|
Lilac
|
120
|
121
|
122
|
123
|
192
|
248
|
249
|
250
|
39
|
Pistachio
|
176
|
177
|
178
|
179
|
166
|
167
|
168
|
169
|
170
|
171
|
172
|
173
|
40
|
Turquoise
|
208
|
209
|
210
|
211
|
212
|
213
|
214
|
215
|
220
|
221
|
222
|
223
|
41
|
Ivory
|
120
|
0
|
1
|
2
|
4
|
6
|
8
|
10
|
42
|
Jet Black
|
200
|
201
|
202
|
203
|
204
|
205
|
206
|
207
|
28
|
29
|
30
|
31
|
43
|
Byzantium
|
192
|
248
|
249
|
250
|
251
|
252
|
253
|
254
|
255
|
29
|
30
|
31
|
44
|
Indigo
|
192
|
193
|
194
|
195
|
196
|
197
|
198
|
199
|
255
|
29
|
30
|
31
|
45
|
Dark Neon Green
|
187
|
188
|
189
|
190
|
191
|
175
|
30
|
31
|
46
|
Dark Rosewood
|
152
|
153
|
154
|
155
|
156
|
157
|
158
|
159
|
139
|
140
|
141
|
142
|
143
|
31
|
Vanilla SRB2 Character S_SKINs
Actions originating from Doom
The 4 Source Code-only SOC Actions!
A_BossZoom
Object Property |
Use
|
AttackSound |
Attacking sound
|
Speed |
Speed (Speed *5*FRACUNIT)
|
Code - A_BossZoom
|
|
// Function: A_BossZoom
//
// Description: Like A_SkullAttack, but used by Boss 1.
//
// var1 = unused
// var2 = unused
//
void A_BossZoom(mobj_t *actor)
{
mobj_t *dest;
angle_t an;
INT32 dist;
if (!actor->target)
return;
dest = actor->target;
actor->flags2 |= MF2_SKULLFLY;
if (actor->info->attacksound)
S_StartAttackSound(actor, actor->info->attacksound);
A_FaceTarget(actor);
an = actor->angle >> ANGLETOFINESHIFT;
actor->momx = FixedMul(actor->info->speed*5*FRACUNIT, FINECOSINE(an));
actor->momy = FixedMul(actor->info->speed*5*FRACUNIT, FINESINE(an));
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
dist = dist / (actor->info->speed*5*FRACUNIT);
if (dist < 1)
dist = 1;
actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist;
}
|
|
A_Boss1Chase
Object Property |
Use
|
MeleeState |
Attack State #1
|
MissileState |
Attack State #2
|
RaiseState |
Pinch Phase Attack
|
Damage |
When the boss' health points reaches this value, start pinch phase
|
Speed |
Chasing Speed
|
Code - A_Boss1Chase
|
|
// Function: A_Boss1Chase
//
// Description: Like A_Chase, but for Boss 1.
//
// var1 = unused
// var2 = unused
//
void A_Boss1Chase(mobj_t *actor)
{
INT32 delta;
if (actor->reactiontime)
actor->reactiontime--;
if (actor->z < actor->floorz+33*FRACUNIT)
actor->z = actor->floorz+33*FRACUNIT;
// turn towards movement direction if not there yet
if (actor->movedir < NUMDIRS)
{
actor->angle &= (7<<29);
delta = actor->angle - (actor->movedir << 29);
if (delta > 0)
actor->angle -= ANGLE_45;
else if (delta < 0)
actor->angle += ANGLE_45;
}
// do not attack twice in a row
if (actor->flags2 & MF2_JUSTATTACKED)
{
actor->flags2 &= ~MF2_JUSTATTACKED;
P_NewChaseDir(actor);
return;
}
if (actor->movecount)
goto nomissile;
if (!P_CheckMissileRange(actor))
goto nomissile;
if (actor->reactiontime <= 0)
{
if (actor->health > actor->info->damage)
{
if (P_Random() & 1)
P_SetMobjState(actor, actor->info->missilestate);
else
P_SetMobjState(actor, actor->info->meleestate);
}
else
P_SetMobjState(actor, actor->info->raisestate);
actor->flags2 |= MF2_JUSTATTACKED;
actor->reactiontime = 2*TICRATE;
return;
}
// ?
nomissile:
// possibly choose another target
if (multiplayer && P_Random() < 2)
{
if (P_LookForPlayers(actor, true, false, 0))
return; // got a new target
}
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
P_NewChaseDir(actor);
}
|
|
A_Boss2Chase
(If the actor is MT_EGGMOBILE2
, actor->watertop
= Speed
)
Angle Increment
actor->target->angle += FixedAngle(FixedDiv(FixedMul(actor->watertop, (actor->info->spawnhealth*(FRACUNIT/4)*3)), speedvar*FRACUNIT))
Angle Increment = (Speed
*(Spawnhealth
*0.75))/(health
*FRACUNIT
)
Egg Slimer - Angle Increment
|
Health points
|
Angle Increment
|
8
|
(2*FRACUNIT *(8*0.75))/(8*FRACUNIT ) = (2*FRACUNIT *6)/(8*FRACUNIT ) = (12*FRACUNIT )/(8*FRACUNIT ) = 12/8 = 1.5°
|
7
|
(2*FRACUNIT *(8*0.75))/(7*FRACUNIT ) = (2*FRACUNIT *6)/(7*FRACUNIT ) = (12*FRACUNIT )/(7*FRACUNIT ) = 12/7 = ~1.71°
|
6
|
(2*FRACUNIT *(8*0.75))/(6*FRACUNIT ) = (2*FRACUNIT *6)/(6*FRACUNIT ) = (12*FRACUNIT )/(6*FRACUNIT ) = 12/6 = 2°
|
5
|
(2*FRACUNIT *(8*0.75))/(5*FRACUNIT ) = (2*FRACUNIT *6)/(5*FRACUNIT ) = (12*FRACUNIT )/(5*FRACUNIT ) = 12/5 = 2.4°
|
4
|
(2*FRACUNIT *(8*0.75))/(4*FRACUNIT ) = (2*FRACUNIT *6)/(4*FRACUNIT ) = (12*FRACUNIT )/(4*FRACUNIT ) = 12/4 = 3°
|
3
|
(2*FRACUNIT *(8*0.75))/(3*FRACUNIT ) = (2*FRACUNIT *6)/(3*FRACUNIT ) = (12*FRACUNIT )/(3*FRACUNIT ) = 12/3 = 4°
|
(Since the Egg Slimer pogos around instead for Health Points 2 and below, I won't list their values here. :P )
Object Property |
Use
|
AttackSound |
Goop Spraying Sound
|
SpawnHealth |
Used to set the Angle Increment
|
PainChance |
Object number of goop to spawn
|
Speed |
Used to set Angle Increment
|
Code - A_Boss2Chase
|
|
// Function: A_Boss2Chase
//
// Description: Really doesn't 'chase', but rather goes in a circle.
//
// var1 = unused
// var2 = unused
//
void A_Boss2Chase(mobj_t *actor)
{
fixed_t radius;
boolean reverse = false;
INT32 speedvar;
if (actor->health <= 0)
return;
// When reactiontime hits zero, he will go the other way
if (actor->reactiontime)
actor->reactiontime--;
if (actor->reactiontime <= 0)
{
reverse = true;
actor->reactiontime = 2*TICRATE + P_Random();
}
P_SetTarget(&actor->target, P_GetClosestAxis(actor));
if (!actor->target) // This should NEVER happen.
{
CONS_Printf("Error: Boss2 has no target!\n");
A_BossDeath(actor);
return;
}
radius = actor->target->radius;
if (reverse)
actor->watertop = -actor->watertop;
// Only speed up if you have the 'Deaf' flag.
if (actor->flags & MF_AMBUSH)
speedvar = actor->health;
else
speedvar = actor->info->spawnhealth;
actor->target->angle += FixedAngle(FixedDiv(FixedMul(actor->watertop, (actor->info->spawnhealth*(FRACUNIT/4)*3)), speedvar*FRACUNIT)); // Don't use FixedAngleC!
P_UnsetThingPosition(actor);
{
const angle_t fa = actor->target->angle>>ANGLETOFINESHIFT;
const fixed_t fc = FixedMul(FINECOSINE(fa),radius);
const fixed_t fs = FixedMul(FINESINE(fa),radius);
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + fc, actor->target->y + fs);
actor->x = actor->target->x + fc;
actor->y = actor->target->y + fs;
}
P_SetThingPosition(actor);
// Spray goo once every second
if (leveltime % (speedvar*15/10)-1 == 0)
{
const fixed_t ns = 3 * FRACUNIT;
mobj_t *goop;
fixed_t fz = actor->z+actor->height+56*FRACUNIT;
angle_t fa;
// actor->movedir is used to determine the last
// direction goo was sprayed in. There are 8 possible
// directions to spray. (45-degree increments)
actor->movedir++;
actor->movedir %= NUMDIRS;
fa = (actor->movedir*FINEANGLES/8) & FINEMASK;
goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance);
goop->momx = FixedMul(FINESINE(fa),ns);
goop->momy = FixedMul(FINECOSINE(fa),ns);
goop->momz = 4*FRACUNIT;
goop->fuse = 30*TICRATE+P_Random();
if (actor->info->attacksound)
S_StartAttackSound(actor, actor->info->attacksound);
if (P_Random() & 1)
{
goop->momx *= 2;
goop->momy *= 2;
}
else if (P_Random() > 128)
{
goop->momx *= 3;
goop->momy *= 3;
}
actor->flags2 |= MF2_JUSTATTACKED;
}
}
|
|
A_Boss2Pogo
Object Property |
Use
|
RaiseState |
Pogoing state
|
AttackSound |
Pogoing sound
|
PainChance |
Object number of goop to spawn
|
Code - A_Boss2Pogo
|
|
// Function: A_Boss2Pogo
//
// Description: Pogo part of Boss 2 AI.
//
// var1 = unused
// var2 = unused
//
void A_Boss2Pogo(mobj_t *actor)
{
if (actor->z <= actor->floorz + 8*FRACUNIT && actor->momz <= 0)
{
P_SetMobjState(actor, actor->info->raisestate);
// Pogo Mode
}
else if (actor->momz < 0 && actor->reactiontime)
{
const fixed_t ns = 3 * FRACUNIT;
mobj_t *goop;
fixed_t fz = actor->z+actor->height+56*FRACUNIT;
angle_t fa;
INT32 i;
// spray in all 8 directions!
for (i = 0; i < 8; i++)
{
actor->movedir++;
actor->movedir %= NUMDIRS;
fa = (actor->movedir*FINEANGLES/8) & FINEMASK;
goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance);
goop->momx = FixedMul(FINESINE(fa),ns);
goop->momy = FixedMul(FINECOSINE(fa),ns);
goop->momz = 4*FRACUNIT;
#ifdef CHAOSISNOTDEADYET
if (gametype == GT_CHAOS)
goop->fuse = 15*TICRATE;
else
#endif
goop->fuse = 30*TICRATE+P_Random();
}
actor->reactiontime = 0;
if (actor->info->attacksound)
S_StartAttackSound(actor, actor->info->attacksound);
actor->flags2 |= MF2_JUSTATTACKED;
}
}
|
|
Test Wads
- FanParticleGenTest2.wad - Basically some test map showcasing 128 of the different angles you can set for Fan Particle Generators
Colormaps used in Vanilla SRB2
Name
|
Hex code (General color)
|
Hex code (Fade)
|
Generic Water
|
#40A0FFJ
|
Default (Black)
|
THZ Slime
|
#E000E0S
|
Default (Black)
|
THZ Alarm Floodlight
|
#FF0000Z
|
Default (Black)
|
ACZ Water
|
#0004FFJ
|
Default (Black)
|
RVZ Lava
|
#FF7F00Z
|
#FF7F00Z
|
ERZ1 Fog #1
|
#7F7F7FZ
|
#7F7F7FZ
|
ERZ1 Fog #2
|
#0000FFZ
|
#0000FFZ
|
ERZ2 Acid
|
#999999D
|
#00FF00Z
|
ERZ2 Gravity Change section Fog
|
#FF0000A
|
#FF00006
|
ERZ2 Teleport Fog
|
#999999D
|
#FFFF00Z
|
ERZ2 Misc Fog #1
|
#00AAFF0
|
#00AAFF0
|
ERZ2 Misc Fog #2
|
#FFFFFFF
|
#00FF000
|
ERZ2 Misc Fog #3
|
#999999D
|
#0000FFZ
|
ERZ2 Final Area Fog #1
|
#FF5500A
|
#FF55000
|
ERZ2 Final Area Fog #2
|
#FF6600A
|
#FF66000
|