diff --git a/extras/ACS/lib/inc/ACS/bkdefs.acs b/extras/ACS/lib/inc/ACS/bkdefs.acs index 73905a2e8..0c22ee8e9 100644 --- a/extras/ACS/lib/inc/ACS/bkdefs.acs +++ b/extras/ACS/lib/inc/ACS/bkdefs.acs @@ -649,6 +649,7 @@ enum MF2_LINKDRAW = 1<<28, MF2_SHIELD = 1<<29, MF2_SPLAT = 1<<30, + MF2_WATERRUN = 1<<31, }; enum diff --git a/src/d_player.h b/src/d_player.h index b5072a2da..d57f9e1f2 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -623,7 +623,6 @@ struct player_t UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters) UINT8 floorboost; // (0 to 3) - Prevents Sneaker sounds for a brief duration when triggered by a floor panel - boolean waterrun; // Tracks condition of water run UINT8 boostcharge; // Charge during race start diff --git a/src/deh_tables.c b/src/deh_tables.c index ddaa1fb03..b2c1f2383 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -194,6 +194,7 @@ const char *const MOBJFLAG2_LIST[] = { "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) + "WATERRUN", // Mobj is able to run on Water! NULL }; diff --git a/src/k_kart.c b/src/k_kart.c index e0a27dcda..6cc84af15 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -417,12 +417,12 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] = INT32 K_GetShieldFromPlayer(player_t *player) { - + if (player->flametimer > 0) { return KSHIELD_FLAME; } - + switch (player->itemtype) { case KITEM_THUNDERSHIELD: return KSHIELD_THUNDER; @@ -3118,13 +3118,147 @@ boolean K_TripwirePass(player_t *player) return (player->tripwirePass != TRIPWIRE_NONE); } -boolean K_WaterRun(player_t *player) +boolean K_ItemMobjAllowedtoWaterRun(mobj_t *item) { - if (player->waterrun) - return true; + switch (item->type) + { + case MT_ORBINAUT: + case MT_JAWZ: + case MT_JAWZ_DUD: + case MT_DROPTARGET: + case MT_BANANA_SHIELD: + case MT_DROPTARGET_SHIELD: + case MT_SSMINE_SHIELD: + return true; + break; + default: + return false; + break; + } return false; } +boolean K_WaterRun(mobj_t *mobj) +{ + // Let dragged items waterrun with the player for free. + switch (mobj->type) + { + case MT_BANANA_SHIELD: + case MT_DROPTARGET_SHIELD: + case MT_SSMINE_SHIELD: + if (mobj->target && (mobj->target->flags2 & MF2_WATERRUN)) + return true; + break; + default: + break; + } + + if (mobj->flags2 & MF2_WATERRUN) + { + return true; + } + + return false; +} + +void K_SpawnWaterTrail(mobj_t *mobj) +{ + fixed_t topspeed = mobj->player ? K_GetKartSpeed(mobj->player, false, false) : K_GetKartSpeedFromStat(5); + fixed_t runspd = 14*mobj->scale; //srb2kart + runspd = FixedMul(runspd, mobj->movefactor); + fixed_t trailScale; + + if (topspeed > runspd) + { + if (mobj->player) + { + trailScale = FixedMul(FixedDiv(mobj->player->speed - runspd, topspeed - runspd), mapobjectscale); + } + else + { + trailScale = FixedMul(FixedDiv(R_PointToDist2(0, 0, mobj->momx, mobj->momy) - runspd, topspeed - runspd), mapobjectscale); + } + } + else + trailScale = mapobjectscale; // Scaling is based off difference between runspeed and top speed + + if (trailScale > 0) + { + const angle_t forwardangle = K_MomentumAngle(mobj); + const fixed_t visualradius = mobj->radius + (8 * mobj->scale); + const SINT8 numFrames = 5; + const INT32 curFrame = (leveltime % numFrames)|FF_PAPERSPRITE; + fixed_t x1, x2, y1, y2; + mobj_t *water; + + x1 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle + ANGLE_90, visualradius); + y1 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle + ANGLE_90, visualradius); + x1 = x1 + P_ReturnThrustX(mobj, forwardangle, visualradius); + y1 = y1 + P_ReturnThrustY(mobj, forwardangle, visualradius); + + x2 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle - ANGLE_90, visualradius); + y2 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle - ANGLE_90, visualradius); + x2 = x2 + P_ReturnThrustX(mobj, forwardangle, visualradius); + y2 = y2 + P_ReturnThrustY(mobj, forwardangle, visualradius); + + // Left + // underlay + water = P_SpawnMobj(x1, y1, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); + water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, S_WATERTRAILSUNDERLAY); + water->frame = curFrame|FF_ADD|FF_TRANS40; + + // overlay + water = P_SpawnMobj(x1, y1, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); + water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, S_WATERTRAILS); + water->frame = curFrame; + + // Right + // Underlay + water = P_SpawnMobj(x2, y2, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); + water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, S_WATERTRAILSUNDERLAY); + water->frame = curFrame|FF_ADD|FF_TRANS40; + + // Overlay + water = P_SpawnMobj(x2, y2, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); + water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, S_WATERTRAILS); + water->frame = curFrame; + + if (!S_SoundPlaying(mobj, sfx_s3kdbs)) + { + const INT32 volume = (min(trailScale, FRACUNIT) * 255) / FRACUNIT; + S_StartSoundAtVolume(mobj, sfx_s3kdbs, volume); + } + } +} + static fixed_t K_FlameShieldDashVar(INT32 val) { // 1 second = 15% + ????% top speed @@ -3214,7 +3348,7 @@ static void K_GetKartBoostPower(player_t *player) { ADDBOOST(FRACUNIT/5, 0); // + 20% top speed, + 0% acceleration } - + if (player->flamestore) // Flame Shield dash { fixed_t dash = K_FlameShieldDashVar(player->flamedash); @@ -3222,10 +3356,10 @@ static void K_GetKartBoostPower(player_t *player) fixed_t boost = 0; fixed_t val = 52428; // Rim idea: diminish starts around 1.2x sneaker speed and plateaus around 1.4-1.5x fixed_t accel = 3*FRACUNIT; - + intermediate = FixedDiv(FixedMul(val, FRACUNIT*-1/2) - FRACUNIT/4,-val+FRACUNIT/2); boost = FixedMul(val,(FRACUNIT-FixedDiv(FRACUNIT,(dash+intermediate)))); - + ADDBOOST(boost, accel); } @@ -4015,6 +4149,15 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I th->flags2 |= flags2; + if (source->flags2 & MF2_WATERRUN) + { + // Allow certain items to run on water as well! + if (K_ItemMobjAllowedtoWaterRun(th)) + { + th->flags2 |= MF2_WATERRUN; + } + } + th->threshold = 10; if (th->info->seesound) @@ -5064,7 +5207,7 @@ void K_DoWaterRunPanel(player_t *player) } player->sneakertimer = TICRATE*2; - player->waterrun = true; + player->mo->flags2 |= MF2_WATERRUN; // set angle for spun out players: player->boostangle = player->mo->angle; @@ -6993,7 +7136,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->floorboost--; if (player->sneakertimer == 0) - player->waterrun = false; + { + // No more waterrunning for you pal! + player->mo->flags2 &= ~MF2_WATERRUN; + } if (player->driftboost) player->driftboost--; @@ -8375,7 +8521,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) if (player->invincibilitytimer || player->sneakertimer || player->growshrinktimer > 0) turnvalue = FixedMul(turnvalue, FixedDiv(5*FRACUNIT, 4*FRACUNIT)); - + if (player->flamedash && player->flamestore) // Reduce turning { fixed_t dashval = ((player->flamedash<flametimer == 0) { player->itemamount--; diff --git a/src/k_kart.h b/src/k_kart.h index 793fca5e8..134ca1bda 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -152,7 +152,9 @@ boolean K_SlopeResistance(player_t *player); fixed_t K_PlayerTripwireSpeedThreshold(player_t *player); tripwirepass_t K_TripwirePassConditions(player_t *player); boolean K_TripwirePass(player_t *player); -boolean K_WaterRun(player_t *player); +boolean K_WaterRun(mobj_t *mobj); +void K_SpawnWaterTrail(mobj_t *mobj); +boolean K_ItemMobjAllowedtoWaterRun(mobj_t *item); void K_SetTireGrease(player_t *player, tic_t tics); void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_ApplyTripWire(player_t *player, tripwirestate_t state); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c4ca9355e..f1ee10811 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -360,8 +360,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->sneakertimer); else if (fastcmp(field,"floorboost")) lua_pushinteger(L, plr->floorboost); - else if (fastcmp(field,"waterrun")) - lua_pushinteger(L, plr->waterrun); else if (fastcmp(field,"growshrinktimer")) lua_pushinteger(L, plr->growshrinktimer); else if (fastcmp(field,"growcancel")) @@ -777,8 +775,6 @@ static int player_set(lua_State *L) plr->sneakertimer = luaL_checkinteger(L, 3); else if (fastcmp(field,"floorboost")) plr->floorboost = luaL_checkinteger(L, 3); - else if (fastcmp(field,"waterrun")) - plr->waterrun = luaL_checkboolean(L, 3); else if (fastcmp(field,"growshrinktimer")) plr->growshrinktimer = luaL_checkinteger(L, 3); else if (fastcmp(field,"growcancel")) diff --git a/src/p_local.h b/src/p_local.h index a2b240251..09f23b231 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -362,7 +362,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); -boolean P_CanRunOnWater(player_t *player, ffloor_t *rover); +boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover); boolean P_CheckSolidFFloorSurface(mobj_t *mobj, ffloor_t *rover); void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot); diff --git a/src/p_map.c b/src/p_map.c index 6f646b255..f08960ae9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2467,17 +2467,8 @@ BlockItReturn_t PIT_PushableMoved(mobj_t *thing) static boolean P_WaterRunning(mobj_t *thing) { ffloor_t *rover = thing->floorrover; - - if (thing->player) - { - return rover && (rover->fofflags & FOF_SWIMMABLE) && - P_IsObjectOnGround(thing) && thing->player->waterrun; - } - else - { - // Maybe move waterrun bool to mobj_t someday..? - return false; - } + return rover && (rover->fofflags & FOF_SWIMMABLE) && + P_IsObjectOnGround(thing) && (thing->flags2 & MF2_WATERRUN); } static boolean P_WaterStepUp(mobj_t *thing) diff --git a/src/p_mobj.c b/src/p_mobj.c index f43bfcc30..d61836615 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2997,11 +2997,11 @@ boolean P_SceneryZMovement(mobj_t *mo) // // P_CanRunOnWater // -// Returns true if player can water run on a 3D floor +// Returns true if mobj can water run on a 3D floor // -boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) +boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover) { - const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); + const boolean flip = (mobj->eflags & MFE_VERTICALFLIP); fixed_t surfaceheight = INT32_MAX; fixed_t playerbottom = INT32_MAX; fixed_t surfDiff = INT32_MAX; @@ -3024,28 +3024,29 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) return false; } - if (player->carry != CR_NONE) // Special carry state. + if (mobj->player && mobj->player->carry != CR_NONE) // Special carry state. { // No good player state. return false; } - if (P_IsObjectOnGround(player->mo) == false) + if (P_IsObjectOnGround(mobj) == false && !K_ItemMobjAllowedtoWaterRun(mobj)) { // Don't allow jumping onto water to start a water run. + // (Unless you are some specfic item mobjs!) // (Already water running still counts as being on the ground.) return false; } - if (K_WaterRun(player) == false) + if (K_WaterRun(mobj) == false) { // Basic conditions for enabling water run. return false; } - if (player->mo->standingslope != NULL) + if (mobj->standingslope != NULL) { - ourZAng = player->mo->standingslope->zangle; + ourZAng = mobj->standingslope->zangle; } waterSlope = (flip ? *rover->b_slope : *rover->t_slope); @@ -3060,10 +3061,10 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) return false; } - surfaceheight = flip ? P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y) : P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y); - playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z; + surfaceheight = flip ? P_GetFFloorBottomZAt(rover, mobj->x, mobj->y) : P_GetFFloorTopZAt(rover, mobj->x, mobj->y); + playerbottom = flip ? (mobj->z + mobj->height) : mobj->z; - doifit = flip ? (surfaceheight - player->mo->floorz >= player->mo->height) : (player->mo->ceilingz - surfaceheight >= player->mo->height); + doifit = flip ? (surfaceheight - mobj->floorz >= mobj->height) : (mobj->ceilingz - surfaceheight >= mobj->height); if (!doifit) { @@ -3071,7 +3072,7 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) return false; } - maxStep = P_GetThingStepUp(player->mo, player->mo->x, player->mo->y); + maxStep = P_GetThingStepUp(mobj, mobj->x, mobj->y); surfDiff = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight); if (surfDiff <= maxStep && surfDiff >= 0) @@ -3087,13 +3088,12 @@ boolean P_CheckSolidFFloorSurface(mobj_t *mobj, ffloor_t *rover) { if (!mobj->player) { - // future proff if we ever decide to allow mobjs - // to interact with P_CheckSolidFFloorSurface - return false; + // They can run on water now! + return P_CanRunOnWater(mobj, rover); } return P_CheckSolidLava(rover) || - P_CanRunOnWater(mobj->player, rover); + P_CanRunOnWater(mobj, rover); } // @@ -6730,6 +6730,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->movecount = 2; mobj->frame++; } + mobj->flags2 &= ~MF2_WATERRUN; } else { @@ -6768,6 +6769,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_Thrust(mobj, mobj->angle, thrustamount); + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < 8*FRACUNIT) + { + // Not moving fast enough to water run. + mobj->flags2 &= ~MF2_WATERRUN; + } + sec2 = P_ThingOnSpecial3DFloor(mobj); if ((mobj->terrain && mobj->terrain->pogoSpring > 0) || (sec2 && (sec2->specialflags & (SSF_YELLOWPOGOSPRING|SSF_REDPOGOSPRING))) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) @@ -6834,6 +6841,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) K_DriftDustHandling(mobj); + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < 8*FRACUNIT) + { + // Not moving fast enough to water run. + mobj->flags2 &= ~MF2_WATERRUN; + } + sec2 = P_ThingOnSpecial3DFloor(mobj); if ((mobj->terrain && mobj->terrain->pogoSpring > 0) || (sec2 && (sec2->specialflags & (SSF_YELLOWPOGOSPRING|SSF_REDPOGOSPRING))) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) @@ -6854,6 +6867,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) S_StartSound(mobj, mobj->info->deathsound); mobj->flags &= ~MF_NOCLIPTHING; } + mobj->flags2 &= ~MF2_WATERRUN; } else { @@ -6870,6 +6884,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) K_DoPogoSpring(mobj, 0, 1); } + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < 8*FRACUNIT) + { + // Not moving fast enough to water run. + mobj->flags2 &= ~MF2_WATERRUN; + } + if (mobj->threshold > 0) mobj->threshold--; @@ -7031,6 +7051,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags = (mobj->renderflags|RF_FULLBRIGHT) ^ RF_FULLDARK; // the difference between semi and fullbright + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < 8*FRACUNIT) + { + // Not moving fast enough to water run. + mobj->flags2 &= ~MF2_WATERRUN; + } + if (mobj->threshold > 0) mobj->threshold--; break; diff --git a/src/p_mobj.h b/src/p_mobj.h index e9389f98e..7244ce061 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -203,7 +203,7 @@ typedef enum MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) MF2_SPLAT = 1<<30, // Renders as a splat - // free: to and including 1<<31 + MF2_WATERRUN = 1<<31, // Mobj is able to run on Water! } mobjflag2_t; typedef enum diff --git a/src/p_saveg.c b/src/p_saveg.c index 8a0b4c1a0..86f2b8125 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -315,7 +315,6 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].sneakertimer); WRITEUINT8(save->p, players[i].floorboost); - WRITEUINT8(save->p, players[i].waterrun); WRITEUINT8(save->p, players[i].boostcharge); @@ -625,7 +624,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].sneakertimer = READUINT16(save->p); players[i].floorboost = READUINT8(save->p); - players[i].waterrun = READUINT8(save->p); players[i].boostcharge = READUINT8(save->p); diff --git a/src/p_user.c b/src/p_user.c index a0a6d5b31..c7d77af15 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2238,89 +2238,7 @@ void P_MovePlayer(player_t *player) && (player->speed > runspd) && player->mo->momz == 0 && player->carry != CR_SLIDING && !player->spectator) { - fixed_t playerTopSpeed = K_GetKartSpeed(player, false, false); - fixed_t trailScale = FixedMul(FixedDiv(player->speed - runspd, playerTopSpeed - runspd), mapobjectscale); - - if (playerTopSpeed > runspd) - trailScale = FixedMul(FixedDiv(player->speed - runspd, playerTopSpeed - runspd), mapobjectscale); - else - trailScale = mapobjectscale; // Scaling is based off difference between runspeed and top speed - - if (trailScale > 0) - { - const angle_t forwardangle = K_MomentumAngle(player->mo); - const fixed_t playerVisualRadius = player->mo->radius + (8 * player->mo->scale); - const SINT8 numFrames = 5; - const INT32 curFrame = (leveltime % numFrames)|FF_PAPERSPRITE; - fixed_t x1, x2, y1, y2; - mobj_t *water; - - x1 = player->mo->x + player->mo->momx + P_ReturnThrustX(player->mo, forwardangle + ANGLE_90, playerVisualRadius); - y1 = player->mo->y + player->mo->momy + P_ReturnThrustY(player->mo, forwardangle + ANGLE_90, playerVisualRadius); - x1 = x1 + P_ReturnThrustX(player->mo, forwardangle, playerVisualRadius); - y1 = y1 + P_ReturnThrustY(player->mo, forwardangle, playerVisualRadius); - - x2 = player->mo->x + player->mo->momx + P_ReturnThrustX(player->mo, forwardangle - ANGLE_90, playerVisualRadius); - y2 = player->mo->y + player->mo->momy + P_ReturnThrustY(player->mo, forwardangle - ANGLE_90, playerVisualRadius); - x2 = x2 + P_ReturnThrustX(player->mo, forwardangle, playerVisualRadius); - y2 = y2 + P_ReturnThrustY(player->mo, forwardangle, playerVisualRadius); - - // Left - // underlay - water = P_SpawnMobj(x1, y1, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; - water->destscale = trailScale; - water->momx = player->mo->momx; - water->momy = player->mo->momy; - water->momz = player->mo->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, S_WATERTRAILSUNDERLAY); - water->frame = curFrame|FF_ADD|FF_TRANS40; - - // overlay - water = P_SpawnMobj(x1, y1, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; - water->destscale = trailScale; - water->momx = player->mo->momx; - water->momy = player->mo->momy; - water->momz = player->mo->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, S_WATERTRAILS); - water->frame = curFrame; - - // Right - // Underlay - water = P_SpawnMobj(x2, y2, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; - water->destscale = trailScale; - water->momx = player->mo->momx; - water->momy = player->mo->momy; - water->momz = player->mo->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, S_WATERTRAILSUNDERLAY); - water->frame = curFrame|FF_ADD|FF_TRANS40; - - // Overlay - water = P_SpawnMobj(x2, y2, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; - water->destscale = trailScale; - water->momx = player->mo->momx; - water->momy = player->mo->momy; - water->momz = player->mo->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, S_WATERTRAILS); - water->frame = curFrame; - - if (!S_SoundPlaying(player->mo, sfx_s3kdbs)) - { - const INT32 volume = (min(trailScale, FRACUNIT) * 255) / FRACUNIT; - S_StartSoundAtVolume(player->mo, sfx_s3kdbs, volume); - } - } + K_SpawnWaterTrail(player->mo); } // Little water sound while touching water - just a nicety.