File: | game/g_move.cpp |
Location: | line 312, column 5 |
Description: | Value stored to 'length' is never read |
1 | /** |
2 | * @file |
3 | */ |
4 | |
5 | /* |
6 | Copyright (C) 2002-2011 UFO: Alien Invasion. |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
16 | |
17 | See the GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with this program; if not, write to the Free Software |
21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 | |
23 | */ |
24 | |
25 | #include "g_local.h" |
26 | |
27 | #define ACTOR_SPEED_NORMAL100 100 |
28 | #define ACTOR_SPEED_CROUCHED(100 / 2) (ACTOR_SPEED_NORMAL100 / 2) |
29 | static const float FALLING_DAMAGE_FACTOR = 10.0f; |
30 | |
31 | /** |
32 | * @brief The forbidden list is a list of entity positions that are occupied by an entity. |
33 | * This list is checked everytime an actor wants to walk there. |
34 | */ |
35 | static pos_t *forbiddenList[MAX_FORBIDDENLIST(1024 * 4)]; |
36 | static int forbiddenListLength; |
37 | |
38 | /** |
39 | * @brief Build the forbidden list for the pathfinding (server side). |
40 | * @param[in] team The team number if the list should be calculated from the eyes of that team. Use 0 to ignore team. |
41 | * @param[in] movingActor The moving actor to build the forbidden list for. If this is an AI actor, everything other actor will be |
42 | * included in the forbidden list - even the invisible ones. This is needed to ensure that they are not walking into each other |
43 | * (civilians <=> aliens, aliens <=> civilians) |
44 | * @sa G_MoveCalc |
45 | * @sa Grid_CheckForbidden |
46 | * @sa CL_BuildForbiddenList <- shares quite some code |
47 | * @note This is used for pathfinding. |
48 | * It is a list of where the selected unit can not move to because others are standing there already. |
49 | */ |
50 | static void G_BuildForbiddenList (int team, const edict_t *movingActor) |
51 | { |
52 | edict_t *ent = NULL__null; |
53 | int visMask; |
54 | |
55 | forbiddenListLength = 0; |
56 | |
57 | /* team visibility */ |
58 | if (team) |
59 | visMask = G_TeamToVisMask(team)(1 << (team)); |
60 | else |
61 | visMask = TEAM_ALL0xFFFFFFFF; |
62 | |
63 | while ((ent = G_EdictsGetNextInUse(ent))) { |
64 | /* Dead 2x2 unit will stop walking, too. */ |
65 | if (G_IsBlockingMovementActor(ent)(((ent)->type == ET_ACTOR && !((ent)->state & (0x0003))) || ent->type == ET_ACTOR2x2) && (G_IsAI(movingActor)((game.players + ((movingActor))->pnum)->pers.ai) || (ent->visflags & visMask))) { |
66 | forbiddenList[forbiddenListLength++] = ent->pos; |
67 | forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize; |
68 | } else if (ent->type == ET_SOLID) { |
69 | int j; |
70 | for (j = 0; j < ent->forbiddenListSize; j++) { |
71 | forbiddenList[forbiddenListLength++] = ent->forbiddenListPos[j]; |
72 | forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize; |
73 | } |
74 | } |
75 | } |
76 | |
77 | if (forbiddenListLength > MAX_FORBIDDENLIST(1024 * 4)) |
78 | gi.Error("G_BuildForbiddenList: list too long\n"); |
79 | } |
80 | |
81 | /** |
82 | * @brief Precalculates a move table for a given team and a given starting position. |
83 | * This will calculate a routing table for all reachable fields with the given distance |
84 | * from the given spot with the given actorsize |
85 | * @param[in] team The current team (see G_BuildForbiddenList) |
86 | * @param[in] from Position in the map to start the move-calculation from. |
87 | * @param[in] crouchingState The crouching state of the actor. 0=stand, 1=crouch |
88 | * @param[in] distance The distance in TUs to calculate the move for. |
89 | * @param[in] movingActor The actor to calculate the move for |
90 | * @sa G_BuildForbiddenList |
91 | * @sa G_MoveCalcLocal |
92 | */ |
93 | void G_MoveCalc (int team, const edict_t *movingActor, const pos3_t from, byte crouchingState, int distance) |
94 | { |
95 | G_MoveCalcLocal(level.pathingMap, team, movingActor, from, crouchingState, distance); |
96 | } |
97 | |
98 | /** |
99 | * @brief Same as @c G_MoveCalc, except that it uses the pathing table passed as the first param |
100 | * @param[in] pt the pathfinding table |
101 | * @param[in] team The current team (see G_BuildForbiddenList) |
102 | * @param[in] from Position in the map to start the move-calculation from. |
103 | * @param[in] crouchingState The crouching state of the actor. 0=stand, 1=crouch |
104 | * @param[in] distance The distance in TUs to calculate the move for. |
105 | * @param[in] movingActor The actor to calculate the move for |
106 | * @sa G_MoveCalc |
107 | * @sa G_BuildForbiddenList |
108 | */ |
109 | void G_MoveCalcLocal (pathing_t *pt, int team, const edict_t *movingActor, const pos3_t from, byte crouchingState, int distance) |
110 | { |
111 | G_BuildForbiddenList(team, movingActor); |
112 | gi.MoveCalc(gi.routingMap, movingActor->fieldSize, pt, from, crouchingState, distance, |
113 | forbiddenList, forbiddenListLength); |
114 | } |
115 | |
116 | /** |
117 | * @brief Let an actor fall down if e.g. the func_breakable the actor was standing on was destroyed. |
118 | * @param[in,out] ent The actor that should fall down |
119 | * @todo Handle cases where the grid position the actor would fall to is occupied by another actor already. |
120 | */ |
121 | void G_ActorFall (edict_t *ent) |
122 | { |
123 | edict_t* entAtPos; |
124 | const int oldZ = ent->pos[2]; |
125 | |
126 | ent->pos[2] = gi.GridFall(gi.routingMap, ent->fieldSize, ent->pos); |
127 | |
128 | if (oldZ == ent->pos[2]) |
129 | return; |
130 | |
131 | entAtPos = G_GetEdictFromPos(ent->pos, ET_NULL); |
132 | if (entAtPos != NULL__null && (G_IsBreakable(entAtPos)((entAtPos)->flags & 0x00000004) || G_IsBlockingMovementActor(entAtPos)(((entAtPos)->type == ET_ACTOR && !((entAtPos)-> state & (0x0003))) || entAtPos->type == ET_ACTOR2x2))) { |
133 | const int diff = oldZ - ent->pos[2]; |
134 | G_TakeDamage(entAtPos, (int)(FALLING_DAMAGE_FACTOR * (float)diff)); |
135 | } |
136 | |
137 | G_EdictCalcOrigin(ent); |
138 | gi.LinkEdict(ent); |
139 | |
140 | G_CheckVis(ent, true); |
141 | |
142 | G_EventActorFall(ent); |
143 | |
144 | gi.EndEvents(); |
145 | } |
146 | |
147 | /** |
148 | * @brief Checks whether the actor should stop movement |
149 | * @param ent The actors edict |
150 | * @param visState The visibility check state @c VIS_PERISH, @c VIS_APPEAR |
151 | * @return @c true if the actor should stop movement, @c false otherwise |
152 | */ |
153 | static bool G_ActorShouldStopInMidMove (const edict_t *ent, int visState, dvec_t* dvtab, int max) |
154 | { |
155 | if (visState & VIS_STOP4) |
156 | return true; |
157 | |
158 | /* check that the appearing unit is not on a grid position the actor wanted to walk to. |
159 | * this might be the case if the edict got visible in mid mode */ |
160 | if (visState & VIS_APPEAR1) { |
161 | pos3_t pos; |
162 | VectorCopy(ent->pos, pos)((pos)[0]=(ent->pos)[0],(pos)[1]=(ent->pos)[1],(pos)[2] =(ent->pos)[2]); |
163 | while (max >= 0) { |
164 | int tmp = 0; |
165 | const edict_t *blockEdict; |
166 | |
167 | PosAddDV(pos, tmp, dvtab[max])((pos)[0]+=dvecs[((dvtab[max]) >> 8)][0], (pos)[1]+=dvecs [((dvtab[max]) >> 8)][1], (pos)[2]=((dvtab[max]) & 0x0007 ), (tmp)+=dvecs[((dvtab[max]) >> 8)][3]); |
168 | max--; |
169 | blockEdict = G_GetLivingActorFromPos(pos); |
170 | |
171 | if (blockEdict && G_IsBlockingMovementActor(blockEdict)(((blockEdict)->type == ET_ACTOR && !((blockEdict) ->state & (0x0003))) || blockEdict->type == ET_ACTOR2x2 )) { |
172 | const bool visible = G_IsVisibleForTeam(blockEdict, ent->team)((blockEdict)->visflags & (1 << (ent->team))); |
173 | if (visible) |
174 | return true; |
175 | } |
176 | } |
177 | } |
178 | return false; |
179 | } |
180 | |
181 | /** |
182 | * @brief Writes a step of the move event to the net |
183 | * @param[in] ent Edict to move |
184 | * @param[in] stepAmount Pointer to the amount of steps in this move-event |
185 | * @param[in] dvec The direction vector for the step to be added |
186 | * @param[in] contentFlags The material we are walking over |
187 | */ |
188 | static void G_WriteStep (edict_t* ent, byte** stepAmount, const int dvec, const int contentFlags) |
189 | { |
190 | /* write move header if not yet done */ |
191 | if (gi.GetEvent() != EV_ACTOR_MOVE) { |
192 | gi.AddEvent(G_VisToPM(ent->visflags), EV_ACTOR_MOVE); |
193 | gi.WriteShort(ent->number); |
194 | /* stepAmount is a pointer to a location in the netchannel |
195 | * the value of this pointer depends on how far the actor walks |
196 | * and this might be influenced at a later stage inside this |
197 | * loop. That's why we can modify the value of this byte |
198 | * if e.g. a VIS_STOP occurred and no more steps should be made. |
199 | * But keep in mind, that no other events might be between |
200 | * this event and its successful end - otherwise the |
201 | * stepAmount pointer would no longer be valid and you would |
202 | * modify data in the new event. */ |
203 | *stepAmount = gi.WriteDummyByte(0); |
204 | /* Add three more dummy bytes. These will be the final actor position. */ |
205 | gi.WriteDummyByte(0); /* x */ |
206 | gi.WriteDummyByte(0); /* y */ |
207 | gi.WriteDummyByte(0); /* z */ |
208 | } else if (!*stepAmount) { |
209 | gi.DPrintf("Event %i activate and no stepAmount pointer set\n", gi.GetEvent()); |
210 | return; |
211 | } |
212 | |
213 | /* the moveinfo stuff is used inside the G_PhysicsStep think function */ |
214 | if (ent->moveinfo.steps >= MAX_DVTAB32) { |
215 | ent->moveinfo.steps = 0; |
216 | ent->moveinfo.currentStep = 0; |
217 | } |
218 | ent->moveinfo.contentFlags[ent->moveinfo.steps] = contentFlags; |
219 | ent->moveinfo.visflags[ent->moveinfo.steps] = ent->visflags; |
220 | ent->moveinfo.steps++; |
221 | |
222 | /* store steps in netchannel */ |
223 | byte *pStep = *stepAmount; |
224 | (*pStep)++; |
225 | /* store the position too */ |
226 | *(pStep + 1) = ent->pos[0]; |
227 | *(pStep + 2) = ent->pos[1]; |
228 | *(pStep + 3) = ent->pos[2]; |
229 | |
230 | /* write move header and always one step after another - because the next step |
231 | * might already be the last one due to some stop event */ |
232 | gi.WriteShort(dvec); |
233 | gi.WriteShort(ent->speed); |
234 | gi.WriteShort(contentFlags); |
235 | } |
236 | |
237 | static int G_FillDirectionTable (dvec_t *dvtab, size_t size, byte crouchingState, pos3_t pos) |
238 | { |
239 | int dvec; |
240 | int numdv = 0; |
241 | while ((dvec = gi.MoveNext(level.pathingMap, pos, crouchingState)) |
242 | != ROUTING_UNREACHABLE-1) { |
243 | const int oldZ = pos[2]; |
244 | /* dvec indicates the direction traveled to get to the new cell and the original cell height. */ |
245 | /* We are going backwards to the origin. */ |
246 | PosSubDV(pos, crouchingState, dvec)((pos)[0]-=dvecs[((dvec) >> 8)][0], (pos)[1]-=dvecs[((dvec ) >> 8)][1], (pos)[2]=((dvec) & 0x0007), (crouchingState )-=dvecs[((dvec) >> 8)][3]); |
247 | /* Replace the z portion of the DV value so we can get back to where we were. */ |
248 | dvtab[numdv++] = setDVz(dvec, oldZ)(((dvec) & (~0x0007)) | ((oldZ) & 0x0007)); |
249 | if (numdv >= size) |
250 | break; |
251 | } |
252 | |
253 | return numdv; |
254 | } |
255 | |
256 | /** |
257 | * @brief Generates the client events that are send over the netchannel to move an actor |
258 | * @param[in] player Player who is moving an actor |
259 | * @param[in] visTeam The team to check the visibility for - if this is 0 we build the forbidden list |
260 | * above all edicts - for the human controlled actors this would mean that clicking to a grid |
261 | * position that is not reachable because an invisible actor is standing there would not result in |
262 | * a single step - as the movement is aborted before. For AI movement this is in general @c 0 - but |
263 | * not if they e.g. hide. |
264 | * @param[in] ent Edict to move |
265 | * @param[in] to The grid position to walk to |
266 | * @sa CL_ActorStartMove |
267 | * @sa PA_MOVE |
268 | */ |
269 | void G_ClientMove (const player_t * player, int visTeam, edict_t* ent, const pos3_t to) |
270 | { |
271 | int status, initTU; |
272 | dvec_t dvtab[MAX_DVTAB32]; |
273 | int dir; |
274 | byte numdv, length; |
275 | pos3_t pos; |
276 | float div; |
277 | int oldState; |
278 | int oldHP; |
279 | bool autoCrouchRequired = false; |
280 | byte crouchingState; |
281 | |
282 | if (VectorCompare(ent->pos, to)((ent->pos)[0]==(to)[0]?(ent->pos)[1]==(to)[1]?(ent-> pos)[2]==(to)[2]?1:0:0:0)) |
283 | return; |
284 | |
285 | /* check if action is possible */ |
286 | if (!G_ActionCheckForCurrentTeam(player, ent, TU_MOVE_STRAIGHT2)) |
287 | return; |
288 | |
289 | crouchingState = G_IsCrouched(ent)((ent)->state & (0x0004)) ? 1 : 0; |
290 | oldState = oldHP = 0; |
291 | |
292 | /* calculate move table */ |
293 | G_MoveCalc(visTeam, ent, ent->pos, crouchingState, ent->TU); |
294 | length = gi.MoveLength(level.pathingMap, to, crouchingState, false); |
295 | |
296 | /* length of ROUTING_NOT_REACHABLE means not reachable */ |
297 | if (length && length >= ROUTING_NOT_REACHABLE0xFF) |
298 | return; |
299 | |
300 | /* Autostand: check if the actor is crouched and player wants autostanding...*/ |
301 | if (crouchingState && player->autostand) { |
302 | /* ...and if this is a long walk... */ |
303 | if (SHOULD_USE_AUTOSTAND(length)((float) (2.0f * 3) * 1.5 / (1.5 - 1.0f) < (float) (length ))) { |
304 | /* ...make them stand first. If the player really wants them to walk a long |
305 | * way crouched, he can move the actor in several stages. |
306 | * Uses the threshold at which standing, moving and crouching again takes |
307 | * fewer TU than just crawling while crouched. */ |
308 | G_ClientStateChange(player, ent, STATE_CROUCHED0x0004, true); /* change to stand state */ |
309 | crouchingState = G_IsCrouched(ent)((ent)->state & (0x0004)) ? 1 : 0; |
310 | if (!crouchingState) { |
311 | G_MoveCalc(visTeam, ent, ent->pos, crouchingState, ent->TU); |
312 | length = gi.MoveLength(level.pathingMap, to, crouchingState, false); |
Value stored to 'length' is never read | |
313 | autoCrouchRequired = true; |
314 | } |
315 | } |
316 | } |
317 | |
318 | /* this let the footstep sounds play even over network */ |
319 | ent->think = G_PhysicsStep; |
320 | ent->nextthink = level.time; |
321 | |
322 | /* assemble dvec-encoded move data */ |
323 | VectorCopy(to, pos)((pos)[0]=(to)[0],(pos)[1]=(to)[1],(pos)[2]=(to)[2]); |
324 | initTU = ent->TU; |
325 | |
326 | numdv = G_FillDirectionTable(dvtab, lengthof(dvtab)(sizeof(dvtab) / sizeof(*(dvtab))), crouchingState, pos); |
327 | |
328 | /* make sure to end any other pending events - we rely on EV_ACTOR_MOVE not being active anymore */ |
329 | gi.EndEvents(); |
330 | |
331 | /* everything ok, found valid route? */ |
332 | if (VectorCompare(pos, ent->pos)((pos)[0]==(ent->pos)[0]?(pos)[1]==(ent->pos)[1]?(pos)[ 2]==(ent->pos)[2]?1:0:0:0)) { |
333 | byte* stepAmount = NULL__null; |
334 | int usedTUs = 0; |
335 | /* no floor inventory at this point */ |
336 | FLOOR(ent)(((ent)->chr.i.c[(gi.csi->idFloor)])) = NULL__null; |
337 | |
338 | while (numdv > 0) { |
339 | /* A flag to see if we needed to change crouch state */ |
340 | int crouchFlag; |
341 | const byte oldDir = ent->dir; |
342 | int dvec; |
343 | |
344 | /* get next dvec */ |
345 | numdv--; |
346 | dvec = dvtab[numdv]; |
347 | /* This is the direction to make the step into */ |
348 | dir = getDVdir(dvec)((dvec) >> 8); |
349 | |
350 | /* turn around first */ |
351 | status = G_ActorDoTurn(ent, dir); |
352 | if (status & VIS_STOP4) { |
353 | autoCrouchRequired = false; |
354 | if (ent->moveinfo.steps == 0) |
355 | usedTUs += TU_TURN1; |
356 | break; |
357 | } |
358 | |
359 | if (G_ActorShouldStopInMidMove(ent, status, dvtab, numdv)) { |
360 | /* don't autocrouch if new enemy becomes visible */ |
361 | autoCrouchRequired = false; |
362 | /* if something appears on our route that didn't trigger a VIS_STOP, we have to |
363 | * send the turn event if this is our first step */ |
364 | if (oldDir != ent->dir && ent->moveinfo.steps == 0) { |
365 | G_EventActorTurn(ent); |
366 | usedTUs += TU_TURN1; |
367 | } |
368 | break; |
369 | } |
370 | |
371 | /* decrease TUs */ |
372 | div = gi.GetTUsForDirection(dir, G_IsCrouched(ent)((ent)->state & (0x0004))); |
373 | if ((int) (usedTUs + div) > ent->TU) |
374 | break; |
375 | usedTUs += div; |
376 | |
377 | /* This is now a flag to indicate a change in crouching - we need this for |
378 | * the stop in mid move call(s), because we need the updated entity position */ |
379 | crouchFlag = 0; |
380 | /* Calculate the new position after the decrease in TUs, otherwise the game |
381 | * remembers the false position if the time runs out */ |
382 | PosAddDV(ent->pos, crouchFlag, dvec)((ent->pos)[0]+=dvecs[((dvec) >> 8)][0], (ent->pos )[1]+=dvecs[((dvec) >> 8)][1], (ent->pos)[2]=((dvec) & 0x0007), (crouchFlag)+=dvecs[((dvec) >> 8)][3]); |
383 | |
384 | /* slower if crouched */ |
385 | if (G_IsCrouched(ent)((ent)->state & (0x0004))) |
386 | ent->speed = ACTOR_SPEED_CROUCHED(100 / 2); |
387 | else |
388 | ent->speed = ACTOR_SPEED_NORMAL100; |
389 | ent->speed *= g_actorspeed->value; |
390 | |
391 | if (crouchFlag == 0) { /* No change in crouch */ |
392 | edict_t* clientAction; |
393 | int contentFlags; |
394 | vec3_t pointTrace; |
395 | |
396 | G_EdictCalcOrigin(ent); |
397 | VectorCopy(ent->origin, pointTrace)((pointTrace)[0]=(ent->origin)[0],(pointTrace)[1]=(ent-> origin)[1],(pointTrace)[2]=(ent->origin)[2]); |
398 | pointTrace[2] += PLAYER_MIN-24; |
399 | |
400 | contentFlags = gi.PointContents(pointTrace); |
401 | |
402 | /* link it at new position - this must be done for every edict |
403 | * movement - to let the server know about it. */ |
404 | gi.LinkEdict(ent); |
405 | |
406 | /* Only the PHALANX team has these stats right now. */ |
407 | if (ent->chr.scoreMission) { |
408 | float truediv = gi.GetTUsForDirection(dir, 0); /* regardless of crouching ! */ |
409 | if (G_IsCrouched(ent)((ent)->state & (0x0004))) |
410 | ent->chr.scoreMission->movedCrouched += truediv; |
411 | else |
412 | ent->chr.scoreMission->movedNormal += truediv; |
413 | } |
414 | /* write the step to the net */ |
415 | G_WriteStep(ent, &stepAmount, dvec, contentFlags); |
416 | |
417 | /* check if player appears/perishes, seen from other teams */ |
418 | G_CheckVis(ent, true); |
419 | |
420 | /* check for anything appearing, seen by "the moving one" */ |
421 | status = G_CheckVisTeamAll(ent->team, false, ent); |
422 | |
423 | /* Set ent->TU because the reaction code relies on ent->TU being accurate. */ |
424 | G_ActorSetTU(ent, initTU - usedTUs); |
425 | |
426 | clientAction = ent->clientAction; |
427 | oldState = ent->state; |
428 | oldHP = ent->HP; |
429 | /* check triggers at new position */ |
430 | if (G_TouchTriggers(ent)) { |
431 | if (!clientAction) |
432 | status |= VIS_STOP4; |
433 | } |
434 | |
435 | G_TouchSolids(ent, 10.0f); |
436 | |
437 | /* state has changed - maybe we walked on a trigger_hurt */ |
438 | if (oldState != ent->state) |
439 | status |= VIS_STOP4; |
440 | else if (oldHP != ent->HP) |
441 | status |= VIS_STOP4; |
442 | } else if (crouchFlag == 1) { |
443 | /* Actor is standing */ |
444 | G_ClientStateChange(player, ent, STATE_CROUCHED0x0004, true); |
445 | } else if (crouchFlag == -1) { |
446 | /* Actor is crouching and should stand up */ |
447 | G_ClientStateChange(player, ent, STATE_CROUCHED0x0004, false); |
448 | } |
449 | |
450 | /* check for reaction fire */ |
451 | if (G_ReactionFireOnMovement(ent)) { |
452 | status |= VIS_STOP4; |
453 | |
454 | autoCrouchRequired = false; |
455 | } |
456 | |
457 | /* check for death */ |
458 | if (((oldHP != 0 && oldHP != ent->HP) || (oldState != ent->state)) && !G_IsDazed(ent)((ent)->state & (0x0080))) { |
459 | /** @todo Handle dazed via trigger_hurt */ |
460 | /* maybe this was due to rf - then the G_ActorDie was already called */ |
461 | if (!G_IsDead(ent)((ent)->state & (0x0003))) { |
462 | G_CheckDeathOrKnockout(ent, NULL__null, NULL__null, oldHP - ent->HP); |
463 | } |
464 | return; |
465 | } |
466 | |
467 | if (G_ActorShouldStopInMidMove(ent, status, dvtab, numdv - 1)) { |
468 | /* don't autocrouch if new enemy becomes visible */ |
469 | autoCrouchRequired = false; |
470 | break; |
471 | } |
472 | |
473 | /* Restore ent->TU because the movement code relies on it not being modified! */ |
474 | G_ActorSetTU(ent, initTU); |
475 | } |
476 | |
477 | /* submit the TUs / round down */ |
478 | if (g_notu != NULL__null && g_notu->integer) |
479 | G_ActorSetTU(ent, initTU); |
480 | else |
481 | G_ActorSetTU(ent, initTU - usedTUs); |
482 | |
483 | G_SendStats(ent); |
484 | |
485 | /* end the move */ |
486 | G_GetFloorItems(ent); |
487 | gi.EndEvents(); |
488 | } |
489 | |
490 | if (autoCrouchRequired) { |
491 | /* toggle back to crouched state */ |
492 | G_ClientStateChange(player, ent, STATE_CROUCHED0x0004, true); |
493 | } |
494 | } |