P_SpawnMapThing(): Separated the giant post-Lua hook switch-case statement into its own function, and separated some of the larger cases into their own function as well

This commit is contained in:
MascaraSnake 2019-12-23 18:59:11 +01:00
parent 8ddd078b20
commit e382c2e094
1 changed files with 759 additions and 780 deletions

View File

@ -11890,63 +11890,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
return i;
}
//
// P_SpawnMapThing
// The fields of the mapthing should
// already be in host byte order.
//
void P_SpawnMapThing(mapthing_t *mthing)
{
mobjtype_t i;
mobj_t *mobj;
fixed_t x, y, z;
boolean doangle = true;
if (!mthing->type)
return; // Ignore type-0 things as NOPs
if (mthing->type == 3328) // 3D Mode start Thing
return;
if (!objectplacing && P_SpawnNonMobjMapThing(mthing))
return;
i = P_GetMobjtype(mthing->type);
if (i == MT_UNKNOWN)
CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y);
// Skip all returning/substitution code in objectplace.
if (!objectplacing)
{
if (!P_AllowMobjSpawn(mthing, i))
return;
i = P_GetMobjtypeSubstitute(mthing, i);
if (i == MT_NULL) // Don't spawn mobj
return;
}
// spawn it
x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
z = P_GetMobjSpawnHeight(i, mthing, x, y);
mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing;
#ifdef HAVE_BLUA
if (LUAh_MapThingSpawn(mobj, mthing))
{
if (P_MobjWasRemoved(mobj))
return;
}
else if (P_MobjWasRemoved(mobj))
return;
else
#endif
switch(mobj->type)
{
case MT_EMBLEM:
static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
{
INT32 j;
emblem_t* emblem = M_GetLevelEmblems(gamemap);
@ -11963,7 +11907,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (!emblem)
{
CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle);
break;
return false;
}
j = emblem - emblemlocations;
@ -12000,126 +11944,10 @@ void P_SpawnMapThing(mapthing_t *mthing)
}
}
}
break;
return true;
}
case MT_SKYBOX:
if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->extrainfo] = mobj;
else
skyboxviewpnts[mthing->extrainfo] = mobj;
break;
case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA)
{
mobj->color = SKINCOLOR_GOLD;
mobj->colorized = true;
}
break;
case MT_EGGMOBILE3:
mobj->cusval = mthing->extrainfo;
break;
case MT_FAN:
if (mthing->options & MTF_OBJECTSPECIAL)
{
P_UnsetThingPosition(mobj);
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
mobj->flags |= MF_NOSECTOR; // this flag basically turns it invisible
P_SetThingPosition(mobj);
}
if (mthing->angle)
mobj->health = mthing->angle;
else
mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS;
break;
case MT_METALSONIC_RACE:
case MT_METALSONIC_BATTLE:
case MT_FANG:
case MT_ROSY:
if (mthing->options & MTF_EXTRA)
{
mobj->color = SKINCOLOR_SILVER;
mobj->colorized = true;
mobj->flags2 |= MF2_SLIDEPUSH;
}
break;
case MT_BALLOON:
if (mthing->angle > 0)
mobj->color = ((mthing->angle-1) % (MAXSKINCOLORS-1))+1;
break;
#define makesoftwarecorona(mo, h) \
corona = P_SpawnMobjFromMobj(mo, 0, 0, h<<FRACBITS, MT_PARTICLE);\
corona->sprite = SPR_FLAM;\
corona->frame = (FF_FULLBRIGHT|FF_TRANS90|12);\
corona->tics = -1
case MT_FLAME:
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(mobj, 20);
P_SetScale(corona, (corona->destscale = mobj->scale*3));
P_SetTarget(&mobj->tracer, corona);
}
break;
case MT_FLAMEHOLDER:
if (!(mthing->options & MTF_OBJECTSPECIAL)) // Spawn the fire
{
mobj_t *flame = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME);
P_SetTarget(&flame->target, mobj);
flame->flags2 |= MF2_BOSSNOTRAP;
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(flame, 20);
P_SetScale(corona, (corona->destscale = flame->scale*3));
P_SetTarget(&flame->tracer, corona);
}
}
break;
case MT_CANDLE:
case MT_CANDLEPRICKET:
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176));
}
break;
#undef makesoftwarecorona
case MT_JACKO1:
case MT_JACKO2:
case MT_JACKO3:
if (!(mthing->options & MTF_EXTRA)) // take the torch out of the crafting recipe
{
mobj_t *overlay = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&overlay->target, mobj);
P_SetMobjState(overlay, mobj->info->raisestate);
}
break;
case MT_WATERDRIP:
if (mthing->angle)
mobj->tics = 3*TICRATE + mthing->angle;
else
mobj->tics = 3*TICRATE;
break;
case MT_FLAMEJET:
case MT_VERTICALFLAMEJET:
mobj->threshold = (mthing->angle >> 10) & 7;
mobj->movecount = (mthing->angle >> 13);
mobj->threshold *= (TICRATE/2);
mobj->movecount *= (TICRATE/2);
mobj->movedir = mthing->extrainfo;
break;
case MT_MACEPOINT:
case MT_CHAINMACEPOINT:
case MT_SPRINGBALLPOINT:
case MT_CHAINPOINT:
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
{
fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor;
angle_t mspokeangle;
@ -12139,7 +11967,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (line == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle);
return;
return false;
}
/*
mapthing -
@ -12203,9 +12031,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook;
mobj->angle = FixedAngle(myaw*FRACUNIT);
doangle = false;
mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->angle = FixedAngle(myaw << FRACBITS);
*doangle = false;
mobj->threshold = (FixedAngle(mpitch << FRACBITS) >> ANGLETOFINESHIFT);
mobj->movefactor = mpinch;
mobj->movedir = 0;
@ -12259,12 +12087,12 @@ ML_EFFECT5 : Don't stop thinking when too far away
}
if (!macetype && !chainlink)
break;
return true;
if (mobj->type == MT_CHAINPOINT)
{
if (!mlength)
break;
return true;
}
else
mlength++;
@ -12308,8 +12136,8 @@ ML_EFFECT5 : Don't stop thinking when too far away
msound = (mchainlike ? 0 : (mwidth & 1));
// Quick and easy preparatory variable setting
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
mphase = (FixedAngle(mphase << FRACBITS) >> ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll << FRACBITS) >> ANGLETOFINESHIFT);
#define makemace(mobjtype, dist, moreflags2) {\
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
@ -12431,12 +12259,11 @@ ML_EFFECT5 : Don't stop thinking when too far away
makemace(linktype, 0, 0);
}
}
#undef makemace
break;
return true;
}
case MT_PARTICLEGEN:
static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
{
fixed_t radius, speed;
INT32 type, numdivisions, anglespeed, ticcount;
@ -12450,7 +12277,7 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (line == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle);
return;
return false;
}
if (sides[lines[line].sidenum[0]].toptexture)
@ -12502,40 +12329,10 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->reactiontime = ticcount;
mobj->cvmem = line;
mobj->watertop = mobj->waterbottom = 0;
break;
return true;
}
case MT_ROCKSPAWNER:
mobj->threshold = mthing->angle;
mobj->movecount = mthing->extrainfo;
break;
case MT_POPUPTURRET:
if (mthing->angle)
mobj->threshold = mthing->angle;
else
mobj->threshold = (TICRATE*2)-1;
break;
case MT_NIGHTSBUMPER:
// Lower 4 bits specify the angle of
// the bumper in 30 degree increments.
mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc
P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold);
break;
case MT_EGGCAPSULE:
if (mthing->angle <= 0)
mthing->angle = 20; // prevent 0 health
mobj->health = mthing->angle;
mobj->threshold = min(mthing->extrainfo, 7);
break;
case MT_TUBEWAYPOINT:
mobj->health = mthing->angle & 255;
mobj->threshold = mthing->angle >> 8;
break;
case MT_IDEYAANCHOR:
mobj->health = mthing->extrainfo;
break;
case MT_NIGHTSDRONE:
static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj)
{
boolean flip = mthing->options & MTF_OBJECTFLIP;
boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA);
@ -12651,7 +12448,225 @@ ML_EFFECT5 : Don't stop thinking when too far away
goalpost->friction = mobj->height;
goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE);
}
return true;
}
static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong)
{
angle_t angle = FixedAngle(mthing->angle << FRACBITS);
fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t x2 = FINECOSINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y2 = FINESINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
statenum_t facestate = strong ? S_REDBOOSTERSEG_FACE : S_YELLOWBOOSTERSEG_FACE;
statenum_t leftstate = strong ? S_REDBOOSTERSEG_LEFT : S_YELLOWBOOSTERSEG_LEFT;
statenum_t rightstate = strong ? S_REDBOOSTERSEG_RIGHT : S_YELLOWBOOSTERSEG_RIGHT;
statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER;
mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle - ANGLE_90;
P_SetMobjState(seg, facestate);
seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle + ANGLE_90;
P_SetMobjState(seg, facestate);
seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, leftstate);
seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, rightstate);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, rollerstate);
return true;
}
static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
{
#ifdef HAVE_BLUA
boolean override = LUAh_MapThingSpawn(mobj, mthing);
if (P_MobjWasRemoved(mobj))
return false;
if (override)
return true;
#endif
switch (mobj->type)
{
case MT_EMBLEM:
{
if (!P_SetupEmblem(mthing, mobj))
return false;
break;
}
case MT_SKYBOX:
if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->extrainfo] = mobj;
else
skyboxviewpnts[mthing->extrainfo] = mobj;
break;
case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA)
{
mobj->color = SKINCOLOR_GOLD;
mobj->colorized = true;
}
break;
case MT_EGGMOBILE3:
mobj->cusval = mthing->extrainfo;
break;
case MT_FAN:
if (mthing->options & MTF_OBJECTSPECIAL)
{
P_UnsetThingPosition(mobj);
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
mobj->flags |= MF_NOSECTOR; // this flag basically turns it invisible
P_SetThingPosition(mobj);
}
if (mthing->angle)
mobj->health = mthing->angle;
else
mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS;
break;
case MT_METALSONIC_RACE:
case MT_METALSONIC_BATTLE:
case MT_FANG:
case MT_ROSY:
if (mthing->options & MTF_EXTRA)
{
mobj->color = SKINCOLOR_SILVER;
mobj->colorized = true;
mobj->flags2 |= MF2_SLIDEPUSH;
}
break;
case MT_BALLOON:
if (mthing->angle > 0)
mobj->color = ((mthing->angle - 1) % (MAXSKINCOLORS - 1)) + 1;
break;
#define makesoftwarecorona(mo, h) \
corona = P_SpawnMobjFromMobj(mo, 0, 0, h<<FRACBITS, MT_PARTICLE);\
corona->sprite = SPR_FLAM;\
corona->frame = (FF_FULLBRIGHT|FF_TRANS90|12);\
corona->tics = -1
case MT_FLAME:
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(mobj, 20);
P_SetScale(corona, (corona->destscale = mobj->scale*3));
P_SetTarget(&mobj->tracer, corona);
}
break;
case MT_FLAMEHOLDER:
if (!(mthing->options & MTF_OBJECTSPECIAL)) // Spawn the fire
{
mobj_t *flame = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME);
P_SetTarget(&flame->target, mobj);
flame->flags2 |= MF2_BOSSNOTRAP;
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(flame, 20);
P_SetScale(corona, (corona->destscale = flame->scale*3));
P_SetTarget(&flame->tracer, corona);
}
}
break;
case MT_CANDLE:
case MT_CANDLEPRICKET:
if (mthing->options & MTF_EXTRA)
{
mobj_t *corona;
makesoftwarecorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176));
}
break;
#undef makesoftwarecorona
case MT_JACKO1:
case MT_JACKO2:
case MT_JACKO3:
if (!(mthing->options & MTF_EXTRA)) // take the torch out of the crafting recipe
{
mobj_t *overlay = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&overlay->target, mobj);
P_SetMobjState(overlay, mobj->info->raisestate);
}
break;
case MT_WATERDRIP:
mobj->tics = 3*TICRATE + mthing->angle;
break;
case MT_FLAMEJET:
case MT_VERTICALFLAMEJET:
mobj->threshold = (mthing->angle >> 10) & 7;
mobj->movecount = (mthing->angle >> 13);
mobj->threshold *= (TICRATE/2);
mobj->movecount *= (TICRATE/2);
mobj->movedir = mthing->extrainfo;
break;
case MT_MACEPOINT:
case MT_CHAINMACEPOINT:
case MT_SPRINGBALLPOINT:
case MT_CHAINPOINT:
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
if (!P_SetupMace(mthing, mobj, doangle))
return false;
break;
case MT_PARTICLEGEN:
if (!P_SetupParticleGen(mthing, mobj))
return false;
break;
case MT_ROCKSPAWNER:
mobj->threshold = mthing->angle;
mobj->movecount = mthing->extrainfo;
break;
case MT_POPUPTURRET:
if (mthing->angle)
mobj->threshold = mthing->angle;
else
mobj->threshold = (TICRATE*2)-1;
break;
case MT_NIGHTSBUMPER:
// Lower 4 bits specify the angle of
// the bumper in 30 degree increments.
mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc
P_SetMobjState(mobj, mobj->info->spawnstate + mobj->threshold);
break;
case MT_EGGCAPSULE:
if (mthing->angle <= 0)
mthing->angle = 20; // prevent 0 health
mobj->health = mthing->angle;
mobj->threshold = min(mthing->extrainfo, 7);
break;
case MT_TUBEWAYPOINT:
mobj->health = mthing->angle & 255;
mobj->threshold = mthing->angle >> 8;
break;
case MT_IDEYAANCHOR:
mobj->health = mthing->extrainfo;
break;
case MT_NIGHTSDRONE:
if (!P_SetupNiGHTSDrone(mthing, mobj))
return false;
break;
case MT_HIVEELEMENTAL:
if (mthing->extrainfo)
@ -12675,9 +12690,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
case MT_THZTREE:
{ // Spawn the branches
angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS);
P_SpawnMobjFromMobj(mobj, 1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h;
P_SpawnMobjFromMobj(mobj, 0, 1*FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h;
P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270;
P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h;
P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h;
P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270;
}
break;
case MT_CEZPOLE1:
@ -12699,10 +12714,10 @@ ML_EFFECT5 : Don't stop thinking when too far away
leaf->angle = mobjangle;\
P_SetMobjState(leaf, leaf->info->seestate);\
mobjangle += ANGLE_90
doleaf(1*FRACUNIT, 0);
doleaf(0, 1*FRACUNIT);
doleaf(-1*FRACUNIT, 0);
doleaf(0, -1*FRACUNIT);
doleaf(FRACUNIT, 0);
doleaf(0, FRACUNIT);
doleaf(-FRACUNIT, 0);
doleaf(0, -FRACUNIT);
#undef doleaf
}
break;
@ -12743,87 +12758,20 @@ ML_EFFECT5 : Don't stop thinking when too far away
break;
}
case MT_REDBOOSTER:
{
angle_t angle = FixedAngle(mthing->angle << FRACBITS);
fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle-ANGLE_90;
P_SetMobjState(seg, S_REDBOOSTERSEG_FACE);
seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle+ANGLE_90;
P_SetMobjState(seg, S_REDBOOSTERSEG_FACE);
seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERSEG_LEFT);
seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERSEG_RIGHT);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_REDBOOSTERROLLER);
break;
}
case MT_YELLOWBOOSTER:
{
angle_t angle = FixedAngle(mthing->angle << FRACBITS);
fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK);
mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle-ANGLE_90;
P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE);
seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle+ANGLE_90;
P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE);
seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERSEG_LEFT);
seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERSEG_RIGHT);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERROLLER);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_SetMobjState(seg, S_YELLOWBOOSTERROLLER);
if (!P_SetupBooster(mthing, mobj, mobj->type == MT_REDBOOSTER))
return false;
break;
}
default:
break;
}
case MT_AXIS:
// Inverted if uppermost bit is set
if (mthing->angle & 16384)
mobj->flags2 |= MF2_AMBUSH;
if (mobj->flags & MF_BOSS)
{
if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss
mobj->flags2 |= MF2_BOSSNOTRAP;
}
if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) // Axis Points
{
if (mthing->angle > 0)
mobj->radius = (mthing->angle & 16383) << FRACBITS;
// FALLTHRU
case MT_AXISTRANSFER:
case MT_AXISTRANSFERLINE:
// Mare it belongs to
mobj->threshold = min(mthing->extrainfo, 7);
@ -12831,33 +12779,24 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->health = mthing->options;
mobj->flags2 |= MF2_AXIS;
if (i == MT_AXIS)
{
// Inverted if uppermost bit is set
if (mthing->angle & 16384)
mobj->flags2 |= MF2_AMBUSH;
if (mthing->angle > 0)
mobj->radius = (mthing->angle & 16383)*FRACUNIT;
}
}
else if (i == MT_TOKEN)
{
break;
case MT_TOKEN:
// We advanced tokenbits earlier due to the return check.
// Subtract 1 here for the correct value.
mobj->health = 1 << (tokenbits - 1);
}
else if (i == MT_CYBRAKDEMON && mthing->options & MTF_AMBUSH)
break;
case MT_CYBRAKDEMON:
if (mthing->options & MTF_AMBUSH)
{
mobj_t* elecmobj;
elecmobj = P_SpawnMobj(x, y, z, MT_CYBRAKDEMON_ELECTRIC_BARRIER);
elecmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_CYBRAKDEMON_ELECTRIC_BARRIER);
P_SetTarget(&elecmobj->target, mobj);
elecmobj->angle = FixedAngle(mthing->angle<<FRACBITS);;
elecmobj->angle = FixedAngle(mthing->angle << FRACBITS);
elecmobj->destscale = mobj->scale*2;
P_SetScale(elecmobj, elecmobj->destscale);
}
else if (i == MT_STARPOST)
break;
case MT_STARPOST:
{
thinker_t* th;
mobj_t* mo2;
@ -12884,9 +12823,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (!foundanother)
numstarposts++;
break;
}
else if (i == MT_SPIKE)
{
case MT_SPIKE:
// Pop up spikes!
if (mthing->options & MTF_OBJECTSPECIAL)
{
@ -12903,9 +12842,8 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->flags |= MF_SOLID;
P_SetThingPosition(mobj);
}
}
else if (i == MT_WALLSPIKE)
{
break;
case MT_WALLSPIKE:
// Pop up spikes!
if (mthing->options & MTF_OBJECTSPECIAL)
{
@ -12937,45 +12875,32 @@ ML_EFFECT5 : Don't stop thinking when too far away
P_SetTarget(&base->target, mobj);
P_SetTarget(&mobj->tracer, base);
}
}
break;
case MT_RING_BOX:
//count 10 ring boxes into the number of rings equation too.
if (i == MT_RING_BOX && nummaprings >= 0)
if (nummaprings >= 0)
nummaprings += 10;
if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED)
{
break;
case MT_BIGTUMBLEWEED:
case MT_LITTLETUMBLEWEED:
if (mthing->options & MTF_AMBUSH)
{
mobj->momz += FixedMul(16*FRACUNIT, mobj->scale);
if (P_RandomChance(FRACUNIT/2))
mobj->momx += FixedMul(16*FRACUNIT, mobj->scale);
else
mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale);
if (P_RandomChance(FRACUNIT/2))
mobj->momy += FixedMul(16*FRACUNIT, mobj->scale);
else
mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale);
fixed_t offset = FixedMul(16*FRACUNIT, mobj->scale);
mobj->momx += P_RandomChance(FRACUNIT/2) ? offset : -offset;
mobj->momy += P_RandomChance(FRACUNIT/2) ? offset : -offset;
mobj->momz += offset;
}
}
// CTF flag pointers
if (i == MT_REDFLAG)
{
break;
case MT_REDFLAG:
redflag = mobj;
rflagpoint = mobj->spawnpoint;
}
if (i == MT_BLUEFLAG)
{
break;
case MT_BLUEFLAG:
blueflag = mobj;
bflagpoint = mobj->spawnpoint;
}
// special push/pull stuff
if (i == MT_PUSH || i == MT_PULL)
{
break;
case MT_PUSH:
case MT_PULL:
mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ
if (mthing->options & MTF_AMBUSH)
@ -12984,14 +12909,68 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->health |= 2; // If object special is set, fade using XY
if (G_IsSpecialStage(gamemap))
P_SetMobjState(mobj, (mobj->type == MT_PUSH) ? S_GRAVWELLGREEN : S_GRAVWELLRED);
break;
default:
break;
}
if (mobj->flags & MF_BOSS)
{
if (i == MT_PUSH)
P_SetMobjState(mobj, S_GRAVWELLGREEN);
if (i == MT_PULL)
P_SetMobjState(mobj, S_GRAVWELLRED);
if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss
mobj->flags2 |= MF2_BOSSNOTRAP;
}
return true;
}
//
// P_SpawnMapThing
// The fields of the mapthing should
// already be in host byte order.
//
void P_SpawnMapThing(mapthing_t *mthing)
{
mobjtype_t i;
mobj_t *mobj;
fixed_t x, y, z;
boolean doangle = true;
if (!mthing->type)
return; // Ignore type-0 things as NOPs
if (mthing->type == 3328) // 3D Mode start Thing
return;
if (!objectplacing && P_SpawnNonMobjMapThing(mthing))
return;
i = P_GetMobjtype(mthing->type);
if (i == MT_UNKNOWN)
CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y);
// Skip all returning/substitution code in objectplace.
if (!objectplacing)
{
if (!P_AllowMobjSpawn(mthing, i))
return;
i = P_GetMobjtypeSubstitute(mthing, i);
if (i == MT_NULL) // Don't spawn mobj
return;
}
// spawn it
x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
z = P_GetMobjSpawnHeight(i, mthing, x, y);
mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing;
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
return;
if (doangle)
mobj->angle = FixedAngle(mthing->angle<<FRACBITS);