1+ /*
2+ Copyright (C) 1997-2001 Id Software, Inc.
3+ Copyright (C) 2007 Chasseur de Bots
4+ Copyright (C) 2019 Victor Luchits
5+
6+ This program is free software; you can redistribute it and/or
7+ modify it under the terms of the GNU General Public License
8+ as published by the Free Software Foundation; either version 2
9+ of the License, or (at your option) any later version.
10+
11+ This program is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14+
15+ See the GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program; if not, write to the Free Software
19+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20+
21+ */
22+
23+ namespace PM {
24+
25+ Vec3 playerboxStandMins, playerboxStandMaxs;
26+ float playerboxStandViewheight ;
27+
28+ Vec3 playerboxCrouchMins, playerboxCrouchMaxs;
29+ float playerboxCrouchViewheight ;
30+
31+ Vec3 playerboxGibMins, playerboxGibMaxs;
32+ float playerboxGibViewheight ;
33+
34+ void Load() {
35+ GS :: GetPlayerStandSize( playerboxStandMins, playerboxStandMaxs );
36+ playerboxStandViewheight = GS :: GetPlayerStandViewHeight();
37+
38+ GS :: GetPlayerCrouchSize( playerboxCrouchMins, playerboxCrouchMaxs );
39+ playerboxCrouchViewheight = GS :: GetPlayerCrouchHeight();
40+
41+ GS :: GetPlayerGibSize( playerboxGibMins, playerboxGibMaxs );
42+ playerboxGibViewheight = GS :: GetPlayerGibHeight();
43+ }
44+
45+ void PMove( PMove @ pm , PlayerState @ ps , UserCmd cmd ) {
46+ PMoveLocal pml ;
47+ auto @ pmoveState = @ ps .pmove ;
48+ int pm_type = pmoveState.pm_type ;
49+
50+ if ( @ pm == null ) {
51+ // GS::Print( "PM::PMove: @pm == null\n" );
52+ return ;
53+ }
54+ if ( @ ps == null ) {
55+ // GS::Print( "PM::PMove: @ps == null\n" );
56+ return ;
57+ }
58+
59+ pml.BeginMove( pm, ps, cmd );
60+
61+ float fallvelocity = ( ( pml.velocity .z < 0.0f ) ? abs( pml.velocity.z ) : 0.0f );
62+
63+ pml.PostBeginMove();
64+
65+ if ( pm_type ! = PM_NORMAL ) { // includes dead, freeze, chasecam...
66+ if ( ( GS :: gameState.stats [GAMESTAT_FLAGS ] & GAMESTAT_FLAG_PAUSED ) == 0 ) {
67+ pml.ClearDash();
68+
69+ pml.ClearWallJump();
70+
71+ pml.ClearStun();
72+
73+ pmoveState.stats [PM_STAT_KNOCKBACK ] = 0 ;
74+ pmoveState.stats [PM_STAT_CROUCHTIME ] = 0 ;
75+ pmoveState.stats [PM_STAT_ZOOMTIME ] = 0 ;
76+ pmoveState.pm_flags = pmoveState.pm_flags & int ( ~ ( PMF_JUMPPAD_TIME | PMF_DOUBLEJUMPED | PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT | PMF_SPECIAL_HELD ) );
77+
78+ pml.AdjustBBox();
79+ }
80+
81+ pml.AdjustViewheight();
82+
83+ if ( pm_type == PM_SPECTATOR ) {
84+ pml.FlyMove( false );
85+ } else {
86+ pml.forwardPush = pml.sidePush = pml.upPush = 0.0f ;
87+ }
88+
89+ pml.EndMove();
90+ return ;
91+ }
92+
93+ // set mins, maxs, viewheight and fov
94+
95+ pml.AdjustBBox();
96+
97+ pml.CheckZoom();
98+
99+ pml.AdjustViewheight();
100+
101+ pml.CategorizePosition();
102+
103+ int oldGroundEntity = pm.groundEntity ;
104+
105+ pml.CheckSpecialMovement();
106+
107+ if ( ( pmoveState.pm_flags & PMF_TIME_TELEPORT ) ! = 0 ) {
108+ // teleport pause stays exactly in place
109+ } else if ( ( pmoveState.pm_flags & PMF_TIME_WATERJUMP ) ! = 0 ) {
110+ // waterjump has no control, but falls
111+
112+ pml.velocity.z - = pmoveState.gravity * pml.frametime ;
113+ if ( pml.velocity .z < 0 ) {
114+ // cancel as soon as we are falling down again
115+ pmoveState.pm_flags = pmoveState.pm_flags & int ( ~ ( PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT ) );
116+ pmoveState.pm_time = 0 ;
117+ }
118+
119+ pml.StepSlideMove();
120+ } else {
121+ // Kurim
122+ // Keep this order !
123+ pml.CheckJump();
124+
125+ pml.CheckDash();
126+
127+ pml.CheckWallJump();
128+
129+ pml.CheckCrouchSlide();
130+
131+ pml.Friction();
132+
133+ if ( pm.waterLevel > = 2 ) {
134+ pml.WaterMove();
135+ } else {
136+ Vec3 angles = ps.viewAngles ;
137+
138+ if ( angles[PITCH ] > 180.0f ) {
139+ angles[PITCH ] = angles[PITCH ] - 360.0f ;
140+ }
141+ angles[PITCH ] / = 3.0f ;
142+
143+ angles.angleVectors( pml.forward , pml.right , pml.up );
144+
145+ // hack to work when looking straight up and straight down
146+ if ( pml.forward.z == - 1.0f ) {
147+ pml.flatforward = pml.up ;
148+ } else if ( pml.forward.z == 1.0f ) {
149+ pml.flatforward = pml.up * - 1.0f ;
150+ } else {
151+ pml.flatforward = pml.forward ;
152+ }
153+ pml.flatforward.z = 0.0f ;
154+ pml.flatforward .normalize();
155+
156+ pml.Move();
157+ }
158+ }
159+
160+ // set groundentity, watertype, and waterlevel for final spot
161+ pml.CategorizePosition();
162+
163+ pml.EndMove();
164+
165+ // falling event
166+
167+ // Execute the triggers that are touched.
168+ // We check the entire path between the origin before the pmove and the
169+ // current origin to ensure no triggers are missed at high velocity.
170+ // Note that this method assumes the movement has been linear.
171+ pm.touchTriggers( ps, pml.previousOrigin );
172+
173+ // touching triggers may force groundentity off
174+ if ( ( ( pmoveState.pm_flags & PMF_ON_GROUND ) == 0 ) && ( pm.groundEntity ! = - 1 ) ) {
175+ pm.groundEntity = - 1 ;
176+ pml.velocity.z = 0 ;
177+ }
178+
179+ if ( pm.groundEntity ! = - 1 ) { // remove wall-jump and dash bits when touching ground
180+ // always keep the dash flag 50 msecs at least (to prevent being removed at the start of the dash)
181+ if ( pmoveState.stats [PM_STAT_DASHTIME ] < ( PM_DASHJUMP_TIMEDELAY - 50 ) ) {
182+ pmoveState.pm_flags = pmoveState.pm_flags & ~ PMF_DASHING ;
183+ }
184+
185+ if ( pmoveState.stats [PM_STAT_WJTIME ] < ( PM_WALLJUMP_TIMEDELAY - 50 ) ) {
186+ pml.ClearWallJump();
187+ }
188+ }
189+
190+ if ( oldGroundEntity == - 1 ) {
191+ float damage ;
192+ float falldelta = fallvelocity - ( ( pml.velocity .z < 0.0f ) ? abs( pml.velocity.z ) : 0.0f );
193+
194+ // scale delta if in water
195+ if ( pm.waterLevel == 3 ) {
196+ falldelta = 0 ;
197+ }
198+ if ( pm.waterLevel == 2 ) {
199+ falldelta *= 0.25 ;
200+ }
201+ if ( pm.waterLevel == 1 ) {
202+ falldelta *= 0.5 ;
203+ }
204+
205+ if ( falldelta > FALL_STEP_MIN_DELTA ) {
206+ if ( ( GS :: gameState.stats [GAMESTAT_FLAGS ] & GAMESTAT_FLAG_FALLDAMAGE ) == 0 ||
207+ ( pml.groundSurfFlags & SURF_NODAMAGE ) ! = 0 ||
208+ ( pmoveState.pm_flags & PMF_JUMPPAD_TIME ) ! = 0 ) {
209+ damage = 0.0f ;
210+ } else {
211+ damage = ( ( falldelta - FALL_DAMAGE_MIN_DELTA ) / 10 ) * FALL_DAMAGE_SCALE ;
212+ }
213+
214+ int damageParam = int ( damage );
215+ if ( damage < 0 ) {
216+ damage = 0 ;
217+ } else if ( damage > MAX_FALLING_DAMAGE ) {
218+ damage = MAX_FALLING_DAMAGE ;
219+ }
220+
221+ GS :: PredictedEvent( ps.POVnum , EV_FALL , damageParam );
222+ }
223+
224+ pmoveState.pm_flags = pmoveState.pm_flags & int ( ~ PMF_JUMPPAD_TIME );
225+ }
226+ }
227+
228+ }
0 commit comments