Merge branch 'flat_alignment_revamp' into 'master'

Revamps of several dated linedef type effects

Felt like being productive so made some things I hate suck less.

Linedef type 7 (flat alignment) now works as follows.
* Linedef angle (from v1 to v2) is flat angle.
* Origin of flat is manipulated to match v1's coordinates - unless ML_NOKNUX is flagged, in which case uses frontside x and y offsets as flat offsets instead.
* ML_NOSONIC prevents changing floor.
* ML_NOTAILS prevents changing ceiling.
* Both of the above flags at once prints a warning.
* (THZ and probably a few other maps need updating.)

Linedef type 540 (friction) now works as follows.
* Controlled by x offset instead of length - offset of -100 is maximum iciness, offset of +483(!!!) is the maximum sludginess BUT things are scaled such that +100 is about the maximum sludginess any reasonable human being would want in a level, 0 is ORIG_FRICTION)
* Not reliant on a sector special to function (can be applied solely by tag to in-map sectors or solid FOF control sectors)
* Uses less memory, perform less calculations, and not bug out objects which just happen to use movefactor for something
* PHYSICS CHANGE: Low friction surfaces actively impede your acceleration (and make your animation speeds faster to give off that Looney Tunes out-of-control effect)
* (ACZ and Frozen Hillside needs updating.)

Sector types 1 and 3 in section 3 no longer do anything.

Linedef type 3 (zoom tube) now works as follows.
* Abs of frontside x offset is speed in units of FRACUNIT/8.
* Abs of frontside y offset is waypoint sequence number.
* Effect 4 flag rotates the player to match the waypoint direction (same as before).
* (ERZ needs updating.)

Linedef type 11 (rope hang) now works as follows.
* Abs of frontside x offset is speed in units of FRACUNIT/8.
* Abs of frontside y offset is waypoint sequence number.
* Effect 1 flag makes rope transfer one-way. (same as before)
* No climb flag makes rope static. (same as before)
* (ACZ and maybe ERZ need updating.)

Linedef type 258 (laser) is almost the same as before, but has altered functionality.
* Its flashing is less obnoxious. (56.25% to 68.75% instead of 100% to 0%, at half the speed)

Linedef type 14 (Bustable block parameters) is new, and works as follows.
* Tagged to the control sector of a block that is likely to be busted (via executor or collision, doesn't matter)
* Concatenation of frontside textures is MT_ object type to spawn, defaults to MT_ROCKCRUMBLE1 if not present
* Sound played when being busted is object type's activesound
* Frontside x offset is spacing (in fracunits) of spawned particles, defaults to 32<<FRACBITS
* Frontside y offset is the fuse of spawned particles in tics, defaults to 3*TICRATE, if set to -1 fuse is not set
* Effect 1 flag makes particles "fly out" horizontally and vertically from the center of the FOF

Sector types 7 through 15 in section 3 no longer do anything.

Linedef type 250 (Mario Block) is almost the same as before, but has new functionality and is slightly different in another way.
* No Climb flag turns it into a brick block (set on Custom FOF via presence of FF_SHATTERBOTTOM - busts when hit from the bottom, player hits their head/fist/whatever, no more upwards momentum)
* Effect 1 flag makes it an invisible block (set on Custom FOF via absence of (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL) - intangible from every side except the bottom. Becomes visible and tangible when it's hit once)
* Only updates side textures when moving down or stationary, not whilst moving up - more fidelity to the source material, less processing on the CPU, everyone wins.
* If FOF master linedef has a backside, then: [If there's items in it the FOF's flats are set to that of the backside sector's ceiling, otherwise the floor.] Otherwise, no flat change.

Linedef type 4 (Speed Pad parameters) now works as follows.
* Frontside x offset is speed in fracunits.
* Effect 4 flag doesn't center the player. (same as before)
* Effect 5 flag sends them off in rolling frames.
* Frontside upper texture is sound to play on launch, defaults to sfx_spdpad when not given

Sector type 6 in section 3 no longer does anything.

Object type 757 is changed as follows, and no longer works on its own - see Linedef type 15 for more details.
* Tag via its angle field
* Number of objects to spawn per tic around it via its z field, if zero then just spawn at center
* Is flipped if given MTF_OBJECTFLIP.
* (ERZ and Seraphic Skylands - if we use that map - needs updating)

Linedef type 15 (Fan particle spawner parameters) is new, and works as follows.
* Tag is tag of object(s!)
* Object type set via concatenation of frontside textures, MT_PARTICLE is default
* The length of the linedef is the radius the particle is spawned out (zeroed if z field is 0)
* Frontside x offset is speed upwards
* Frontside y offset is number of degrees to turn each tic (zeroed if z field is 0)
* Frontside floor and ceiling heights are the heights in which the particle is bound through some fun mathematics

A_ParticleSpawn is changed, too.
* Object type is now changed through actor->threshold instead of var1 to support Linedef type 15.

Test executable uploaded at /toaster/srb2win_branch_flatalignment.exe on the ftp.

Test file uploaded at /toaster/flatalignment.wad on the ftp.

Breaks compatibility with 2.1 so put in internal.

See merge request !29
This commit is contained in:
Monster Iestyn 2017-01-24 16:49:43 -05:00
commit fb8140312b
9 changed files with 412 additions and 219 deletions

View file

@ -14335,7 +14335,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14362,7 +14362,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14389,7 +14389,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14416,7 +14416,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14443,7 +14443,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14470,7 +14470,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14497,7 +14497,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14524,7 +14524,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14551,7 +14551,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14578,7 +14578,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14605,7 +14605,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14632,7 +14632,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14659,7 +14659,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14686,7 +14686,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14713,7 +14713,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14740,7 +14740,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View file

@ -3541,41 +3541,49 @@ void A_ScoreRise(mobj_t *actor)
// Function: A_ParticleSpawn // Function: A_ParticleSpawn
// //
// Description: Spawns a particle at a specified interval // Description: Hyper-specialised function for spawning a particle for MT_PARTICLEGEN.
// //
// var1 = type (if 0, defaults to MT_PARTICLE) // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ParticleSpawn(mobj_t *actor) void A_ParticleSpawn(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 i = 0;
fixed_t speed;
mobjtype_t type;
mobj_t *spawn; mobj_t *spawn;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_ParticleSpawn", actor)) if (LUA_CallAction("A_ParticleSpawn", actor))
return; return;
#endif #endif
if (!actor->spawnpoint) if (!actor->health)
{
P_RemoveMobj(actor);
return; return;
if (!actor->lastlook)
return;
if (!actor->threshold)
return;
for (i = 0; i < actor->lastlook; i++)
{
spawn = P_SpawnMobj(
actor->x + FixedMul(FixedMul(actor->friction, actor->scale), FINECOSINE(actor->angle>>ANGLETOFINESHIFT)),
actor->y + FixedMul(FixedMul(actor->friction, actor->scale), FINESINE(actor->angle>>ANGLETOFINESHIFT)),
actor->z,
(mobjtype_t)actor->threshold);
P_SetScale(spawn, actor->scale);
spawn->momz = FixedMul(actor->movefactor, spawn->scale);
spawn->destscale = spawn->scale/100;
spawn->scalespeed = spawn->scale/actor->health;
spawn->tics = (tic_t)actor->health;
spawn->flags2 |= (actor->flags2 & MF2_OBJECTFLIP);
spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
if (spawn->frame & FF_ANIMATE)
spawn->frame += P_RandomKey(spawn->state->var1);
actor->angle += actor->movedir;
} }
actor->angle += (angle_t)actor->movecount;
if (locvar1)
type = (mobjtype_t)locvar1;
else
type = MT_PARTICLE;
speed = FixedMul((actor->spawnpoint->angle >> 12)<<FRACBITS, actor->scale);
spawn = P_SpawnMobj(actor->x, actor->y, actor->z, type);
P_SetScale(spawn, actor->scale);
spawn->momz = speed;
spawn->destscale = FixedDiv(spawn->scale<<FRACBITS, 100<<FRACBITS);
spawn->scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) << FRACBITS, 100<<FRACBITS);
actor->tics = actor->spawnpoint->extrainfo + 1;
} }
// Function: A_BunnyHop // Function: A_BunnyHop

View file

@ -13,7 +13,11 @@
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "m_random.h"
#include "p_local.h" #include "p_local.h"
#ifdef ESLOPE
#include "p_slopes.h"
#endif
#include "r_state.h" #include "r_state.h"
#include "s_sound.h" #include "s_sound.h"
#include "z_zone.h" #include "z_zone.h"
@ -1141,6 +1145,7 @@ void T_MarioBlock(levelspecthink_t *block)
block->sector->ceilingdata = NULL; block->sector->ceilingdata = NULL;
block->sector->floorspeed = 0; block->sector->floorspeed = 0;
block->sector->ceilspeed = 0; block->sector->ceilspeed = 0;
block->direction = 0;
} }
for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;) for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;)
@ -1800,10 +1805,24 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
void T_MarioBlockChecker(levelspecthink_t *block) void T_MarioBlockChecker(levelspecthink_t *block)
{ {
line_t *masterline = block->sourceline; line_t *masterline = block->sourceline;
if (block->vars[2] == 1) // Don't update the textures when the block's being bumped upwards.
return;
if (SearchMarioNode(block->sector->touching_thinglist)) if (SearchMarioNode(block->sector->touching_thinglist))
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; {
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; // Update textures
if (masterline->backsector)
{
block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->ceilingpic; // Update flats to be backside's ceiling
}
}
else else
{
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture; sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture;
if (masterline->backsector)
{
block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->floorpic; // Update flats to be backside's floor
}
}
} }
// This is the Thwomp's 'brain'. It looks around for players nearby, and if // This is the Thwomp's 'brain'. It looks around for players nearby, and if
@ -2903,18 +2922,41 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
size_t topmostvertex = 0, bottommostvertex = 0; size_t topmostvertex = 0, bottommostvertex = 0;
fixed_t leftx, rightx; fixed_t leftx, rightx;
fixed_t topy, bottomy; fixed_t topy, bottomy;
fixed_t topz; fixed_t topz, bottomz;
fixed_t widthfactor, heightfactor;
fixed_t a, b, c; fixed_t a, b, c;
mobjtype_t type = MT_ROCKCRUMBLE1; mobjtype_t type = MT_ROCKCRUMBLE1;
fixed_t spacing = (32<<FRACBITS);
tic_t lifetime = 3*TICRATE;
INT16 flags = 0;
// If the control sector has a special #define controlsec rover->master->frontsector
// of Section3:7-15, use the custom debris.
if (GETSECSPECIAL(rover->master->frontsector->special, 3) >= 8) if (controlsec->tag != 0)
type = MT_ROCKCRUMBLE1+(GETSECSPECIAL(rover->master->frontsector->special, 3)-7); {
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1);
if (tagline != -1)
{
if (sides[lines[tagline].sidenum[0]].toptexture)
type = (mobjtype_t)sides[lines[tagline].sidenum[0]].toptexture; // Set as object type in p_setup.c...
if (sides[lines[tagline].sidenum[0]].textureoffset)
spacing = sides[lines[tagline].sidenum[0]].textureoffset;
if (sides[lines[tagline].sidenum[0]].rowoffset)
{
if (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS != -1)
lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS);
else
lifetime = 0;
}
flags = lines[tagline].flags;
}
}
#undef controlsec
// soundorg z height never gets set normally, so MEH. // soundorg z height never gets set normally, so MEH.
sec->soundorg.z = sec->floorheight; sec->soundorg.z = sec->floorheight;
S_StartSound(&sec->soundorg, sfx_crumbl); S_StartSound(&sec->soundorg, mobjinfo[type].activesound);
// Find the outermost vertexes in the subsector // Find the outermost vertexes in the subsector
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
@ -2933,23 +2975,46 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
bottommostvertex = i; bottommostvertex = i;
} }
leftx = sec->lines[leftmostvertex]->v1->x+(16<<FRACBITS); leftx = sec->lines[leftmostvertex]->v1->x+(spacing>>1);
rightx = sec->lines[rightmostvertex]->v1->x; rightx = sec->lines[rightmostvertex]->v1->x;
topy = sec->lines[topmostvertex]->v1->y-(16<<FRACBITS); topy = sec->lines[topmostvertex]->v1->y-(spacing>>1);
bottomy = sec->lines[bottommostvertex]->v1->y; bottomy = sec->lines[bottommostvertex]->v1->y;
topz = *rover->topheight-(16<<FRACBITS);
for (a = leftx; a < rightx; a += (32<<FRACBITS)) topz = *rover->topheight-(spacing>>1);
bottomz = *rover->bottomheight;
if (flags & ML_EFFECT1)
{ {
for (b = topy; b > bottomy; b -= (32<<FRACBITS)) widthfactor = (rightx + topy - leftx - bottomy)>>3;
heightfactor = (topz - *rover->bottomheight)>>2;
}
for (a = leftx; a < rightx; a += spacing)
{
for (b = topy; b > bottomy; b -= spacing)
{ {
if (R_PointInSubsector(a, b)->sector == sec) if (R_PointInSubsector(a, b)->sector == sec)
{ {
mobj_t *spawned = NULL; mobj_t *spawned = NULL;
for (c = topz; c > *rover->bottomheight; c -= (32<<FRACBITS)) #ifdef ESLOPE
if (*rover->t_slope)
topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1);
if (*rover->b_slope)
bottomz = P_GetZAt(*rover->b_slope, a, b);
#endif
for (c = topz; c > bottomz; c -= spacing)
{ {
spawned = P_SpawnMobj(a, b, c, type); spawned = P_SpawnMobj(a, b, c, type);
spawned->fuse = 3*TICRATE; spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
if (flags & ML_EFFECT1)
{
P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor));
P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false);
}
spawned->fuse = lifetime;
} }
} }
} }
@ -3109,8 +3174,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
return 1; return 1;
} }
INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mobj_t *puncher) INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
{ {
sector_t *roversec = rover->master->frontsector;
fixed_t topheight = *rover->topheight;
levelspecthink_t *block; levelspecthink_t *block;
mobj_t *thing; mobj_t *thing;
fixed_t oldx = 0, oldy = 0, oldz = 0; fixed_t oldx = 0, oldy = 0, oldz = 0;
@ -3118,11 +3185,14 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
I_Assert(puncher != NULL); I_Assert(puncher != NULL);
I_Assert(puncher->player != NULL); I_Assert(puncher->player != NULL);
if (sec->floordata || sec->ceilingdata) if (roversec->floordata || roversec->ceilingdata)
return 0; return 0;
if (!(rover->flags & FF_SOLID))
rover->flags |= (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL);
// Find an item to pop out! // Find an item to pop out!
thing = SearchMarioNode(sec->touching_thinglist); thing = SearchMarioNode(roversec->touching_thinglist);
// Found something! // Found something!
if (thing) if (thing)
@ -3132,13 +3202,13 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
P_AddThinker(&block->thinker); P_AddThinker(&block->thinker);
sec->floordata = block; roversec->floordata = block;
sec->ceilingdata = block; roversec->ceilingdata = block;
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; block->thinker.function.acp1 = (actionf_p1)T_MarioBlock;
// Set up the fields // Set up the fields
block->sector = sec; block->sector = roversec;
block->vars[0] = roversector->tag; // actionsector block->vars[0] = sector->tag; // actionsector
block->vars[1] = 4*FRACUNIT; // speed block->vars[1] = 4*FRACUNIT; // speed
block->vars[2] = 1; // Up // direction block->vars[2] = 1; // Up // direction
block->vars[3] = block->sector->floorheight; // floorwasheight block->vars[3] = block->sector->floorheight; // floorwasheight
@ -3154,8 +3224,8 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
} }
P_UnsetThingPosition(thing); P_UnsetThingPosition(thing);
thing->x = roversector->soundorg.x; thing->x = sector->soundorg.x;
thing->y = roversector->soundorg.y; thing->y = sector->soundorg.y;
thing->z = topheight; thing->z = topheight;
thing->momz = FixedMul(6*FRACUNIT, thing->scale); thing->momz = FixedMul(6*FRACUNIT, thing->scale);
P_SetThingPosition(thing); P_SetThingPosition(thing);
@ -3172,7 +3242,7 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
{ {
if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL)) if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL))
{ {
mobj_t *tokenobj = P_SpawnMobj(roversector->soundorg.x, roversector->soundorg.y, topheight, MT_TOKEN); mobj_t *tokenobj = P_SpawnMobj(sector->soundorg.x, sector->soundorg.y, topheight, MT_TOKEN);
P_SetTarget(&thing->tracer, tokenobj); P_SetTarget(&thing->tracer, tokenobj);
P_SetTarget(&tokenobj->target, thing); P_SetTarget(&tokenobj->target, thing);
P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate); P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate);

View file

@ -564,7 +564,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
// Adjust the player's animation speed to match their velocity. // Adjust the player's animation speed to match their velocity.
if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{ {
fixed_t speed;// = FixedDiv(player->speed, mobj->scale); fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_FALL) if (player->panim == PA_FALL)
{ {
speed = FixedDiv(abs(mobj->momz), mobj->scale); speed = FixedDiv(abs(mobj->momz), mobj->scale);
@ -590,7 +590,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
} }
else else
{ {
speed = FixedDiv(player->speed, mobj->scale); speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_ROLL || player->panim == PA_JUMP) if (player->panim == PA_ROLL || player->panim == PA_JUMP)
{ {
if (speed > 16<<FRACBITS) if (speed > 16<<FRACBITS)
@ -1842,7 +1842,6 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
} }
#define STOPSPEED (FRACUNIT) #define STOPSPEED (FRACUNIT)
#define FRICTION (ORIG_FRICTION) // 0.90625
// //
// P_SceneryXYFriction // P_SceneryXYFriction
@ -1875,7 +1874,6 @@ static void P_SceneryXYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
{ {
// Stolen from P_SpawnFriction // Stolen from P_SpawnFriction
mo->friction = FRACUNIT - 0x100; mo->friction = FRACUNIT - 0x100;
mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158;
} }
else else
mo->friction = ORIG_FRICTION; mo->friction = ORIG_FRICTION;
@ -1900,7 +1898,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
// spinning friction // spinning friction
if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)) if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH))
{ {
const fixed_t ns = FixedDiv(549*FRICTION,500*FRACUNIT); const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT);
mo->momx = FixedMul(mo->momx, ns); mo->momx = FixedMul(mo->momx, ns);
mo->momy = FixedMul(mo->momy, ns); mo->momy = FixedMul(mo->momy, ns);
} }
@ -2409,14 +2407,16 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL);
if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water
; ;
else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
continue; continue;
else if (rover->flags & FF_QUICKSAND) // quicksand else if (rover->flags & FF_QUICKSAND) // quicksand
; ;
else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players? else if (!( // if it's not either of the following...
|| (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? (rover->flags & (FF_BLOCKPLAYER|FF_MARIO) && mo->player) // ...solid to players? (mario blocks are always solid from beneath to players)
|| (rover->flags & FF_BLOCKOTHERS && !mo->player) // ...solid to others?
)) // ...don't take it into account.
continue; continue;
if (rover->flags & FF_QUICKSAND) if (rover->flags & FF_QUICKSAND)
{ {
@ -2441,7 +2441,9 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2)); delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2));
delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
if (topheight > mo->floorz && abs(delta1) < abs(delta2) if (topheight > mo->floorz && abs(delta1) < abs(delta2)
&& (rover->flags & FF_SOLID) // Non-FF_SOLID Mario blocks are only solid from bottom
&& !(rover->flags & FF_REVERSEPLATFORM) && !(rover->flags & FF_REVERSEPLATFORM)
&& ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference)
{ {
@ -2449,7 +2451,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
} }
if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
&& !(rover->flags & FF_PLATFORM) && !(rover->flags & FF_PLATFORM)
&& ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below && ((P_MobjFlip(mo)*mo->momz >= 0) || ((rover->flags & FF_SOLID) && !(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below
{ {
mo->ceilingz = bottomheight; mo->ceilingz = bottomheight;
} }
@ -2934,7 +2936,6 @@ static boolean P_ZMovement(mobj_t *mo)
// Stolen from P_SpawnFriction // Stolen from P_SpawnFriction
mo->friction = FRACUNIT - 0x100; mo->friction = FRACUNIT - 0x100;
mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158;
} }
else if (mo->type == MT_FALLINGROCK) else if (mo->type == MT_FALLINGROCK)
{ {
@ -3389,8 +3390,13 @@ nightsdone:
if (rover->flags & FF_MARIO if (rover->flags & FF_MARIO
&& !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it? && !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it?
&& *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom! && *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom!
{
// DO THE MARIO! // DO THE MARIO!
EV_MarioBlock(rover->master->frontsector, node->m_sector, *rover->topheight, mo); if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
} }
} // Ugly ugly billions of braces! Argh! } // Ugly ugly billions of braces! Argh!
} }
@ -8263,7 +8269,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->friction = ORIG_FRICTION; mobj->friction = ORIG_FRICTION;
mobj->movefactor = ORIG_FRICTION_FACTOR; mobj->movefactor = FRACUNIT;
// All mobjs are created at 100% scale. // All mobjs are created at 100% scale.
mobj->scale = FRACUNIT; mobj->scale = FRACUNIT;
@ -9774,6 +9780,85 @@ ML_NOCLIMB : Direction not controllable
} }
break; break;
} }
case MT_PARTICLEGEN:
{
fixed_t radius, speed, bottomheight, topheight;
INT32 type, numdivisions, time, anglespeed;
angle_t angledivision;
size_t line;
const size_t mthingi = (size_t)(mthing - mapthings);
for (line = 0; line < numlines; line++)
{
if (lines[line].special == 15 && lines[line].tag == mthing->angle)
break;
}
if (line == numlines)
{
CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle);
return;
}
if (sides[lines[line].sidenum[0]].toptexture)
type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c...
else
type = (INT32)MT_PARTICLE;
speed = abs(sides[lines[line].sidenum[0]].textureoffset);
bottomheight = lines[line].frontsector->floorheight;
topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height;
numdivisions = (mthing->options >> ZSHIFT);
if (numdivisions)
{
radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y);
anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360;
angledivision = 360/numdivisions;
}
else
{
numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler.
radius = 0;
anglespeed = 0;
angledivision = 0;
}
if ((speed) && (topheight > bottomheight))
time = (INT32)(FixedDiv((topheight - bottomheight), speed) >> FRACBITS);
else
time = 1; // There's no reasonable way to set it, so just show the object for one tic and move on.
if (mthing->options & MTF_OBJECTFLIP)
{
mobj->z = topheight;
speed *= -1;
}
else
mobj->z = bottomheight;
CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n"
"Radius is %d\n"
"Speed is %d\n"
"Anglespeed is %d\n"
"Numdivisions is %d\n"
"Angledivision is %d\n"
"Time is %d\n"
"Type is %d\n",
sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, time, type);
mobj->angle = 0;
mobj->movefactor = speed;
mobj->lastlook = numdivisions;
mobj->movedir = angledivision*ANG1;
mobj->movecount = anglespeed*ANG1;
mobj->health = time;
mobj->friction = radius;
mobj->threshold = type;
break;
}
case MT_ROCKSPAWNER: case MT_ROCKSPAWNER:
mobj->threshold = mthing->angle; mobj->threshold = mthing->angle;
mobj->movecount = mthing->extrainfo; mobj->movecount = mthing->extrainfo;

View file

@ -1098,7 +1098,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_TRACER; diff |= MD_TRACER;
if (mobj->friction != ORIG_FRICTION) if (mobj->friction != ORIG_FRICTION)
diff |= MD_FRICTION; diff |= MD_FRICTION;
if (mobj->movefactor != ORIG_FRICTION_FACTOR) if (mobj->movefactor != FRACUNIT)
diff |= MD_MOVEFACTOR; diff |= MD_MOVEFACTOR;
if (mobj->fuse) if (mobj->fuse)
diff |= MD_FUSE; diff |= MD_FUSE;
@ -2105,7 +2105,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (diff & MD_MOVEFACTOR) if (diff & MD_MOVEFACTOR)
mobj->movefactor = READFIXED(save_p); mobj->movefactor = READFIXED(save_p);
else else
mobj->movefactor = ORIG_FRICTION_FACTOR; mobj->movefactor = FRACUNIT;
if (diff & MD_FUSE) if (diff & MD_FUSE)
mobj->fuse = READINT32(save_p); mobj->fuse = READINT32(save_p);
if (diff & MD_WATERTOP) if (diff & MD_WATERTOP)

View file

@ -1561,6 +1561,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
sd->text[6] = 0; sd->text[6] = 0;
break; break;
} }
case 4: // Speed pad parameters
case 414: // Play SFX case 414: // Play SFX
{ {
sd->toptexture = sd->midtexture = sd->bottomtexture = 0; sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
@ -1574,6 +1576,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
break; break;
} }
case 14: // Bustable block parameters
case 15: // Fan particle spawner parameters
case 425: // Calls P_SetMobjState on calling mobj case 425: // Calls P_SetMobjState on calling mobj
case 434: // Custom Power case 434: // Custom Power
case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors

View file

@ -51,6 +51,9 @@ mobj_t *skyboxmo[2];
// Amount (dx, dy) vector linedef is shifted right to get scroll amount // Amount (dx, dy) vector linedef is shifted right to get scroll amount
#define SCROLL_SHIFT 5 #define SCROLL_SHIFT 5
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
/** Animated texture descriptor /** Animated texture descriptor
* This keeps track of an animated texture or an animated flat. * This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
@ -2441,7 +2444,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{ {
fixed_t sfxnum; fixed_t sfxnum;
sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS; sfxnum = sides[line->sidenum[0]].toptexture;
if (line->tag != 0 && line->flags & ML_EFFECT5) if (line->tag != 0 && line->flags & ML_EFFECT5)
{ {
@ -3684,14 +3687,13 @@ DoneSection2:
// Process Section 3 // Process Section 3
switch (special) switch (special)
{ {
case 1: // Ice/Sludge case 1: // Unused
case 2: // Wind/Current case 2: // Wind/Current
case 3: // Ice/Sludge and Wind/Current case 3: // Unused
case 4: // Conveyor Belt case 4: // Conveyor Belt
break; break;
case 5: // Speed pad w/o spin case 5: // Speed pad
case 6: // Speed pad w/ spin
if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2)
break; break;
@ -3701,9 +3703,16 @@ DoneSection2:
{ {
angle_t lineangle; angle_t lineangle;
fixed_t linespeed; fixed_t linespeed;
fixed_t sfxnum;
lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); linespeed = sides[lines[i].sidenum[0]].textureoffset;
if (linespeed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sector->tag);
break;
}
player->mo->angle = lineangle; player->mo->angle = lineangle;
@ -3733,7 +3742,7 @@ DoneSection2:
P_InstaThrust(player->mo, player->mo->angle, linespeed); P_InstaThrust(player->mo, player->mo->angle, linespeed);
if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) if ((lines[i].flags & ML_EFFECT5) && (player->charability2 == CA2_SPINDASH)) // Roll!
{ {
if (!(player->pflags & PF_SPINNING)) if (!(player->pflags & PF_SPINNING))
player->pflags |= PF_SPINNING; player->pflags |= PF_SPINNING;
@ -3742,19 +3751,26 @@ DoneSection2:
} }
player->powers[pw_flashing] = TICRATE/3; player->powers[pw_flashing] = TICRATE/3;
S_StartSound(player->mo, sfx_spdpad);
sfxnum = sides[lines[i].sidenum[0]].toptexture;
if (!sfxnum)
sfxnum = sfx_spdpad;
S_StartSound(player->mo, sfxnum);
} }
break; break;
case 7: // Bustable block sprite parameter case 6: // Unused
case 8: case 7: // Unused
case 9: case 8: // Unused
case 10: case 9: // Unused
case 11: case 10: // Unused
case 12: case 11: // Unused
case 13: case 12: // Unused
case 14: case 13: // Unused
case 15: case 14: // Unused
case 15: // Unused
break; break;
} }
@ -3924,8 +3940,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = abs(lines[lineindex].dx)/8; speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8;
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// scan the thinkers // scan the thinkers
// to find the first waypoint // to find the first waypoint
@ -3997,8 +4019,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = -(abs(lines[lineindex].dx)/8); // Negative means reverse speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// scan the thinkers // scan the thinkers
// to find the last waypoint // to find the last waypoint
@ -4038,6 +4066,7 @@ DoneSection2:
player->speed = speed; player->speed = speed;
player->pflags |= PF_SPINNING; player->pflags |= PF_SPINNING;
player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY);
player->climbing = 0;
if (player->mo->state-states != S_PLAY_SPIN) if (player->mo->state-states != S_PLAY_SPIN)
{ {
@ -4136,8 +4165,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = abs(lines[lineindex].dx)/8; speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8;
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// Find the closest waypoint // Find the closest waypoint
// Find the preceding waypoint // Find the preceding waypoint
@ -4984,7 +5019,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
if ((flags & FF_MARIO)) if ((flags & FF_MARIO))
{ {
P_AddBlockThinker(sec2, master); if (!(flags & FF_SHATTERBOTTOM)) // Don't change the textures of a brick block, just a question block
P_AddBlockThinker(sec2, master);
CheckForMarioBlocks = true; CheckForMarioBlocks = true;
} }
@ -5349,7 +5385,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
elevator->distance = FixedInt(AngleFixed(angle)); elevator->distance = FixedInt(AngleFixed(angle));
} }
static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA; static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT;
/** Flashes a laser block. /** Flashes a laser block.
* *
@ -5369,10 +5405,12 @@ void T_LaserFlash(laserthink_t *flash)
if (!ffloor || !(ffloor->flags & FF_EXISTS)) if (!ffloor || !(ffloor->flags & FF_EXISTS))
return; return;
if (leveltime & 1) if (leveltime & 2)
ffloor->flags |= FF_RENDERALL; //ffloor->flags |= FF_RENDERALL;
ffloor->alpha = 0xB0;
else else
ffloor->flags &= ~FF_RENDERALL; //ffloor->flags &= ~FF_RENDERALL;
ffloor->alpha = 0x90;
sourcesec = ffloor->master->frontsector; // Less to type! sourcesec = ffloor->master->frontsector; // Less to type!
@ -5600,32 +5638,27 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Init line EFFECTs // Init line EFFECTs
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
// set line specials to 0 here too, same reason as above if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups...
if (netgame || multiplayer)
{ {
// future: nonet flag? // set line specials to 0 here too, same reason as above
} if (netgame || multiplayer)
else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) {
{ // future: nonet flag?
lines[i].special = 0; }
continue; else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
}
else
{
if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
{ {
lines[i].special = 0; lines[i].special = 0;
continue; continue;
} }
if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) else
{ {
lines[i].special = 0; if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
continue; || (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
} || (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)))
if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) {
{ lines[i].special = 0;
lines[i].special = 0; continue;
continue; }
} }
} }
@ -5671,47 +5704,53 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
#endif #endif
case 7: // Flat alignment case 7: // Flat alignment - redone by toast
if (lines[i].flags & ML_EFFECT4) // Align angle if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something...
{ {
if (!(lines[i].flags & ML_EFFECT5)) // Align floor unless ALLTRIGGER flag is set angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y));
fixed_t xoffs;
fixed_t yoffs;
if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set
{ {
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) xoffs = sides[lines[i].sidenum[0]].textureoffset;
sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); yoffs = sides[lines[i].sidenum[0]].rowoffset;
}
else // Otherwise, set calculated offsets such that line's v1 is the apparent origin
{
fixed_t cosinecomponent = FINECOSINE(flatangle>>ANGLETOFINESHIFT);
fixed_t sinecomponent = FINESINE(flatangle>>ANGLETOFINESHIFT);
xoffs = (-FixedMul(lines[i].v1->x, cosinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, sinecomponent) % MAXFLATSIZE); // No danger of overflow thanks to the strategically placed modulo operations.
yoffs = (FixedMul(lines[i].v1->x, sinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, cosinecomponent) % MAXFLATSIZE); // Ditto.
} }
if (!(lines[i].flags & ML_BOUNCY)) // Align ceiling unless BOUNCY flag is set for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
}
}
else // Do offsets
{
if (!(lines[i].flags & ML_BLOCKMONSTERS)) // Align floor unless BLOCKMONSTERS flag is set
{
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
sectors[s].floor_xoffs += lines[i].dx; sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle;
sectors[s].floor_yoffs += lines[i].dy; sectors[s].floor_xoffs += xoffs;
sectors[s].floor_yoffs += yoffs;
// saved for netgames // saved for netgames
sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs; sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs;
sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs; sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs;
} }
}
if (!(lines[i].flags & ML_NOCLIMB)) // Align ceiling unless NOCLIMB flag is set if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
sectors[s].ceiling_xoffs += lines[i].dx; sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle;
sectors[s].ceiling_yoffs += lines[i].dy; sectors[s].ceiling_xoffs += xoffs;
sectors[s].ceiling_yoffs += yoffs;
// saved for netgames // saved for netgames
sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs; sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs;
sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs; sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs;
} }
} }
} }
else // Otherwise, print a helpful warning. Can I do no less?
CONS_Alert(CONS_WARNING,
M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"),
lines[i].tag);
break; break;
case 8: // Sector Parameters case 8: // Sector Parameters
@ -5850,11 +5889,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5961,11 +5997,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5979,11 +6012,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -6007,11 +6037,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -6025,11 +6052,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -6207,7 +6231,13 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 250: // Mario Block case 250: // Mario Block
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO;
if (lines[i].flags & ML_NOCLIMB)
ffloorflags |= FF_SHATTERBOTTOM;
if (lines[i].flags & ML_EFFECT1)
ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL);
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 251: // A THWOMP! case 251: // A THWOMP!
@ -6221,10 +6251,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 252: // Shatter block (breaks when touched) case 252: // Shatter block (breaks when touched)
ffloorflags = FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_SHATTERBOTTOM, secthinkers); ffloorflags |= FF_SOLID|FF_SHATTERBOTTOM;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 253: // Translucent shatter block (see 76) case 253: // Translucent shatter block (see 76)
@ -6232,10 +6263,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 254: // Bustable block case 254: // Bustable block
ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_ONLYKNUX, secthinkers); ffloorflags |= FF_ONLYKNUX;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 255: // Spin bust block (breaks when jumped or spun downwards onto) case 255: // Spin bust block (breaks when jumped or spun downwards onto)
@ -6247,10 +6279,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 257: // Quicksand case 257: // Quicksand
ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES;
if (lines[i].flags & ML_EFFECT5) if (lines[i].flags & ML_EFFECT5)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES|FF_RIPPLE, secthinkers); ffloorflags |= FF_RIPPLE;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 258: // Laser block case 258: // Laser block
@ -7011,7 +7044,6 @@ void T_Disappear(disappear_t *d)
/** Adds friction thinker. /** Adds friction thinker.
* *
* \param friction Friction value, 0xe800 is normal. * \param friction Friction value, 0xe800 is normal.
* \param movefactor Inertia factor.
* \param affectee Target sector. * \param affectee Target sector.
* \param roverfriction FOF or not * \param roverfriction FOF or not
* \sa T_Friction, P_SpawnFriction * \sa T_Friction, P_SpawnFriction
@ -7049,22 +7081,10 @@ void T_Friction(friction_t *f)
sec = sectors + f->affectee; sec = sectors + f->affectee;
// Make sure the sector type hasn't changed // Get FOF control sector
if (f->roverfriction) if (f->roverfriction)
{
referrer = sectors + f->referrer; referrer = sectors + f->referrer;
if (!(GETSECSPECIAL(referrer->special, 3) == 1
|| GETSECSPECIAL(referrer->special, 3) == 3))
return;
}
else
{
if (!(GETSECSPECIAL(sec->special, 3) == 1
|| GETSECSPECIAL(sec->special, 3) == 3))
return;
}
// Assign the friction value to players on the floor, non-floating, // Assign the friction value to players on the floor, non-floating,
// and clipped. Normally the object's friction value is kept at // and clipped. Normally the object's friction value is kept at
// ORIG_FRICTION and this thinker changes it for icy or muddy floors. // ORIG_FRICTION and this thinker changes it for icy or muddy floors.
@ -7094,14 +7114,16 @@ void T_Friction(friction_t *f)
|| (f->friction < thing->friction)) || (f->friction < thing->friction))
{ {
thing->friction = f->friction; thing->friction = f->friction;
thing->movefactor = f->movefactor; if (thing->player)
thing->movefactor = f->movefactor;
} }
} }
else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction? else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction?
|| f->friction < thing->friction)) || f->friction < thing->friction))
{ {
thing->friction = f->friction; thing->friction = f->friction;
thing->movefactor = f->movefactor; if (thing->player)
thing->movefactor = f->movefactor;
} }
} }
node = node->m_thinglist_next; node = node->m_thinglist_next;
@ -7117,33 +7139,32 @@ static void P_SpawnFriction(void)
size_t i; size_t i;
line_t *l = lines; line_t *l = lines;
register INT32 s; register INT32 s;
fixed_t length; // line length controls magnitude fixed_t strength; // frontside texture offset controls magnitude
fixed_t friction; // friction value to be applied during movement fixed_t friction; // friction value to be applied during movement
INT32 movefactor; // applied to each player move to simulate inertia INT32 movefactor; // applied to each player move to simulate inertia
for (i = 0; i < numlines; i++, l++) for (i = 0; i < numlines; i++, l++)
if (l->special == 540) if (l->special == 540)
{ {
length = P_AproxDistance(l->dx, l->dy)>>FRACBITS; strength = sides[l->sidenum[0]].textureoffset>>FRACBITS;
friction = (0x1EB8*length)/0x80 + 0xD000; if (strength > 0) // sludge
strength = strength*2; // otherwise, the maximum sludginess value is +967...
// The following might seem odd. At the time of movement,
// the move distance is multiplied by 'friction/0x10000', so a
// higher friction value actually means 'less friction'.
friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800
if (friction > FRACUNIT) if (friction > FRACUNIT)
friction = FRACUNIT; friction = FRACUNIT;
if (friction < 0) if (friction < 0)
friction = 0; friction = 0;
// The following check might seem odd. At the time of movement, movefactor = FixedDiv(ORIG_FRICTION, friction);
// the move distance is multiplied by 'friction/0x10000', so a if (movefactor < FRACUNIT)
// higher friction value actually means 'less friction'. movefactor = 8*movefactor - 7*FRACUNIT;
if (friction > ORIG_FRICTION) // ice
movefactor = ((0x10092 - friction)*(0x70))/0x158;
else else
movefactor = ((friction - 0xDB34)*(0xA))/0x80; movefactor = FRACUNIT;
// killough 8/28/98: prevent odd situations
if (movefactor < 32)
movefactor = 32;
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
Add_Friction(friction, movefactor, s, -1); Add_Friction(friction, movefactor, s, -1);
@ -7393,12 +7414,10 @@ void T_Pusher(pusher_t *p)
{ {
referrer = &sectors[p->referrer]; referrer = &sectors[p->referrer];
if (!(GETSECSPECIAL(referrer->special, 3) == 2 if (GETSECSPECIAL(referrer->special, 3) != 2)
|| GETSECSPECIAL(referrer->special, 3) == 3))
return; return;
} }
else if (!(GETSECSPECIAL(sec->special, 3) == 2 else if (GETSECSPECIAL(sec->special, 3) != 2)
|| GETSECSPECIAL(sec->special, 3) == 3))
return; return;
// For constant pushers (wind/current) there are 3 situations: // For constant pushers (wind/current) there are 3 situations:

View file

@ -325,7 +325,7 @@ INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,
INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards); INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards);
INT32 EV_MarioBlock(sector_t *sector, sector_t *roversector, fixed_t topheight, mobj_t *puncher); INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
void T_MoveFloor(floormove_t *movefloor); void T_MoveFloor(floormove_t *movefloor);
@ -388,7 +388,7 @@ typedef struct
{ {
thinker_t thinker; ///< Thinker structure for friction. thinker_t thinker; ///< Thinker structure for friction.
INT32 friction; ///< Friction value, 0xe800 = normal. INT32 friction; ///< Friction value, 0xe800 = normal.
INT32 movefactor; ///< Inertia factor when adding to momentum. INT32 movefactor; ///< Inertia factor when adding to momentum, FRACUNIT = normal.
INT32 affectee; ///< Number of affected sector. INT32 affectee; ///< Number of affected sector.
INT32 referrer; ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied. INT32 referrer; ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied.
UINT8 roverfriction; ///< flag for whether friction originated from a FOF or not UINT8 roverfriction; ///< flag for whether friction originated from a FOF or not

View file

@ -4791,6 +4791,9 @@ static void P_3dMovement(player_t *player)
acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration;
} }
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS;
// Forward movement // Forward movement
if (player->climbing) if (player->climbing)
{ {
@ -6447,7 +6450,7 @@ static void P_SkidStuff(player_t *player)
// If your push angle is more than this close to a full 180 degrees, trigger a skid. // If your push angle is more than this close to a full 180 degrees, trigger a skid.
if (dang > ANGLE_157h) if (dang > ANGLE_157h)
{ {
player->skidtime = TICRATE/2; player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_skid); S_StartSound(player->mo, sfx_skid);
if (player->panim != PA_WALK) if (player->panim != PA_WALK)
P_SetPlayerMobjState(player->mo, S_PLAY_WALK); P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
@ -6484,6 +6487,9 @@ static void P_MovePlayer(player_t *player)
cmd = &player->cmd; cmd = &player->cmd;
runspd = FixedMul(player->runspeed, player->mo->scale); runspd = FixedMul(player->runspeed, player->mo->scale);
// Let's have some movement speed fun on low-friction surfaces, JUST for players... (high friction surfaces shouldn't have any adjustment, since the acceleration in this game is super high and that ends up cheesing high-friction surfaces.)
runspd = FixedMul(runspd, player->mo->movefactor);
// Control relinquishing stuff! // Control relinquishing stuff!
if (player->powers[pw_ingoop]) if (player->powers[pw_ingoop])
player->pflags |= PF_FULLSTASIS; player->pflags |= PF_FULLSTASIS;
@ -6674,6 +6680,7 @@ static void P_MovePlayer(player_t *player)
if (!player->mo->momx && !player->mo->momy && !player->mo->momz && player->panim == PA_WALK) if (!player->mo->momx && !player->mo->momy && !player->mo->momz && player->panim == PA_WALK)
P_SetPlayerMobjState(player->mo, S_PLAY_STND); P_SetPlayerMobjState(player->mo, S_PLAY_STND);
player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame.
////////////////// //////////////////
//GAMEPLAY STUFF// //GAMEPLAY STUFF//