UFO: Alien Invasion
e_event_actormove.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2022 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 "../../../../client.h"
26 #include "../../../cl_localentity.h"
27 #include "e_event_actormove.h"
28 
33 int CL_ActorDoMoveTime (const eventRegister_t* self, dbuffer* msg, eventTiming_t* eventTiming)
34 {
35  int time = 0;
36 
37  const int eventTime = eventTiming->nextTime;
38  const int number = NET_ReadShort(msg);
39  /* get le */
40  le_t* le = LE_Get(number);
41  if (!le)
42  LE_NotFoundError(number);
43 
44  pos3_t pos;
45  VectorCopy(le->pos, pos);
46  byte crouchingState = LE_IsCrouched(le) ? 1 : 0;
47 
48  leStep_t* newStep = Mem_AllocType(leStep_t);
49  if (le->stepList == nullptr) {
50  le->stepList = newStep;
51  le->stepIndex = 0;
52  } else {
53  /* append to the list */
54  leStep_t* step = le->stepList;
55  while (step) {
56  if (step->next == nullptr) {
57  step->next = newStep;
58  le->stepIndex++;
59  break;
60  }
61  step = step->next;
62  }
63  }
64 
65  /* the end of this event is marked with a 0 */
66  while (NET_PeekLong(msg) != 0) {
67  newStep->steps = NET_ReadByte(msg);
68  if (newStep->steps >= MAX_ROUTE || newStep->steps < 0)
69  Com_Error(ERR_DROP, "CL_ActorDoMoveTime: Invalid step number: %i", newStep->steps);
70  const dvec_t dvec = NET_ReadShort(msg);
71  const byte dir = getDVdir(dvec);
72  pos3_t oldPos;
73  VectorCopy(pos, oldPos);
74  PosAddDV(pos, crouchingState, dvec);
75  const int stepTime = LE_ActorGetStepTime(le, pos, oldPos, dir, NET_ReadShort(msg));
76  newStep->stepTimes[newStep->steps] = stepTime;
77  time += stepTime;
78  NET_ReadShort(msg);
79  }
80 
81  /* skip the end of move marker */
82  NET_ReadLong(msg);
83 
84  /* Also skip the final position */
85  NET_ReadByte(msg);
86  NET_ReadByte(msg);
87  NET_ReadByte(msg);
88 
89  assert(NET_PeekByte(msg) == EV_NULL);
90 
91  eventTiming->nextTime += time + 400;
92  newStep->lastMoveTime = eventTime;
93  newStep->lastMoveDuration = time;
94  return eventTime;
95 }
96 
104 void CL_ActorDoMove (const eventRegister_t* self, dbuffer* msg)
105 {
106  const int number = NET_ReadShort(msg);
107 
108  /* get le */
109  le_t* le = LE_Get(number);
110  if (!le)
111  LE_NotFoundError(number);
112 
113  if (!LE_IsActor(le))
114  Com_Error(ERR_DROP, "Can't move, LE doesn't exist or is not an actor (entnum: %i, type: %i)\n",
115  number, le->type);
116 
117  /* lock this le for other events, the corresponding unlock is in LE_DoEndPathMove() */
118  LE_Lock(le);
119  if (le->isMoving()) {
120  if (le->pathLength == le->pathPos) {
121  LE_DoEndPathMove(le);
122  } else {
123  Com_Error(ERR_DROP, "Actor (entnum: %i) on team %i is still moving (%i steps left). Times: %i, %i, %i",
124  le->entnum, le->team, le->pathLength - le->pathPos, le->startTime, le->endTime, cl.time);
125  }
126  }
127 
128  int i = 0;
129  /* the end of this event is marked with a 0 */
130  while (NET_PeekLong(msg) != 0) {
131  NET_ReadByte(msg);
132  le->dvtab[i] = NET_ReadShort(msg);
133  if (getDVdir(le->dvtab[i]) != DIRECTION_FALL && LE_IsDead(le))
134  Com_Error(ERR_DROP, "Can't move, actor on team %i dead (entnum: %i)", le->team, number);
135  le->speed[i] = NET_ReadShort(msg);
136  le->pathContents[i] = NET_ReadShort(msg);
137  i++;
138  }
139  le->pathLength = i;
140 
141  if (le->pathLength > MAX_ROUTE)
142  Com_Error(ERR_DROP, "Overflow in pathLength (entnum: %i)", number);
143 
144  /* skip the end of move marker */
145  NET_ReadLong(msg);
146  /* Also get the final position */
147  NET_ReadGPos(msg, le->newPos);
148 
149  if (VectorCompare(le->newPos, le->pos))
150  Com_Error(ERR_DROP, "start and end pos are the same (entnum: %i)", number);
151 
152  /* activate PathMove function */
153  le->resetFloor();
154  if (LE_IsInvisible(le))
155  /* Hack: this relies on the visibility events interrupting the EV_ACTOR_MOVE event */
157  else
159  le->pathPos = 0;
160  le->startTime = cl.time;
161  le->endTime = cl.time;
162 }
int pathContents[MAX_ROUTE]
void NET_ReadGPos(dbuffer *buf, pos3_t pos)
Definition: netpack.cpp:376
#define VectorCopy(src, dest)
Definition: vector.h:51
int pathLength
#define LE_IsCrouched(le)
int lastMoveTime
void CL_ActorDoMove(const eventRegister_t *self, dbuffer *msg)
Moves actor.
int lastMoveDuration
CL_ParseEvent timers and vars.
Definition: e_main.h:30
struct leStep_s * next
#define LE_IsInvisible(le)
static int oldPos
int NET_ReadLong(dbuffer *buf)
Definition: netpack.cpp:282
bool LE_IsActor(const le_t *le)
Checks whether the given le is a living actor.
int entnum
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
int LE_ActorGetStepTime(const le_t *le, const pos3_t pos, const pos3_t oldPos, const int dir, const int speed)
int CL_ActorDoMoveTime(const eventRegister_t *self, dbuffer *msg, eventTiming_t *eventTiming)
Decides if following events should be delayed. The delay is the amount of time the actor needs to wal...
Struct that defines one particular event with all its callbacks and data.
Definition: e_main.h:42
#define ERR_DROP
Definition: common.h:211
a local entity
le_t * LE_Get(int entnum)
Searches all local entities for the one with the searched entnum.
int nextTime
Definition: e_main.h:31
#define MAX_ROUTE
Definition: defines.h:84
int NET_ReadShort(dbuffer *buf)
Definition: netpack.cpp:242
int startTime
clientBattleScape_t cl
void LE_DoEndPathMove(le_t *le)
Ends the move of an actor.
int NET_PeekByte(const dbuffer *buf)
Definition: netpack.cpp:251
int team
pos_t pos3_t[3]
Definition: ufotypes.h:58
dvec_t dvtab[MAX_ROUTE]
#define PosAddDV(p, crouch, dv)
Definition: mathlib.h:253
#define DIRECTION_FALL
Definition: defines.h:335
#define VectorCompare(a, b)
Definition: vector.h:63
int NET_PeekLong(const dbuffer *buf)
Definition: netpack.cpp:273
int endTime
int pathPos
QGL_EXTERN GLint i
Definition: r_gl.h:113
#define LE_IsDead(le)
void LE_Lock(le_t *le)
Markes a le_t struct as locked. Should be called at the beginning of an event handler on this le_t...
void resetFloor()
#define Mem_AllocType(type)
Definition: mem.h:39
int stepTimes[MAX_ROUTE]
#define getDVdir(dv)
Definition: mathlib.h:249
entity_type_t type
short dvec_t
The direction vector tells us where the actor came from (in his previous step). The pathing table hol...
Definition: mathlib.h:236
void LET_HiddenMove(le_t *le)
Handle move for invisible actors.
bool isMoving() const
pos3_t newPos
void LE_SetThink(le_t *le, localEntityThinkFunc_t think)
uint8_t byte
Definition: ufotypes.h:34
leStep_t * stepList
int speed[MAX_ROUTE]
int NET_ReadByte(dbuffer *buf)
Reads a byte from the netchannel.
Definition: netpack.cpp:234
int stepIndex
void LET_StartPathMove(le_t *le)
Change the actors animation to walking.
#define LE_NotFoundError(entnum)
pos3_t pos