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

View file

@ -11890,63 +11890,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
return i; return i;
} }
// static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
// 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:
{ {
INT32 j; INT32 j;
emblem_t* emblem = M_GetLevelEmblems(gamemap); emblem_t* emblem = M_GetLevelEmblems(gamemap);
@ -11963,7 +11907,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (!emblem) if (!emblem)
{ {
CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle);
break; return false;
} }
j = emblem - emblemlocations; 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); static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
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:
{ {
fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor;
angle_t mspokeangle; angle_t mspokeangle;
@ -12139,7 +11967,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (line == -1) 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); 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 - mapthing -
@ -12203,9 +12031,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->lastlook = mspeed; mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook; mobj->movecount = mobj->lastlook;
mobj->angle = FixedAngle(myaw*FRACUNIT); mobj->angle = FixedAngle(myaw << FRACBITS);
doangle = false; *doangle = false;
mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT); mobj->threshold = (FixedAngle(mpitch << FRACBITS) >> ANGLETOFINESHIFT);
mobj->movefactor = mpinch; mobj->movefactor = mpinch;
mobj->movedir = 0; mobj->movedir = 0;
@ -12259,12 +12087,12 @@ ML_EFFECT5 : Don't stop thinking when too far away
} }
if (!macetype && !chainlink) if (!macetype && !chainlink)
break; return true;
if (mobj->type == MT_CHAINPOINT) if (mobj->type == MT_CHAINPOINT)
{ {
if (!mlength) if (!mlength)
break; return true;
} }
else else
mlength++; mlength++;
@ -12308,8 +12136,8 @@ ML_EFFECT5 : Don't stop thinking when too far away
msound = (mchainlike ? 0 : (mwidth & 1)); msound = (mchainlike ? 0 : (mwidth & 1));
// Quick and easy preparatory variable setting // Quick and easy preparatory variable setting
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT); mphase = (FixedAngle(mphase << FRACBITS) >> ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT); mroll = (FixedAngle(mroll << FRACBITS) >> ANGLETOFINESHIFT);
#define makemace(mobjtype, dist, moreflags2) {\ #define makemace(mobjtype, dist, moreflags2) {\
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ 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); makemace(linktype, 0, 0);
} }
} }
#undef makemace #undef makemace
return true;
break;
} }
case MT_PARTICLEGEN:
static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
{ {
fixed_t radius, speed; fixed_t radius, speed;
INT32 type, numdivisions, anglespeed, ticcount; INT32 type, numdivisions, anglespeed, ticcount;
@ -12450,7 +12277,7 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (line == -1) 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); 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) 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->reactiontime = ticcount;
mobj->cvmem = line; mobj->cvmem = line;
mobj->watertop = mobj->waterbottom = 0; mobj->watertop = mobj->waterbottom = 0;
return true;
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; static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj)
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:
{ {
boolean flip = mthing->options & MTF_OBJECTFLIP; boolean flip = mthing->options & MTF_OBJECTFLIP;
boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); 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->friction = mobj->height;
goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE); 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; break;
case MT_HIVEELEMENTAL: case MT_HIVEELEMENTAL:
if (mthing->extrainfo) if (mthing->extrainfo)
@ -12675,9 +12690,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
case MT_THZTREE: case MT_THZTREE:
{ // Spawn the branches { // Spawn the branches
angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS); angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS);
P_SpawnMobjFromMobj(mobj, 1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h; P_SpawnMobjFromMobj(mobj, 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, 0, 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_270;
} }
break; break;
case MT_CEZPOLE1: case MT_CEZPOLE1:
@ -12699,10 +12714,10 @@ ML_EFFECT5 : Don't stop thinking when too far away
leaf->angle = mobjangle;\ leaf->angle = mobjangle;\
P_SetMobjState(leaf, leaf->info->seestate);\ P_SetMobjState(leaf, leaf->info->seestate);\
mobjangle += ANGLE_90 mobjangle += ANGLE_90
doleaf(1*FRACUNIT, 0); doleaf(FRACUNIT, 0);
doleaf(0, 1*FRACUNIT); doleaf(0, FRACUNIT);
doleaf(-1*FRACUNIT, 0); doleaf(-FRACUNIT, 0);
doleaf(0, -1*FRACUNIT); doleaf(0, -FRACUNIT);
#undef doleaf #undef doleaf
} }
break; break;
@ -12743,87 +12758,20 @@ ML_EFFECT5 : Don't stop thinking when too far away
break; break;
} }
case MT_REDBOOSTER: 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: case MT_YELLOWBOOSTER:
{ if (!P_SetupBooster(mthing, mobj, mobj->type == MT_REDBOOSTER))
angle_t angle = FixedAngle(mthing->angle << FRACBITS); return false;
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);
break; break;
} case MT_AXIS:
default: // Inverted if uppermost bit is set
break; if (mthing->angle & 16384)
} mobj->flags2 |= MF2_AMBUSH;
if (mobj->flags & MF_BOSS) if (mthing->angle > 0)
{ mobj->radius = (mthing->angle & 16383) << FRACBITS;
if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss // FALLTHRU
mobj->flags2 |= MF2_BOSSNOTRAP; case MT_AXISTRANSFER:
} case MT_AXISTRANSFERLINE:
if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) // Axis Points
{
// Mare it belongs to // Mare it belongs to
mobj->threshold = min(mthing->extrainfo, 7); 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->health = mthing->options;
mobj->flags2 |= MF2_AXIS; mobj->flags2 |= MF2_AXIS;
break;
if (i == MT_AXIS) case MT_TOKEN:
{
// 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)
{
// We advanced tokenbits earlier due to the return check. // We advanced tokenbits earlier due to the return check.
// Subtract 1 here for the correct value. // Subtract 1 here for the correct value.
mobj->health = 1 << (tokenbits - 1); mobj->health = 1 << (tokenbits - 1);
} break;
else if (i == MT_CYBRAKDEMON && mthing->options & MTF_AMBUSH) case MT_CYBRAKDEMON:
if (mthing->options & MTF_AMBUSH)
{ {
mobj_t* elecmobj; 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); P_SetTarget(&elecmobj->target, mobj);
elecmobj->angle = FixedAngle(mthing->angle<<FRACBITS);; elecmobj->angle = FixedAngle(mthing->angle << FRACBITS);
elecmobj->destscale = mobj->scale*2; elecmobj->destscale = mobj->scale*2;
P_SetScale(elecmobj, elecmobj->destscale); P_SetScale(elecmobj, elecmobj->destscale);
} }
else if (i == MT_STARPOST) break;
case MT_STARPOST:
{ {
thinker_t* th; thinker_t* th;
mobj_t* mo2; mobj_t* mo2;
@ -12884,9 +12823,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (!foundanother) if (!foundanother)
numstarposts++; numstarposts++;
break;
} }
else if (i == MT_SPIKE) case MT_SPIKE:
{
// Pop up spikes! // Pop up spikes!
if (mthing->options & MTF_OBJECTSPECIAL) if (mthing->options & MTF_OBJECTSPECIAL)
{ {
@ -12903,9 +12842,8 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->flags |= MF_SOLID; mobj->flags |= MF_SOLID;
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
} }
} break;
else if (i == MT_WALLSPIKE) case MT_WALLSPIKE:
{
// Pop up spikes! // Pop up spikes!
if (mthing->options & MTF_OBJECTSPECIAL) 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(&base->target, mobj);
P_SetTarget(&mobj->tracer, base); P_SetTarget(&mobj->tracer, base);
} }
} break;
case MT_RING_BOX:
//count 10 ring boxes into the number of rings equation too. //count 10 ring boxes into the number of rings equation too.
if (i == MT_RING_BOX && nummaprings >= 0) if (nummaprings >= 0)
nummaprings += 10; nummaprings += 10;
break;
if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED) case MT_BIGTUMBLEWEED:
{ case MT_LITTLETUMBLEWEED:
if (mthing->options & MTF_AMBUSH) if (mthing->options & MTF_AMBUSH)
{ {
mobj->momz += FixedMul(16*FRACUNIT, mobj->scale); fixed_t offset = FixedMul(16*FRACUNIT, mobj->scale);
mobj->momx += P_RandomChance(FRACUNIT/2) ? offset : -offset;
if (P_RandomChance(FRACUNIT/2)) mobj->momy += P_RandomChance(FRACUNIT/2) ? offset : -offset;
mobj->momx += FixedMul(16*FRACUNIT, mobj->scale); mobj->momz += offset;
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);
} }
} break;
case MT_REDFLAG:
// CTF flag pointers
if (i == MT_REDFLAG)
{
redflag = mobj; redflag = mobj;
rflagpoint = mobj->spawnpoint; rflagpoint = mobj->spawnpoint;
} break;
if (i == MT_BLUEFLAG) case MT_BLUEFLAG:
{
blueflag = mobj; blueflag = mobj;
bflagpoint = mobj->spawnpoint; bflagpoint = mobj->spawnpoint;
} break;
case MT_PUSH:
// special push/pull stuff case MT_PULL:
if (i == MT_PUSH || i == MT_PULL)
{
mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ
if (mthing->options & MTF_AMBUSH) 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 mobj->health |= 2; // If object special is set, fade using XY
if (G_IsSpecialStage(gamemap)) 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) if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss
P_SetMobjState(mobj, S_GRAVWELLGREEN); mobj->flags2 |= MF2_BOSSNOTRAP;
if (i == MT_PULL)
P_SetMobjState(mobj, S_GRAVWELLRED);
} }
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) if (doangle)
mobj->angle = FixedAngle(mthing->angle<<FRACBITS); mobj->angle = FixedAngle(mthing->angle<<FRACBITS);