diff --git a/src/d_net.cpp b/src/d_net.cpp index 50d524cd2f..1532c0a35f 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2450,6 +2450,11 @@ void Net_DoCommand (int type, BYTE **stream, int player) } break; + case DEM_SETPITCHLIMIT: + players[player].MinPitch = ReadByte(stream) * -ANGLE_1; // up + players[player].MaxPitch = ReadByte(stream) * ANGLE_1; // down + break; + default: I_Error ("Unknown net command: %d", type); break; @@ -2570,6 +2575,9 @@ void Net_SkipCommand (int type, BYTE **stream) skip = 2 + ((*stream)[1] >> 7); break; + case DEM_SETPITCHLIMIT: + skip = 2; + break; default: return; diff --git a/src/d_player.h b/src/d_player.h index d3f2feb951..95604f0bde 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -282,6 +282,7 @@ public: bool centering; BYTE turnticks; + bool attackdown; bool usedown; DWORD oldbuttons; @@ -342,9 +343,9 @@ public: TObjPtr enemy; // The dead meat. - TObjPtr missile; // A threathing missile that got to be avoided. - TObjPtr mate; // Friend (used for grouping in templay or coop. - TObjPtr last_mate; // If bots mate dissapeared (not if died) that mate is + TObjPtr missile; // A threatening missile that needs to be avoided. + TObjPtr mate; // Friend (used for grouping in teamplay or coop). + TObjPtr last_mate; // If bots mate disappeared (not if died) that mate is // pointed to by this. Allows bot to roam to it if // necessary. @@ -380,6 +381,9 @@ public: FString LogText; // [RH] Log for Strife + int MinPitch; // Viewpitch limits (negative is up, positive is down) + int MaxPitch; + SBYTE crouching; SBYTE crouchdir; fixed_t crouchfactor; diff --git a/src/d_protocol.h b/src/d_protocol.h index b96c94e06c..f00526555b 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -159,6 +159,7 @@ enum EDemoCommand DEM_CONVCLOSE, // 60 DEM_CONVNULL, // 61 DEM_RUNSPECIAL, // 62 Byte: Special number, Byte: Arg count, Ints: Args + DEM_SETPITCHLIMIT, // 63 Byte: Up limit, Byte: Down limit (in degrees) }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1057726218..559b2e477a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2783,6 +2783,7 @@ void AActor::Tick () static const BYTE HereticScrollDirs[4] = { 6, 9, 1, 4 }; static const BYTE HereticSpeedMuls[5] = { 5, 10, 25, 30, 35 }; + AActor *onmo; int i; @@ -4027,6 +4028,7 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer) p->BlendR = p->BlendG = p->BlendB = p->BlendA = 0.f; p->mo->ResetAirSupply(false); p->Uncrouch(); + p->MinPitch = p->MaxPitch = 0; // will be filled in by PostBeginPlay()/netcode p->velx = p->vely = 0; // killough 10/98: initialize bobbing to 0. diff --git a/src/p_user.cpp b/src/p_user.cpp index 4c438b3dad..236f4d3198 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -522,6 +522,14 @@ void APlayerPawn::PostBeginPlay() P_FindFloorCeiling(this, true); z = floorz; } + else if (player - players == consoleplayer) + { + // Ask the local player's renderer what pitch restrictions + // should be imposed and let everybody know. + Net_WriteByte(DEM_SETPITCHLIMIT); + Net_WriteByte(Renderer->GetMaxViewPitch(false)); // up + Net_WriteByte(Renderer->GetMaxViewPitch(true)); // down + } } //=========================================================================== @@ -2213,11 +2221,11 @@ void P_PlayerThink (player_t *player) player->mo->pitch -= look; if (look > 0) { // look up - player->mo->pitch = MAX(player->mo->pitch, Renderer->GetMaxViewPitch(false)); + player->mo->pitch = MAX(player->mo->pitch, player->MinPitch); } else { // look down - player->mo->pitch = MIN(player->mo->pitch, Renderer->GetMaxViewPitch(true)); + player->mo->pitch = MIN(player->mo->pitch, player->MaxPitch); } } } diff --git a/src/r_renderer.h b/src/r_renderer.h index c9de1278ac..bc464c0311 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -49,7 +49,7 @@ struct FRenderer virtual void StartSerialize(FArchive &arc) {} virtual void EndSerialize(FArchive &arc) {} - virtual int GetMaxViewPitch(bool down) = 0; + virtual int GetMaxViewPitch(bool down) = 0; // return value is in plain degrees virtual void OnModeSet () {} virtual void ErrorCleanup () {} diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index c518abf909..56f816d6fc 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -173,7 +173,7 @@ void FSoftwareRenderer::DrawRemainingPlayerSprites() int FSoftwareRenderer::GetMaxViewPitch(bool down) { - return down? MAX_DN_ANGLE*ANGLE_1 : -MAX_UP_ANGLE*ANGLE_1; + return down ? MAX_DN_ANGLE : MAX_UP_ANGLE; } //========================================================================== diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 0f715e2bd9..858cbbba7b 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -601,11 +601,11 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi // Avoid overflowing viewpitch (can happen when a netgame is stalled) if (viewpitch + delta <= viewpitch) { - viewpitch = Renderer->GetMaxViewPitch(true); + viewpitch = player->MaxPitch; } else { - viewpitch = MIN(viewpitch + delta, Renderer->GetMaxViewPitch(true)); + viewpitch = MIN(viewpitch + delta, player->MaxPitch); } } else if (delta < 0) @@ -613,11 +613,11 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi // Avoid overflowing viewpitch (can happen when a netgame is stalled) if (viewpitch + delta >= viewpitch) { - viewpitch = Renderer->GetMaxViewPitch(false); + viewpitch = player->MinPitch; } else { - viewpitch = MAX(viewpitch + delta, Renderer->GetMaxViewPitch(false)); + viewpitch = MAX(viewpitch + delta, player->MinPitch); } } } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index c265107275..b801b3e4f2 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3416,10 +3416,34 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) // //=========================================================================== +enum +{ + SPF_FORCECLAMP = 1, // players always clamp +}; + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(pitch, 0); + ACTION_PARAM_INT(flags, 1); + + if (self->player != NULL || (flags & SPF_FORCECLAMP)) + { // clamp the pitch we set + int min, max; + + if (self->player != NULL) + { + min = self->player->MinPitch; + max = self->player->MaxPitch; + } + else + { + min = -ANGLE_90 + (1 << ANGLETOFINESHIFT); + max = ANGLE_90 - (1 << ANGLETOFINESHIFT); + } + pitch = clamp(pitch, min, max); + } + self->pitch = pitch; } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 29b265ac64..0d51bf4e80 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -278,7 +278,7 @@ ACTOR Actor native //: Thinker action native A_PigPain (); action native A_MonsterRefire(int chance, state label); action native A_SetAngle(float angle = 0); - action native A_SetPitch(float pitch); + action native A_SetPitch(float pitch, int flags = 0); action native A_ScaleVelocity(float scale); action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); action native A_SetArg(int pos, int value); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index fe84014e2c..42dca0e3e4 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -257,5 +257,8 @@ Const Int WARPF_STOP = 0x80; Const Int WARPF_TOFLOOR = 0x100; Const Int WARPF_TESTONLY = 0x200; +// flags for A_SetPitch +const int SPF_FORCECLAMP = 1; + // This is only here to provide one global variable for testing. native int testglobalvar;