Merge branch 'strongpower' into 'next'

Add player->powers[pw_strong], refactor attacks and busting conditions, and allow breaking floors and ceilings separately

See merge request STJr/SRB2!1366
This commit is contained in:
sphere 2023-07-05 17:05:47 +00:00
commit d7a84b967c
6 changed files with 179 additions and 107 deletions

View file

@ -249,6 +249,38 @@ typedef enum
CR_FAN
} carrytype_t; // pw_carry
typedef enum
{
STR_NONE = 0, // All strong powers can stack onto each other
// Attack powers
STR_ANIM = 0x1, // remove powers when leaving current animation
STR_PUNCH = 0x2, // frontal attack (knuckles glide)
STR_TAIL = 0x4, // rear attack
STR_STOMP = 0x8, // falling onto object (fang bounce)
STR_UPPER = 0x10, // moving upwards into object (tails fly)
STR_GUARD = 0x20, //protect against damage
STR_HEAVY = 0x40, // ignore vertical rebound
STR_DASH = 0x80, // special type for machine dashmode, automatically removes your powers when leaving dashmode
// Environment powers
STR_WALL = 0x100, // fof busting
STR_FLOOR = 0x200,
STR_CEILING = 0x400,
STR_SPRING = 0x800, // power up hit springs
STR_SPIKE = 0x1000, // break spikes
// Shortcuts
STR_ATTACK = STR_PUNCH|STR_TAIL|STR_STOMP|STR_UPPER,
STR_BUST = STR_WALL|STR_FLOOR|STR_CEILING,
STR_FLY = STR_ANIM|STR_UPPER,
STR_GLIDE = STR_ANIM|STR_PUNCH,
STR_TWINSPIN = STR_ANIM|STR_ATTACK|STR_BUST|STR_SPRING|STR_SPIKE,
STR_MELEE = STR_ANIM|STR_PUNCH|STR_HEAVY|STR_WALL|STR_FLOOR|STR_SPRING|STR_SPIKE,
STR_BOUNCE = STR_ANIM|STR_STOMP|STR_FLOOR,
STR_METAL = STR_DASH|STR_SPIKE
} strongtype_t; // pw_strong
// Player powers. (don't edit this comment)
typedef enum
{
@ -293,6 +325,8 @@ typedef enum
pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types
pw_strong, // Additional properties for powerful attacks
NUMPOWERS
} powertype_t;
@ -407,6 +441,7 @@ typedef struct player_s
// playing animation.
panim_t panim;
UINT8 stronganim;
// For screen flashing (bright).
UINT16 flashcount;

View file

@ -4813,7 +4813,9 @@ const char *const POWERS_LIST[] = {
"JUSTLAUNCHED",
"IGNORELATCH"
"IGNORELATCH",
"STRONG"
};
const char *const HUDITEMS_LIST[] = {
@ -5166,6 +5168,30 @@ struct int_const_s const INT_CONST[] = {
{"CR_DUSTDEVIL",CR_DUSTDEVIL},
{"CR_FAN",CR_FAN},
// Strong powers
{"STR_NONE",STR_NONE},
{"STR_ANIM",STR_ANIM},
{"STR_PUNCH",STR_PUNCH},
{"STR_TAIL",STR_TAIL},
{"STR_STOMP",STR_STOMP},
{"STR_UPPER",STR_UPPER},
{"STR_GUARD",STR_GUARD},
{"STR_HEAVY",STR_HEAVY},
{"STR_DASH",STR_DASH},
{"STR_WALL",STR_WALL},
{"STR_FLOOR",STR_FLOOR},
{"STR_CEILING",STR_CEILING},
{"STR_SPRING",STR_SPRING},
{"STR_SPIKE",STR_SPIKE},
{"STR_ATTACK",STR_ATTACK},
{"STR_BUST",STR_BUST},
{"STR_FLY",STR_FLY},
{"STR_GLIDE",STR_GLIDE},
{"STR_TWINSPIN",STR_TWINSPIN},
{"STR_MELEE",STR_MELEE},
{"STR_BOUNCE",STR_BOUNCE},
{"STR_METAL",STR_METAL},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon
{"RW_AUTO",RW_AUTO},

View file

@ -498,23 +498,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1)
return; // Can't hurt a Pterabyte if it's trying to pick you up
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY)))
{
if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player);
toucher->momz = setmomz;
if (elementalpierce == 2) // Reset bubblewrap, part 2
{
fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
boolean underwater = toucher->eflags & MFE_UNDERWATER;
if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player);
toucher->momz = setmomz;
if (elementalpierce == 2) // Reset bubblewrap, part 2
{
boolean underwater = toucher->eflags & MFE_UNDERWATER;
if (underwater)
toucher->momz /= 2;
toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height!
}
if (underwater)
toucher->momz /= 2;
toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height!
}
}
if (player->pflags & PF_BOUNCING)
@ -533,8 +530,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->momx = 7*toucher->momx>>3;
toucher->momy = 7*toucher->momy>>3;
}
else if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& player->panim == PA_DASH)
else if ((player->powers[pw_strong] & STR_DASH) && player->panim == PA_DASH)
P_DoPlayerPain(player, special, special);
}
P_DamageMobj(special, toucher, toucher, 1, 0);
@ -3303,7 +3299,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return false;
// Add pity.
if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super]
if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] && !(player->powers[pw_strong] & STR_GUARD)
&& source->player->score > player->score)
player->pity++;
@ -3775,7 +3771,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
return false;
}
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || (player->powers[pw_strong] & STR_GUARD)) // ignore bouncing & such in invulnerability
{
if (force
|| (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned!

View file

@ -177,10 +177,8 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
if (spring->info->painchance == 3)
;
else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
else if (object->player->powers[pw_strong] & STR_SPRING)
strong = 1;
else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)
strong = 2;
}
if (spring->info->painchance == -1) // Pinball bumper mode.
@ -495,7 +493,8 @@ springstate:
if (strong)
{
P_TwinSpinRejuvenate(object->player, (strong == 1 ? object->player->thokitem : object->player->revitem));
if (object->player->charability == CA_TWINSPIN || object->player->charability2 == CA2_MELEE)
P_TwinSpinRejuvenate(object->player, (object->player->charability == CA_TWINSPIN ? object->player->thokitem : object->player->revitem));
S_StartSound(object, sfx_sprong); // strong spring. sprong.
}
}
@ -836,43 +835,25 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
// SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes.
if ((tmthing->player)
&& ((((tmthing->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) && (tmthing->player->dashmode >= DASHMODE_THRESHOLD)
&& (thing->flags & (MF_MONITOR)
|| (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)))
|| ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2))
&& (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE))))
// STR_SPIKE users destroy spikes
if ((tmthing->player) && ((tmthing->player->powers[pw_strong] & STR_SPIKE) && (thing->type == MT_SPIKE || thing->type == MT_WALLSPIKE)))
{
if ((thing->flags & (MF_MONITOR)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE)))
return true;
blockdist = thing->radius + tmthing->radius;
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
return true; // didn't hit it
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)
{
mobj_t *iter;
if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound);
for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(iter, tmthing, tmthing, 0);
return true;
}
else
{
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0))
return true;
}
mobj_t *iter;
blockdist = thing->radius + tmthing->radius;
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
return true; // didn't hit it
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound);
for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(iter, tmthing, tmthing, 0);
return true;
}
// vectorise metal - done in a special case as at this point neither has the right flags for touching
@ -1727,25 +1708,22 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Going down? Then bounce back up.
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor
&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
&& (elementalpierce != 1)) // you're not piercing through the monitor...
&& (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) // you're not piercing through the monitor...
{
if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player);
*momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically.
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
P_TwinSpinRejuvenate(player, player->thokitem);
if (elementalpierce == 2) // Reset bubblewrap, part 2
{
fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
boolean underwater = tmthing->eflags & MFE_UNDERWATER;
if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player);
*momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically.
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
P_TwinSpinRejuvenate(player, player->thokitem);
if (elementalpierce == 2) // Reset bubblewrap, part 2
{
boolean underwater = tmthing->eflags & MFE_UNDERWATER;
if (underwater)
*momz /= 2;
*momz -= (*momz/(underwater ? 8 : 4)); // Cap the height!
}
if (underwater)
*momz /= 2;
*momz -= (*momz/(underwater ? 8 : 4)); // Cap the height!
}
}
if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.

View file

@ -169,6 +169,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].playerstate);
WRITEUINT32(save_p, players[i].pflags);
WRITEUINT8(save_p, players[i].panim);
WRITEUINT8(save_p, players[i].stronganim);
WRITEUINT8(save_p, players[i].spectator);
WRITEUINT16(save_p, players[i].flashpal);
@ -396,6 +397,7 @@ static void P_NetUnArchivePlayers(void)
players[i].playerstate = READUINT8(save_p);
players[i].pflags = READUINT32(save_p);
players[i].panim = READUINT8(save_p);
players[i].stronganim = READUINT8(save_p);
players[i].spectator = READUINT8(save_p);
players[i].flashpal = READUINT16(save_p);

View file

@ -989,6 +989,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
if (player->powers[pw_carry] == CR_ROPEHANG)
P_SetTarget(&player->mo->tracer, NULL);
player->powers[pw_strong] = STR_NONE;
{
angle_t ang;
fixed_t fallbackspeed;
@ -1106,6 +1108,7 @@ void P_ResetPlayer(player_t *player)
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
{
fixed_t bottomheight, topheight;
boolean allatk = ((player->powers[pw_strong] & STR_PUNCH) && (player->powers[pw_strong] & STR_TAIL) && (player->powers[pw_strong] & STR_STOMP) && (player->powers[pw_strong] & STR_UPPER));
if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing))
return false;
@ -1130,22 +1133,33 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
// Jumping.
if ((player->pflags & PF_JUMPED)
&& (!(player->pflags & PF_NOJUMPDAMAGE)
|| (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
&& (!(player->pflags & PF_NOJUMPDAMAGE)))
return true;
// Spinning.
if (player->pflags & PF_SPINNING)
return true;
if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE))
// Shield stomp.
if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY))
return true;
// pw_strong checks below here
// Omnidirectional attacks.
if (allatk || (player->powers[pw_strong] & STR_DASH))
return true;
// From the front.
if (((player->pflags & PF_GLIDING) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
if ((player->powers[pw_strong] & STR_PUNCH)
&& (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) < ANGLE_180)
return true;
// From the back.
if ((player->powers[pw_strong] & STR_TAIL)
&& (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) >= ANGLE_180)
return true;
// From the top/bottom.
bottomheight = player->mo->z;
topheight = player->mo->z + player->mo->height;
@ -1159,19 +1173,15 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
if (P_MobjFlip(player->mo)*(bottomheight - (thing->z + thing->height/2)) > 0)
{
if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0))
if ((player->charflags & SF_STOMPDAMAGE || player->powers[pw_strong] & STR_STOMP) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0))
return true;
}
else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0)
{
if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0))
if ((player->powers[pw_strong] & STR_UPPER) && (player->mo->sprite2 != SPR2_SWIM) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0))
return true;
}
// Shield stomp.
if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY))
return true;
return false;
}
@ -2333,6 +2343,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_s3k8b);
player->pflags |= PF_FULLSTASIS;
player->powers[pw_strong] = STR_MELEE;
// hearticles
if (type)
@ -2557,17 +2568,13 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
return true;
// Passive wall breaking
if (player->charflags & SF_CANBUSTWALLS)
if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING|STR_DASH))
return true;
// Super
if (player->powers[pw_super])
return true;
// Dashmode
if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD)
return true;
// NiGHTS drill
if (player->pflags & PF_DRILLING)
return true;
@ -2578,21 +2585,11 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
/* FALLTHRU */
case BT_STRONG: // Requires a "strong ability"
if (player->charflags & SF_CANBUSTWALLS)
return true;
if (player->pflags & PF_BOUNCING)
return true;
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
return true;
if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING))
return true;
break;
}
return false;
}
@ -2608,7 +2605,7 @@ static void P_CheckBustableBlocks(player_t *player)
oldx = player->mo->x;
oldy = player->mo->y;
if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways
if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS)))) // Don't break sideways without wall powers
{
P_UnsetThingPosition(player->mo);
player->mo->x += player->mo->momx;
@ -2635,8 +2632,24 @@ static void P_CheckBustableBlocks(player_t *player)
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY))
|| ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2)))))
// Height checks
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z > topheight)
continue;
if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height < bottomheight)
continue;
}
else
{
if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z < bottomheight)
continue;
if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height > topheight)
continue;
}
if (player->powers[pw_strong] & (STR_FLOOR|STR_CEILING))
{
topheight -= player->mo->momz;
bottomheight -= player->mo->momz;
@ -2704,7 +2717,7 @@ static void P_CheckBustableBlocks(player_t *player)
}
}
bustupdone:
if (!(player->pflags & PF_BOUNCING))
if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS))))
{
P_UnsetThingPosition(player->mo);
player->mo->x = oldx;
@ -4769,6 +4782,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
player->mo->momx += player->cmomx;
player->mo->momy += player->cmomy;
P_SetPlayerMobjState(player->mo, S_PLAY_MELEE);
player->powers[pw_strong] = STR_MELEE;
S_StartSound(player->mo, sfx_s3k42);
}
player->pflags |= PF_SPINDOWN;
@ -5016,6 +5030,7 @@ static void P_DoTwinSpin(player_t *player)
S_StartSound(player->mo, sfx_s3k42);
player->mo->frame = 0;
P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
player->powers[pw_strong] = STR_TWINSPIN;
}
//
@ -5383,6 +5398,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
player->pflags |= PF_THOKKED;
else
player->pflags |= (PF_THOKKED|PF_CANCARRY);
player->powers[pw_strong] = STR_FLY;
}
break;
case CA_GLIDEANDCLIMB:
@ -5409,7 +5425,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
if (playerspeed < glidespeed)
P_Thrust(player->mo, player->mo->angle, glidespeed - playerspeed);
player->pflags &= ~(PF_SPINNING|PF_STARTDASH);
player->pflags &= ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH);
player->powers[pw_strong] = STR_GLIDE;
}
break;
case CA_DOUBLEJUMP: // Double-Jump
@ -5469,6 +5486,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE);
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING);
player->pflags |= PF_THOKKED|PF_BOUNCING;
player->powers[pw_strong] = STR_BOUNCE;
player->mo->momx >>= 1;
player->mo->momy >>= 1;
player->mo->momz >>= 1;
@ -12172,6 +12190,16 @@ void P_PlayerThink(player_t *player)
else
player->powers[pw_ignorelatch] = 0;
if (player->powers[pw_strong] & STR_ANIM)
{
if (!(player->stronganim))
player->stronganim = player->panim;
else if (player->panim != player->stronganim)
player->powers[pw_strong] = STR_NONE;
}
else if (player->stronganim)
player->stronganim = 0;
//pw_super acts as a timer now
if (player->powers[pw_super]
&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]
@ -12266,6 +12294,8 @@ void P_PlayerThink(player_t *player)
{
player->normalspeed = skins[player->skin].normalspeed; // Reset to default if not capable of entering dash mode.
player->jumpfactor = skins[player->skin].jumpfactor;
if (player->powers[pw_strong] & STR_DASH)
player->powers[pw_strong] = STR_NONE;
}
}
else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground.
@ -12275,6 +12305,9 @@ void P_PlayerThink(player_t *player)
if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height.
player->jumpfactor += FRACUNIT/300;
if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL)))
player->powers[pw_strong] = STR_METAL;
}
if (player->normalspeed >= skins[player->skin].normalspeed*2)
@ -12292,6 +12325,8 @@ void P_PlayerThink(player_t *player)
player->normalspeed = skins[player->skin].normalspeed;
player->jumpfactor = skins[player->skin].jumpfactor;
S_StartSound(player->mo, sfx_kc65);
if (player->powers[pw_strong] & STR_DASH)
player->powers[pw_strong] = STR_NONE;
}
dashmode = 0;
}