mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 15:32:33 +00:00
Adapt push/pull point to UDMF
This commit is contained in:
parent
2a2d70e7cf
commit
ebf692f143
9 changed files with 216 additions and 379 deletions
|
@ -4504,13 +4504,27 @@ udmf
|
|||
|
||||
754
|
||||
{
|
||||
title = "Push Point";
|
||||
title = "Push/Pull Point";
|
||||
sprite = "GWLGA0";
|
||||
}
|
||||
755
|
||||
{
|
||||
title = "Pull Point";
|
||||
sprite = "GWLRA0";
|
||||
arg0
|
||||
{
|
||||
title = "Radius";
|
||||
}
|
||||
arg1
|
||||
{
|
||||
title = "Strength";
|
||||
}
|
||||
arg2
|
||||
{
|
||||
title = "Flags";
|
||||
type = 12;
|
||||
enum
|
||||
{
|
||||
1 = "Fade using XY";
|
||||
2 = "Push using XYZ";
|
||||
4 = "Non-exclusive";
|
||||
}
|
||||
}
|
||||
}
|
||||
756
|
||||
{
|
||||
|
|
28
src/info.c
28
src/info.c
|
@ -20713,34 +20713,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
// for use with wind and current effects
|
||||
{ // MT_PULL
|
||||
755, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8, // radius
|
||||
8, // height
|
||||
0, // display offset
|
||||
10, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_GHOST
|
||||
-1, // doomednum
|
||||
S_THOK, // spawnstate
|
||||
|
|
|
@ -5046,7 +5046,6 @@ typedef enum mobj_type
|
|||
MT_CRUMBLEOBJ, // Sound generator for crumbling platform
|
||||
MT_TUBEWAYPOINT,
|
||||
MT_PUSH,
|
||||
MT_PULL,
|
||||
MT_GHOST,
|
||||
MT_OVERLAY,
|
||||
MT_ANGLEMAN,
|
||||
|
|
127
src/p_mobj.c
127
src/p_mobj.c
|
@ -9234,6 +9234,118 @@ static void P_DragonbomberThink(mobj_t *mobj)
|
|||
#undef DRAGONTURNSPEED
|
||||
}
|
||||
|
||||
static mobj_t *pushmobj;
|
||||
|
||||
#define PUSH_FACTOR 7
|
||||
|
||||
static inline boolean PIT_PushThing(mobj_t *thing)
|
||||
{
|
||||
if (thing->eflags & MFE_PUSHED)
|
||||
return false;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG)
|
||||
return false;
|
||||
|
||||
if (!pushmobj)
|
||||
return false;
|
||||
|
||||
if (!pushmobj->spawnpoint)
|
||||
return false;
|
||||
|
||||
// Allow this to affect pushable objects at some point?
|
||||
if (thing->player && !(thing->flags & (MF_NOGRAVITY|MF_NOCLIP)))
|
||||
{
|
||||
INT32 dist;
|
||||
INT32 speed;
|
||||
INT32 sx = pushmobj->x;
|
||||
INT32 sy = pushmobj->y;
|
||||
INT32 sz = pushmobj->z;
|
||||
fixed_t radius = pushmobj->spawnpoint->args[0] << FRACBITS;
|
||||
|
||||
if (pushmobj->spawnpoint->args[2] & TMPP_NOZFADE)
|
||||
dist = P_AproxDistance(thing->x - sx, thing->y - sy);
|
||||
else
|
||||
{
|
||||
// Make sure the Z is in range
|
||||
if (thing->z < sz - radius || thing->z > sz + radius)
|
||||
return false;
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), thing->z - sz);
|
||||
}
|
||||
|
||||
speed = (abs(pushmobj->spawnpoint->args[1]) - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1);
|
||||
|
||||
// If speed <= 0, you're outside the effective radius. You also have
|
||||
// to be able to see the push/pull source point.
|
||||
|
||||
// Written with bits and pieces of P_HomingAttack
|
||||
if ((speed > 0) && (P_CheckSight(thing, pushmobj)))
|
||||
{
|
||||
fixed_t tmpmomx, tmpmomy, tmpmomz;
|
||||
|
||||
if (pushmobj->spawnpoint->args[2] & TMPP_PUSHZ)
|
||||
{
|
||||
tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed);
|
||||
tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed);
|
||||
tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy) >> ANGLETOFINESHIFT;
|
||||
tmpmomx = FixedMul(speed, FINECOSINE(pushangle));
|
||||
tmpmomy = FixedMul(speed, FINESINE(pushangle));
|
||||
tmpmomz = 0;
|
||||
}
|
||||
|
||||
if (pushmobj->spawnpoint->args[1] > 0) // away!
|
||||
{
|
||||
tmpmomx *= -1;
|
||||
tmpmomy *= -1;
|
||||
tmpmomz *= -1;
|
||||
}
|
||||
|
||||
thing->momx += tmpmomx;
|
||||
thing->momy += tmpmomy;
|
||||
thing->momz += tmpmomz;
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
thing->player->cmomx += tmpmomx;
|
||||
thing->player->cmomy += tmpmomy;
|
||||
thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800);
|
||||
thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pushmobj->spawnpoint->args[2] & TMPP_NONEXCLUSIVE))
|
||||
thing->eflags |= MFE_PUSHED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void P_PointPushThink(mobj_t *mobj)
|
||||
{
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
fixed_t radius;
|
||||
|
||||
if (!mobj->spawnpoint)
|
||||
return;
|
||||
|
||||
// Seek out all pushable things within the force radius of this
|
||||
// point pusher. Crosses sectors, so use blockmap.
|
||||
radius = mobj->spawnpoint->args[0] << FRACBITS;
|
||||
|
||||
pushmobj = mobj;
|
||||
xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
for (by = yl; by <= yh; by++)
|
||||
P_BlockThingsIterator(bx, by, PIT_PushThing);
|
||||
}
|
||||
|
||||
static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||
{
|
||||
if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1))
|
||||
|
@ -9721,6 +9833,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
else
|
||||
mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1));
|
||||
break;
|
||||
case MT_PUSH:
|
||||
P_PointPushThink(mobj);
|
||||
break;
|
||||
case MT_SPINFIRE:
|
||||
if (mobj->flags & MF_NOGRAVITY)
|
||||
{
|
||||
|
@ -12956,18 +13071,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
blueflag = mobj;
|
||||
bflagpoint = mobj->spawnpoint;
|
||||
break;
|
||||
case MT_PUSH:
|
||||
case MT_PULL:
|
||||
mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ
|
||||
|
||||
if (mthing->options & MTF_AMBUSH)
|
||||
mobj->health |= 1; // If ambush is set, push using XYZ
|
||||
if (mthing->options & MTF_OBJECTSPECIAL)
|
||||
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;
|
||||
case MT_NIGHTSSTAR:
|
||||
if (maptol & TOL_XMAS)
|
||||
P_SetMobjState(mobj, mobj->info->seestate);
|
||||
|
|
|
@ -1537,7 +1537,6 @@ typedef enum
|
|||
tc_scroll,
|
||||
tc_friction,
|
||||
tc_pusher,
|
||||
tc_pointpusher,
|
||||
tc_laserflash,
|
||||
tc_lightfade,
|
||||
tc_executor,
|
||||
|
@ -2191,19 +2190,6 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
|
|||
WRITEINT32(save_p, ht->slider);
|
||||
}
|
||||
|
||||
static inline void SavePointPusherThinker(const thinker_t* th, const UINT8 type)
|
||||
{
|
||||
const pointpusher_t *ht = (const void *)th;
|
||||
WRITEUINT8(save_p, type);
|
||||
WRITEINT32(save_p, ht->magnitude);
|
||||
WRITEINT32(save_p, ht->radius);
|
||||
WRITEINT32(save_p, ht->x);
|
||||
WRITEINT32(save_p, ht->y);
|
||||
WRITEINT32(save_p, ht->z);
|
||||
WRITEINT32(save_p, ht->affectee);
|
||||
WRITEINT32(save_p, ht->exclusive);
|
||||
}
|
||||
|
||||
static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
|
||||
{
|
||||
const laserthink_t *ht = (const void *)th;
|
||||
|
@ -2523,11 +2509,6 @@ static void P_NetArchiveThinkers(void)
|
|||
SavePusherThinker(th, tc_pusher);
|
||||
continue;
|
||||
}
|
||||
else if (th->function.acp1 == (actionf_p1)T_PointPusher)
|
||||
{
|
||||
SavePointPusherThinker(th, tc_pointpusher);
|
||||
continue;
|
||||
}
|
||||
else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
|
||||
{
|
||||
SaveBounceCheeseThinker(th, tc_bouncecheese);
|
||||
|
@ -3344,21 +3325,6 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker)
|
|||
return &ht->thinker;
|
||||
}
|
||||
|
||||
static thinker_t* LoadPointPusherThinker(actionf_p1 thinker)
|
||||
{
|
||||
pointpusher_t *ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
|
||||
ht->thinker.function.acp1 = thinker;
|
||||
ht->magnitude = READINT32(save_p);
|
||||
ht->radius = READINT32(save_p);
|
||||
ht->x = READINT32(save_p);
|
||||
ht->y = READINT32(save_p);
|
||||
ht->z = READINT32(save_p);
|
||||
ht->affectee = READINT32(save_p);
|
||||
ht->exclusive = READINT32(save_p);
|
||||
ht->source = P_GetPushThing(ht->affectee);
|
||||
return &ht->thinker;
|
||||
}
|
||||
|
||||
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
|
||||
{
|
||||
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
||||
|
@ -3821,10 +3787,6 @@ static void P_NetUnArchiveThinkers(void)
|
|||
th = LoadPusherThinker((actionf_p1)T_Pusher);
|
||||
break;
|
||||
|
||||
case tc_pointpusher:
|
||||
th = LoadPointPusherThinker((actionf_p1)T_PointPusher);
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass);
|
||||
}
|
||||
|
|
|
@ -3146,6 +3146,28 @@ static void P_WriteConstant(INT32 constant, char **target)
|
|||
M_Memcpy(*target, buffer, strlen(buffer) + 1);
|
||||
}
|
||||
|
||||
static line_t *P_FindPointPushLine(taglist_t *list)
|
||||
{
|
||||
INT32 i, l;
|
||||
|
||||
for (i = 0; i < list->count; i++)
|
||||
{
|
||||
mtag_t tag = list->tags[i];
|
||||
TAG_ITER_LINES(tag, l)
|
||||
{
|
||||
if (Tag_FGet(&lines[l].tags) != tag)
|
||||
continue;
|
||||
|
||||
if (lines[l].special != 547)
|
||||
continue;
|
||||
|
||||
return &lines[l];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//For maps in binary format, converts setup of specials to UDMF format.
|
||||
static void P_ConvertBinaryMap(void)
|
||||
{
|
||||
|
@ -4851,6 +4873,41 @@ static void P_ConvertBinaryMap(void)
|
|||
{
|
||||
switch (mapthings[i].type)
|
||||
{
|
||||
case 754: //Push point
|
||||
case 755: //Pull point
|
||||
{
|
||||
subsector_t *ss = R_PointInSubsector(mapthings[i].x << FRACBITS, mapthings[i].y << FRACBITS);
|
||||
sector_t *s;
|
||||
line_t *line;
|
||||
|
||||
if (!ss)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Push/pull point: Placed outside of map bounds!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
s = ss->sector;
|
||||
line = P_FindPointPushLine(&s->tags);
|
||||
|
||||
if (!line)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Push/pull point: Unable to find line of type 547 tagged to sector %s!\n", sizeu1((size_t)(s - sectors)));
|
||||
break;
|
||||
}
|
||||
|
||||
mapthings[i].args[0] = mapthings[i].angle;
|
||||
mapthings[i].args[1] = P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS);
|
||||
if (mapthings[i].type == 755)
|
||||
mapthings[i].args[1] *= -1;
|
||||
if (mapthings[i].options & MTF_OBJECTSPECIAL)
|
||||
mapthings[i].args[2] |= TMPP_NOZFADE;
|
||||
if (mapthings[i].options & MTF_AMBUSH)
|
||||
mapthings[i].args[2] |= TMPP_PUSHZ;
|
||||
if (!(line->flags & ML_NOCLIMB))
|
||||
mapthings[i].args[2] |= TMPP_NONEXCLUSIVE;
|
||||
mapthings[i].type = 754;
|
||||
break;
|
||||
}
|
||||
case 762: //PolyObject spawn point (crush)
|
||||
{
|
||||
INT32 check = -1;
|
||||
|
|
287
src/p_spec.c
287
src/p_spec.c
|
@ -98,7 +98,6 @@ typedef struct
|
|||
static void P_SpawnScrollers(void);
|
||||
static void P_SpawnFriction(void);
|
||||
static void P_SpawnPushers(void);
|
||||
static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive);
|
||||
static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t z_mag, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000
|
||||
static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline);
|
||||
static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize);
|
||||
|
@ -5331,7 +5330,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I
|
|||
thinker_t *th;
|
||||
friction_t *f;
|
||||
pusher_t *p;
|
||||
pointpusher_t *pp;
|
||||
size_t sec2num;
|
||||
size_t i;
|
||||
|
||||
|
@ -5442,13 +5440,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I
|
|||
if (p->affectee == (INT32)sec2num)
|
||||
Add_Pusher(p->type, p->x_mag, p->y_mag, p->z_mag, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider);
|
||||
}
|
||||
else if (th->function.acp1 == (actionf_p1)T_PointPusher)
|
||||
{
|
||||
pp = (pointpusher_t *)th;
|
||||
|
||||
if (pp->affectee == (INT32)sec2num)
|
||||
Add_PointPusher(pp->magnitude, pp->source, pp->affectee, pp->exclusive);
|
||||
}
|
||||
|
||||
if(secthinkers) i++;
|
||||
else th = th->next;
|
||||
|
@ -6024,8 +6015,6 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
secthinkers[((friction_t *)th)->affectee].count++;
|
||||
else if (th->function.acp1 == (actionf_p1)T_Pusher)
|
||||
secthinkers[((pusher_t *)th)->affectee].count++;
|
||||
else if (th->function.acp1 == (actionf_p1)T_PointPusher)
|
||||
secthinkers[((pointpusher_t *)th)->affectee].count++;
|
||||
}
|
||||
|
||||
// Allocate each list, and then zero the count so we can use it to track
|
||||
|
@ -6046,8 +6035,6 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
secnum = ((friction_t *)th)->affectee;
|
||||
else if (th->function.acp1 == (actionf_p1)T_Pusher)
|
||||
secnum = ((pusher_t *)th)->affectee;
|
||||
else if (th->function.acp1 == (actionf_p1)T_PointPusher)
|
||||
secnum = ((pointpusher_t *)th)->affectee;
|
||||
|
||||
if (secnum != (size_t)-1)
|
||||
secthinkers[secnum].thinkers[secthinkers[secnum].count++] = th;
|
||||
|
@ -8328,26 +8315,6 @@ static void P_SpawnFriction(void)
|
|||
|
||||
#define PUSH_FACTOR 7
|
||||
|
||||
static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive)
|
||||
{
|
||||
pointpusher_t *p = Z_Calloc(sizeof * p, PU_LEVSPEC, NULL);
|
||||
|
||||
p->thinker.function.acp1 = (actionf_p1)T_PointPusher;
|
||||
p->source = source;
|
||||
p->magnitude = magnitude;
|
||||
p->exclusive = exclusive;
|
||||
|
||||
if (source) // point source exist?
|
||||
{
|
||||
p->radius = AngleFixed(source->angle);
|
||||
p->x = p->source->x;
|
||||
p->y = p->source->y;
|
||||
p->z = p->source->z;
|
||||
}
|
||||
p->affectee = affectee;
|
||||
P_AddThinker(THINK_MAIN, &p->thinker);
|
||||
}
|
||||
|
||||
/** Adds a pusher.
|
||||
*
|
||||
* \param type Type of push/pull effect.
|
||||
|
@ -8382,187 +8349,6 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t
|
|||
P_AddThinker(THINK_MAIN, &p->thinker);
|
||||
}
|
||||
|
||||
// PIT_PushThing determines the angle and magnitude of the effect.
|
||||
// The object's x and y momentum values are changed.
|
||||
static pointpusher_t *tmpusher; // pointpusher structure for blockmap searches
|
||||
|
||||
/** Applies a point pusher/puller to a thing.
|
||||
*
|
||||
* \param thing Thing to be pushed.
|
||||
* \return True if the thing was pushed.
|
||||
* \todo Make a more robust P_BlockThingsIterator() so the hidden parameter
|
||||
* ::tmpusher won't need to be used.
|
||||
* \sa T_Pusher
|
||||
*/
|
||||
static inline boolean PIT_PushThing(mobj_t *thing)
|
||||
{
|
||||
if (thing->eflags & MFE_PUSHED)
|
||||
return false;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG)
|
||||
return false;
|
||||
|
||||
if (!tmpusher->source)
|
||||
return false;
|
||||
|
||||
// Allow this to affect pushable objects at some point?
|
||||
if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE))
|
||||
{
|
||||
INT32 dist;
|
||||
INT32 speed;
|
||||
INT32 sx, sy, sz;
|
||||
|
||||
sx = tmpusher->x;
|
||||
sy = tmpusher->y;
|
||||
sz = tmpusher->z;
|
||||
|
||||
// don't fade wrt Z if health & 2 (mapthing has multi flag)
|
||||
if (tmpusher->source->health & 2)
|
||||
dist = P_AproxDistance(thing->x - sx,thing->y - sy);
|
||||
else
|
||||
{
|
||||
// Make sure the Z is in range
|
||||
if (thing->z < sz - tmpusher->radius || thing->z > sz + tmpusher->radius)
|
||||
return false;
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy),
|
||||
thing->z - sz);
|
||||
}
|
||||
|
||||
speed = (tmpusher->magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1);
|
||||
|
||||
// If speed <= 0, you're outside the effective radius. You also have
|
||||
// to be able to see the push/pull source point.
|
||||
|
||||
// Written with bits and pieces of P_HomingAttack
|
||||
if ((speed > 0) && (P_CheckSight(thing, tmpusher->source)))
|
||||
{
|
||||
if (thing->player->powers[pw_carry] != CR_NIGHTSMODE)
|
||||
{
|
||||
// only push wrt Z if health & 1 (mapthing has ambush flag)
|
||||
if (tmpusher->source->health & 1)
|
||||
{
|
||||
fixed_t tmpmomx, tmpmomy, tmpmomz;
|
||||
|
||||
tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed);
|
||||
tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed);
|
||||
tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed);
|
||||
if (tmpusher->source->type == MT_PUSH) // away!
|
||||
{
|
||||
tmpmomx *= -1;
|
||||
tmpmomy *= -1;
|
||||
tmpmomz *= -1;
|
||||
}
|
||||
|
||||
thing->momx += tmpmomx;
|
||||
thing->momy += tmpmomy;
|
||||
thing->momz += tmpmomz;
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
thing->player->cmomx += tmpmomx;
|
||||
thing->player->cmomy += tmpmomy;
|
||||
thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800);
|
||||
thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t pushangle;
|
||||
|
||||
pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy);
|
||||
if (tmpusher->source->type == MT_PUSH)
|
||||
pushangle += ANGLE_180; // away
|
||||
pushangle >>= ANGLETOFINESHIFT;
|
||||
thing->momx += FixedMul(speed, FINECOSINE(pushangle));
|
||||
thing->momy += FixedMul(speed, FINESINE(pushangle));
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle));
|
||||
thing->player->cmomy += FixedMul(speed, FINESINE(pushangle));
|
||||
thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800);
|
||||
thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NiGHTS-specific handling.
|
||||
//By default, pushes and pulls only affect the Z-axis.
|
||||
//By having the ambush flag, it affects the X-axis.
|
||||
//By having the object special flag, it affects the Y-axis.
|
||||
fixed_t tmpmomx, tmpmomy, tmpmomz;
|
||||
|
||||
if (tmpusher->source->health & 1)
|
||||
tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed);
|
||||
else
|
||||
tmpmomx = 0;
|
||||
|
||||
if (tmpusher->source->health & 2)
|
||||
tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed);
|
||||
else
|
||||
tmpmomy = 0;
|
||||
|
||||
tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed);
|
||||
|
||||
if (tmpusher->source->type == MT_PUSH) // away!
|
||||
{
|
||||
tmpmomx *= -1;
|
||||
tmpmomy *= -1;
|
||||
tmpmomz *= -1;
|
||||
}
|
||||
|
||||
thing->momx += tmpmomx;
|
||||
thing->momy += tmpmomy;
|
||||
thing->momz += tmpmomz;
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
thing->player->cmomx += tmpmomx;
|
||||
thing->player->cmomy += tmpmomy;
|
||||
thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800);
|
||||
thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpusher->exclusive)
|
||||
thing->eflags |= MFE_PUSHED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void T_PointPusher(pointpusher_t *p)
|
||||
{
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
sector_t *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 (GETSECSPECIAL(sec->special, 3) != 2)
|
||||
return;
|
||||
|
||||
// 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
|
||||
tmbbox[BOXTOP] = p->y + p->radius;
|
||||
tmbbox[BOXBOTTOM] = p->y - p->radius;
|
||||
tmbbox[BOXRIGHT] = p->x + p->radius;
|
||||
tmbbox[BOXLEFT] = p->x - p->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);
|
||||
}
|
||||
|
||||
/** Applies a pusher to all affected objects.
|
||||
*
|
||||
* \param p Thinker for the pusher effect.
|
||||
|
@ -8751,78 +8537,33 @@ void T_Pusher(pusher_t *p)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** Gets a push/pull object.
|
||||
*
|
||||
* \param s Sector number to look in.
|
||||
* \return Pointer to the first ::MT_PUSH or ::MT_PULL object found in the
|
||||
* sector.
|
||||
* \sa P_GetTeleportDestThing, P_GetStarpostThing, P_GetAltViewThing
|
||||
*/
|
||||
mobj_t *P_GetPushThing(UINT32 s)
|
||||
{
|
||||
mobj_t *thing;
|
||||
sector_t *sec;
|
||||
|
||||
sec = sectors + s;
|
||||
thing = sec->thinglist;
|
||||
while (thing)
|
||||
{
|
||||
switch (thing->type)
|
||||
{
|
||||
case MT_PUSH:
|
||||
case MT_PULL:
|
||||
return thing;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
thing = thing->snext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Spawns pushers.
|
||||
*
|
||||
* \todo Remove magic numbers.
|
||||
* \sa P_SpawnSpecials, Add_Pusher
|
||||
*/
|
||||
static void P_SpawnPushers(void)
|
||||
{
|
||||
size_t i;
|
||||
line_t *l = lines;
|
||||
mtag_t tag;
|
||||
register INT32 s;
|
||||
mobj_t *thing;
|
||||
fixed_t length, hspeed, dx, dy;
|
||||
|
||||
for (i = 0; i < numlines; i++, l++)
|
||||
{
|
||||
tag = Tag_FGet(&l->tags);
|
||||
switch (l->special)
|
||||
{
|
||||
case 541: // wind/current
|
||||
{
|
||||
fixed_t length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
|
||||
fixed_t hspeed = l->args[1] << FRACBITS;
|
||||
fixed_t dx = FixedMul(FixedDiv(l->dx, length), hspeed);
|
||||
fixed_t dy = FixedMul(FixedDiv(l->dy, length), hspeed);
|
||||
if (l->special != 541)
|
||||
continue;
|
||||
|
||||
if (l->args[0] == 0)
|
||||
Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, (INT32)(l->frontsector - sectors), -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE));
|
||||
else
|
||||
{
|
||||
TAG_ITER_SECTORS(l->args[0], s)
|
||||
Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 547: // push/pull
|
||||
TAG_ITER_SECTORS(tag, s)
|
||||
{
|
||||
thing = P_GetPushThing(s);
|
||||
if (thing) // No MT_P* means no effect
|
||||
Add_PointPusher(P_AproxDistance(l->dx >> FRACBITS, l->dy >> FRACBITS), thing, s, l->flags & ML_NOCLIMB);
|
||||
}
|
||||
break;
|
||||
length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
|
||||
hspeed = l->args[1] << FRACBITS;
|
||||
dx = FixedMul(FixedDiv(l->dx, length), hspeed);
|
||||
dy = FixedMul(FixedDiv(l->dy, length), hspeed);
|
||||
|
||||
if (l->args[0] == 0)
|
||||
Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, (INT32)(l->frontsector - sectors), -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE));
|
||||
else
|
||||
{
|
||||
TAG_ITER_SECTORS(l->args[0], s)
|
||||
Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
src/p_spec.h
23
src/p_spec.h
|
@ -343,6 +343,14 @@ typedef enum
|
|||
TMPF_NONEXCLUSIVE = 1<<1,
|
||||
} textmappusherflags_t;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TMPP_NOZFADE = 1,
|
||||
TMPP_PUSHZ = 1<<1,
|
||||
TMPP_NONEXCLUSIVE = 1<<2,
|
||||
} textmappointpushflags_t;
|
||||
|
||||
// GETSECSPECIAL (specialval, section)
|
||||
//
|
||||
// Pulls out the special # from a particular section.
|
||||
|
@ -874,17 +882,6 @@ typedef struct
|
|||
INT32 slider; /// < Should the player go into an uncontrollable slide?
|
||||
} pusher_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker; ///< Thinker structure for push/pull effect.
|
||||
mobj_t *source; ///< Point source.
|
||||
INT32 magnitude; ///< Vector strength.
|
||||
INT32 radius; ///< Effective radius.
|
||||
INT32 x, y, z; ///< Point source.
|
||||
INT32 affectee; ///< Number of affected sector.
|
||||
INT32 exclusive; /// < Once this affect has been applied to a mobj, no other pushers may affect it.
|
||||
} pointpusher_t;
|
||||
|
||||
// Model for disappearing/reappearing FOFs
|
||||
typedef struct
|
||||
{
|
||||
|
@ -941,10 +938,8 @@ typedef struct
|
|||
|
||||
void T_FadeColormap(fadecolormap_t *d);
|
||||
|
||||
// Prototype functions for pushers
|
||||
// Prototype function for pushers
|
||||
void T_Pusher(pusher_t *p);
|
||||
void T_PointPusher(pointpusher_t *p);
|
||||
mobj_t *P_GetPushThing(UINT32 s);
|
||||
|
||||
// Plane displacement
|
||||
typedef struct
|
||||
|
|
|
@ -66,8 +66,7 @@ void Command_Numthinkers_f(void)
|
|||
"\t2: P_NullPrecipThinker\n"
|
||||
"\t3: T_Friction\n"
|
||||
"\t4: T_Pusher\n"
|
||||
"\t5: T_PointPusher\n"
|
||||
"\t6: P_RemoveThinkerDelayed\n");
|
||||
"\t5: P_RemoveThinkerDelayed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,11 +103,6 @@ void Command_Numthinkers_f(void)
|
|||
CONS_Printf(M_GetText("Number of %s: "), "T_Pusher");
|
||||
break;
|
||||
case 5:
|
||||
start = end = THINK_MAIN;
|
||||
action = (actionf_p1)T_PointPusher;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "T_PointPusher");
|
||||
break;
|
||||
case 6:
|
||||
action = (actionf_p1)P_RemoveThinkerDelayed;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_RemoveThinkerDelayed");
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue