Introducing CA2_GUNSLINGER.

* Mildly hacky proof of concept! Will de-hack later.
* Charge up your ability!
* You can only damage others if it's at full power.
* Fires directly at enemies/bosses when at full power. Does NOT aim at players.
This commit is contained in:
toasterbabe 2017-03-21 00:54:47 +00:00
parent ee74fa4042
commit 59bc0da022
9 changed files with 181 additions and 65 deletions

View File

@ -75,6 +75,7 @@ typedef enum
CA2_NONE=0, CA2_NONE=0,
CA2_SPINDASH, CA2_SPINDASH,
CA2_MULTIABILITY, CA2_MULTIABILITY,
CA2_GUNSLINGER,
CA2_MELEE CA2_MELEE
} charability2_t; } charability2_t;

View File

@ -3908,7 +3908,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAY_DEAD", "S_PLAY_DEAD",
"S_PLAY_DRWN", "S_PLAY_DRWN",
"S_PLAY_ROLL", "S_PLAY_ROLL",
"S_PLAY_SPINDASH",
"S_PLAY_GASP", "S_PLAY_GASP",
"S_PLAY_JUMP", "S_PLAY_JUMP",
"S_PLAY_SPRING", "S_PLAY_SPRING",
@ -3916,6 +3915,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAY_EDGE", "S_PLAY_EDGE",
"S_PLAY_RIDE", "S_PLAY_RIDE",
// CA2_SPINDASH
"S_PLAY_SPINDASH",
// CA_FLY/SWIM // CA_FLY/SWIM
"S_PLAY_FLY", "S_PLAY_FLY",
"S_PLAY_SWIM", "S_PLAY_SWIM",
@ -3934,6 +3936,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAY_BOUNCE", "S_PLAY_BOUNCE",
"S_PLAY_BOUNCE_LANDING", "S_PLAY_BOUNCE_LANDING",
// CA2_GUNSLINGER
"S_PLAY_CHARGE",
"S_PLAY_FIRE",
// CA_TWINSPIN // CA_TWINSPIN
"S_PLAY_TWINSPIN", "S_PLAY_TWINSPIN",
@ -7398,6 +7404,7 @@ struct {
{"CA2_NONE",CA2_NONE}, // now slot 0! {"CA2_NONE",CA2_NONE}, // now slot 0!
{"CA2_SPINDASH",CA2_SPINDASH}, {"CA2_SPINDASH",CA2_SPINDASH},
{"CA2_MULTIABILITY",CA2_MULTIABILITY}, {"CA2_MULTIABILITY",CA2_MULTIABILITY},
{"CA2_GUNSLINGER",CA2_GUNSLINGER},
{"CA2_MELEE",CA2_MELEE}, {"CA2_MELEE",CA2_MELEE},
// Sound flags // Sound flags

View File

@ -396,7 +396,6 @@ char spr2names[NUMPLAYERSPRITES][5] =
"DEAD", "DEAD",
"DRWN", "DRWN",
"ROLL", "ROLL",
"SPIN",
"GASP", "GASP",
"JUMP", "JUMP",
"SPNG", "SPNG",
@ -404,6 +403,8 @@ char spr2names[NUMPLAYERSPRITES][5] =
"EDGE", "EDGE",
"RIDE", "RIDE",
"SPIN",
"FLY_", "FLY_",
"SWIM", "SWIM",
"TIRE", "TIRE",
@ -418,6 +419,9 @@ char spr2names[NUMPLAYERSPRITES][5] =
"BNCE", "BNCE",
"BLND", "BLND",
"CHRG",
"FIRE",
"TWIN", "TWIN",
"MLEE", "MLEE",
@ -500,7 +504,6 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DEAD {SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DEAD
{SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DRWN {SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DRWN
{SPR_PLAY, SPR2_ROLL, 1, {NULL}, 0, 0, S_PLAY_ROLL}, // S_PLAY_ROLL {SPR_PLAY, SPR2_ROLL, 1, {NULL}, 0, 0, S_PLAY_ROLL}, // S_PLAY_ROLL
{SPR_PLAY, SPR2_SPIN, 2, {NULL}, 0, 0, S_PLAY_SPINDASH}, // S_PLAY_SPINDASH
{SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK}, // S_PLAY_GASP {SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK}, // S_PLAY_GASP
{SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP
{SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING
@ -508,6 +511,9 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_EDGE|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_EDGE {SPR_PLAY, SPR2_EDGE|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_EDGE
{SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
// CA2_SPINDASH
{SPR_PLAY, SPR2_SPIN, 2, {NULL}, 0, 0, S_PLAY_SPINDASH}, // S_PLAY_SPINDASH
// CA_FLY/CA_SWIM // CA_FLY/CA_SWIM
{SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY
{SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM
@ -524,7 +530,11 @@ state_t states[NUMSTATES] =
// CA_BOUNCE // CA_BOUNCE
{SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE
{SPR_PLAY, SPR2_BLND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 4, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING {SPR_PLAY, SPR2_BLND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 0, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING
// CA2_GUNSLINGER
{SPR_PLAY, SPR2_CHRG, 2, {NULL}, 0, 0, S_PLAY_CHARGE}, // S_PLAY_CHARGE
{SPR_PLAY, SPR2_FIRE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_STND, 0, S_PLAY_FIRE}, // S_PLAY_FIRE
// CA_TWINSPIN // CA_TWINSPIN
{SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN

View File

@ -609,7 +609,6 @@ enum playersprite
SPR2_DEAD, SPR2_DEAD,
SPR2_DRWN, // drown SPR2_DRWN, // drown
SPR2_ROLL, SPR2_ROLL,
SPR2_SPIN, // spindash charge
SPR2_GASP, SPR2_GASP,
SPR2_JUMP, SPR2_JUMP,
SPR2_SPNG, // spring SPR2_SPNG, // spring
@ -617,6 +616,8 @@ enum playersprite
SPR2_EDGE, SPR2_EDGE,
SPR2_RIDE, SPR2_RIDE,
SPR2_SPIN, // spindash
SPR2_FLY , SPR2_FLY ,
SPR2_SWIM, SPR2_SWIM,
SPR2_TIRE, // tired SPR2_TIRE, // tired
@ -631,6 +632,9 @@ enum playersprite
SPR2_BNCE, // bounce SPR2_BNCE, // bounce
SPR2_BLND, // bounce landing SPR2_BLND, // bounce landing
SPR2_CHRG, // charge
SPR2_FIRE, // fire
SPR2_TWIN, // twinspin SPR2_TWIN, // twinspin
SPR2_MLEE, // melee SPR2_MLEE, // melee
@ -710,7 +714,6 @@ typedef enum state
S_PLAY_DEAD, S_PLAY_DEAD,
S_PLAY_DRWN, S_PLAY_DRWN,
S_PLAY_ROLL, S_PLAY_ROLL,
S_PLAY_SPINDASH,
S_PLAY_GASP, S_PLAY_GASP,
S_PLAY_JUMP, S_PLAY_JUMP,
S_PLAY_SPRING, S_PLAY_SPRING,
@ -718,6 +721,9 @@ typedef enum state
S_PLAY_EDGE, S_PLAY_EDGE,
S_PLAY_RIDE, S_PLAY_RIDE,
// CA2_SPINDASH
S_PLAY_SPINDASH,
// CA_FLY/SWIM // CA_FLY/SWIM
S_PLAY_FLY, S_PLAY_FLY,
S_PLAY_SWIM, S_PLAY_SWIM,
@ -736,6 +742,10 @@ typedef enum state
S_PLAY_BOUNCE, S_PLAY_BOUNCE,
S_PLAY_BOUNCE_LANDING, S_PLAY_BOUNCE_LANDING,
// CA2_GUNSLINGER
S_PLAY_CHARGE,
S_PLAY_FIRE,
// CA_TWINSPIN // CA_TWINSPIN
S_PLAY_TWINSPIN, S_PLAY_TWINSPIN,

View File

@ -1055,11 +1055,12 @@ static int lib_pLookForEnemies(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean nonenemies = lua_opttrueboolean(L, 2); boolean nonenemies = lua_opttrueboolean(L, 2);
boolean abovehorizontal = lua_opttrueboolean(L, 3);
NOHUD NOHUD
INLEVEL INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_LookForEnemies(player, nonenemies)); lua_pushboolean(L, P_LookForEnemies(player, nonenemies, abovehorizontal));
return 1; return 1;
} }

View File

@ -174,7 +174,7 @@ fixed_t P_ReturnThrustX(mobj_t *mo, angle_t angle, fixed_t move);
fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move); fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move);
void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move);
boolean P_LookForEnemies(player_t *player, boolean nonenemies); boolean P_LookForEnemies(player_t *player, boolean nonenemies, boolean abovehorizontal);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_SuperReady(player_t *player); boolean P_SuperReady(player_t *player);

View File

@ -938,11 +938,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->eflags & MFE_VERTICALFLIP) if (tmthing->eflags & MFE_VERTICALFLIP)
{ {
if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && thing->eflags & MFE_VERTICALFLIP))
P_DamageMobj(thing, tmthing, tmthing, 1, 0); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
} }
else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && !(thing->eflags & MFE_VERTICALFLIP)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
} }
else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?!
@ -950,11 +952,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->eflags & MFE_VERTICALFLIP) if (thing->eflags & MFE_VERTICALFLIP)
{ {
if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP))
P_DamageMobj(tmthing, thing, thing, 1, 0); P_DamageMobj(tmthing, thing, thing, 1, 0);
} }
else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP)))
P_DamageMobj(tmthing, thing, thing, 1, 0); P_DamageMobj(tmthing, thing, thing, 1, 0);
} }

View File

@ -280,6 +280,10 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2)
spr2 = SPR2_ROLL; spr2 = SPR2_ROLL;
break; break;
case SPR2_FIRE:
spr2 = SPR2_CHRG;
break;
case SPR2_TWIN: case SPR2_TWIN:
spr2 = SPR2_ROLL; spr2 = SPR2_ROLL;
break; break;
@ -470,6 +474,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
player->panim = PA_ABILITY; player->panim = PA_ABILITY;
break; break;
case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific. case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific.
case S_PLAY_CHARGE:
case S_PLAY_FIRE:
case S_PLAY_MELEE: case S_PLAY_MELEE:
case S_PLAY_MELEE_FINISH: case S_PLAY_MELEE_FINISH:
case S_PLAY_MELEE_LANDING: case S_PLAY_MELEE_LANDING:
@ -517,7 +523,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
else else
mobj->tics = 1; mobj->tics = 1;
} }
else if (player->panim == PA_ABILITY2 && player->charability2 == CA2_SPINDASH) else if (player->panim == PA_ABILITY2 && (player->charability2 == CA2_SPINDASH || state == S_PLAY_CHARGE))
{ {
fixed_t step = (player->maxdash - player->mindash)/4; fixed_t step = (player->maxdash - player->mindash)/4;
speed = (player->dashspeed - player->mindash); speed = (player->dashspeed - player->mindash);

View File

@ -3775,10 +3775,9 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
{ {
player->mo->momx = player->cmomx; player->mo->momx = player->cmomx;
player->mo->momy = player->cmomy; player->mo->momy = player->cmomy;
player->pflags |= PF_STARTDASH|PF_SPINNING; player->pflags |= (PF_USEDOWN|PF_STARTDASH|PF_SPINNING);
player->dashspeed = player->mindash; player->dashspeed = player->mindash;
P_SetPlayerMobjState(player->mo, S_PLAY_SPINDASH); P_SetPlayerMobjState(player->mo, S_PLAY_SPINDASH);
player->pflags |= PF_USEDOWN;
if (!player->spectator) if (!player->spectator)
S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh.
} }
@ -3809,15 +3808,97 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
&& !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale) && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
|| !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING))) || !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING)))
{ {
player->pflags |= PF_SPINNING; player->pflags |= (PF_USEDOWN|PF_SPINNING);
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
if (!player->spectator) if (!player->spectator)
S_StartSound(player->mo, sfx_spin); S_StartSound(player->mo, sfx_spin);
player->pflags |= PF_USEDOWN; }
else
// Catapult the player from a spindash rev!
if (onground && !(player->pflags & PF_USEDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))
{
player->pflags &= ~PF_STARTDASH;
if (player->powers[pw_carry] == CR_BRAKGOOP)
player->dashspeed = 0;
if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE))
{
if (player->dashspeed)
{
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->dashspeed, player->mo->scale)); // catapult forward ho!!
}
else
{
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
player->pflags &= ~PF_SPINNING;
}
if (!player->spectator)
S_StartSound(player->mo, sfx_zoom);
}
player->dashspeed = 0;
}
break;
case CA2_GUNSLINGER:
if ((cmd->buttons & BT_USE)
&& !player->mo->momz && onground
&& canstand)
{
if (!player->dashspeed)
{
player->mo->momx = player->cmomx;
player->mo->momy = player->cmomy;
player->pflags |= PF_USEDOWN;
player->dashspeed = player->mindash;
P_SetPlayerMobjState(player->mo, S_PLAY_CHARGE);
if (!player->spectator)
S_StartSound(player->mo, sfx_s3k5a); // Make the rev sound! Previously sfx_spndsh.
}
else if (player->dashspeed < player->maxdash)
player->dashspeed += FRACUNIT;
else if (player->mo->tics != -1)
{
player->mo->tics = -1;
player->mo->frame = 0;
}
}
else if (player->dashspeed && (player->pflags & PF_USEDOWN))
{
mobj_t *cork;
const boolean maxspeed = (player->dashspeed >= player->maxdash);
P_SetPlayerMobjState(player->mo, S_PLAY_FIRE);
if (maxspeed && P_LookForEnemies(player, false, true) && player->mo->tracer)
{
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y);
cork = P_SpawnMissile(player->mo, player->mo->tracer, player->spinitem);
}
else
{
fixed_t z = (player->mo->z + player->mo->height/2);
if ((cork = P_SpawnPointMissile(player->mo, player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, FRACUNIT), player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, FRACUNIT), z, player->spinitem, player->mo->x, player->mo->y, z)))
{
cork->flags &= ~MF_NOGRAVITY;
if (!maxspeed)
cork->flags |= MF_NOCLIPTHING;
}
}
if (cork)
{
cork->momx = FixedDiv(FixedMul(cork->momx, player->dashspeed), mobjinfo[player->spinitem].speed);
cork->momy = FixedDiv(FixedMul(cork->momy, player->dashspeed), mobjinfo[player->spinitem].speed);
if (player->mo->tracer)
cork->momz = ((player->mo->tracer->z - player->mo->z) / (P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y) / player->dashspeed));
}
P_SetTarget(&player->mo->tracer, NULL);
player->dashspeed = 0;
} }
break; break;
case CA2_MELEE: // Melee attack case CA2_MELEE: // Melee attack
if (!(player->panim == PA_ABILITY2) && (cmd->buttons & BT_USE) if (player->panim != PA_ABILITY2 && (cmd->buttons & BT_USE)
&& !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN)
&& canstand) && canstand)
{ {
@ -3870,33 +3951,6 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
} }
} }
// Catapult the player from a spindash rev!
if (onground && !(player->pflags & PF_USEDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))
{
player->pflags &= ~PF_STARTDASH;
if (player->powers[pw_carry] == CR_BRAKGOOP)
player->dashspeed = 0;
if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE))
{
if (player->dashspeed)
{
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->dashspeed, player->mo->scale)); // catapult forward ho!!
}
else
{
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
player->pflags &= ~PF_SPINNING;
}
if (!player->spectator)
S_StartSound(player->mo, sfx_zoom);
}
player->dashspeed = 0;
}
if (onground && player->pflags & PF_STARTDASH) if (onground && player->pflags & PF_STARTDASH)
{ {
if (player->mo->state-states != S_PLAY_SPINDASH) if (player->mo->state-states != S_PLAY_SPINDASH)
@ -4211,7 +4265,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if (player->charability == CA_HOMINGTHOK && !player->homing) if (player->charability == CA_HOMINGTHOK && !player->homing)
{ {
if (P_LookForEnemies(player, true)) if (P_LookForEnemies(player, true, false))
{ {
if (player->mo->tracer) if (player->mo->tracer)
player->homing = 3*TICRATE; player->homing = 3*TICRATE;
@ -4885,13 +4939,14 @@ static void P_3dMovement(player_t *player)
// Allow a bit of movement while spinning // Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING) if (player->pflags & PF_SPINNING)
{ {
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)) if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)
|| (player->pflags & PF_STARTDASH))
movepushforward = 0; movepushforward = 0;
else if (!(player->pflags & PF_STARTDASH))
movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
else else
movepushforward = 0; movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
} }
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
movepushforward = 0;
movepushforward = FixedMul(movepushforward, player->mo->scale); movepushforward = FixedMul(movepushforward, player->mo->scale);
@ -4928,13 +4983,14 @@ static void P_3dMovement(player_t *player)
{ {
// Stupid little movement prohibitor hack // Stupid little movement prohibitor hack
// that REALLY shouldn't belong in analog code. // that REALLY shouldn't belong in analog code.
if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)) if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)
|| (player->pflags & PF_STARTDASH))
movepushforward = 0; movepushforward = 0;
else if (!(player->pflags & PF_STARTDASH))
movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
else else
movepushforward = 0; movepushforward = FixedDiv(movepushforward, 16*FRACUNIT);
} }
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
movepushforward = 0;
movepushsideangle = controldirection; movepushsideangle = controldirection;
@ -4964,11 +5020,13 @@ static void P_3dMovement(player_t *player)
// Allow a bit of movement while spinning // Allow a bit of movement while spinning
if (player->pflags & PF_SPINNING) if (player->pflags & PF_SPINNING)
{ {
if (!(player->pflags & PF_STARTDASH)) if ((player->pflags & PF_STARTDASH))
movepushside = FixedDiv(movepushside,16*FRACUNIT);
else
movepushside = 0; movepushside = 0;
else
movepushside = FixedDiv(movepushside,16*FRACUNIT);
} }
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
movepushside = 0;
// Finally move the player now that his speed/direction has been decided. // Finally move the player now that his speed/direction has been decided.
movepushside = FixedMul(movepushside, player->mo->scale); movepushside = FixedMul(movepushside, player->mo->scale);
@ -6555,6 +6613,7 @@ static void P_MovePlayer(player_t *player)
// Control relinquishing stuff! // Control relinquishing stuff!
if ((player->powers[pw_carry] == CR_BRAKGOOP) if ((player->powers[pw_carry] == CR_BRAKGOOP)
|| (player->pflags & PF_GLIDING && player->skidtime) || (player->pflags & PF_GLIDING && player->skidtime)
|| (player->charability2 == CA2_GUNSLINGER && player->mo->state-states == S_PLAY_FIRE)
|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
player->pflags |= PF_FULLSTASIS; player->pflags |= PF_FULLSTASIS;
else if (player->powers[pw_nocontrol]) else if (player->powers[pw_nocontrol])
@ -7165,7 +7224,7 @@ static void P_MovePlayer(player_t *player)
case SH_ATTRACT: case SH_ATTRACT:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->homing = 2; player->homing = 2;
if (P_LookForEnemies(player, false) && player->mo->tracer) if (P_LookForEnemies(player, false, false) && player->mo->tracer)
{ {
player->pflags &= ~PF_NOJUMPDAMAGE; player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
@ -7812,8 +7871,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
// P_LookForEnemies // P_LookForEnemies
// Looks for something you can hit - Used for homing attack // Looks for something you can hit - Used for homing attack
// If nonenemies is true, includes monitors and springs! // If nonenemies is true, includes monitors and springs!
// If abovehorizontal is true, you can look up, but your total vertical range is limited to compensate.
// //
boolean P_LookForEnemies(player_t *player, boolean nonenemies) boolean P_LookForEnemies(player_t *player, boolean nonenemies, boolean abovehorizontal)
{ {
mobj_t *mo; mobj_t *mo;
thinker_t *think; thinker_t *think;
@ -7845,13 +7905,30 @@ boolean P_LookForEnemies(player_t *player, boolean nonenemies)
if (mo->type == MT_DETON) // Don't be STUPID, Sonic! if (mo->type == MT_DETON) // Don't be STUPID, Sonic!
continue; continue;
if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale)) && !(player->mo->eflags & MFE_VERTICALFLIP)) {
|| ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame. fixed_t dist = P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y);
continue; // Don't home upwards!
if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), if (abovehorizontal)
player->mo->z-mo->z) > FixedMul(RING_DIST, player->mo->scale)) {
continue; // out of range angle_t ang = R_PointToAngle2(0, player->mo->z, dist, mo->z) + ANGLE_45;
if (ang > ANGLE_90)
continue; // Don't home outside of desired angle!
}
else // Don't home upwards!
{
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if (mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale))
continue;
}
else if (mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale))
continue;
}
if (P_AproxDistance(dist,
player->mo->z-mo->z) > FixedMul(RING_DIST, player->mo->scale))
continue; // out of range
}
if ((twodlevel || player->mo->flags2 & MF2_TWOD) if ((twodlevel || player->mo->flags2 & MF2_TWOD)
&& abs(player->mo->y-mo->y) > player->mo->radius) && abs(player->mo->y-mo->y) > player->mo->radius)