UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
e_event_actormove.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2020 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 }
void NET_ReadGPos(dbuffer *buf, pos3_t pos)
Definition: netpack.cpp:376
#define VectorCopy(src, dest)
Definition: vector.h:51
pos3_t newPos
#define LE_IsCrouched(le)
void CL_ActorDoMove(const eventRegister_t *self, dbuffer *msg)
Moves actor.
int entnum
int startTime
pos3_t pos
int pathPos
#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 stepTimes[MAX_ROUTE]
CL_ParseEvent timers and vars.
Definition: e_main.h:30
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)
void resetFloor()
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...
int lastMoveTime
#define ERR_DROP
Definition: common.h:211
le_t * LE_Get(int entnum)
Searches all local entities for the one with the searched entnum.
int lastMoveDuration
struct leStep_s * next
int stepIndex
#define MAX_ROUTE
Definition: defines.h:84
int NET_ReadShort(dbuffer *buf)
Definition: netpack.cpp:242
clientBattleScape_t cl
void LE_DoEndPathMove(le_t *le)
Ends the move of an actor.
int endTime
int NET_PeekByte(const dbuffer *buf)
Definition: netpack.cpp:251
pos_t pos3_t[3]
Definition: ufotypes.h:58
Struct that defines one particular event with all its callbacks and data.
Definition: e_main.h:42
#define PosAddDV(p, crouch, dv)
Definition: mathlib.h:253
#define DIRECTION_FALL
Definition: defines.h:335
#define VectorCompare(a, b)
Definition: vector.h:63
a local entity
int speed[MAX_ROUTE]
int NET_PeekLong(const dbuffer *buf)
Definition: netpack.cpp:273
int pathContents[MAX_ROUTE]
entity_type_t type
QGL_EXTERN GLint i
Definition: r_gl.h:113
int pathLength
#define LE_IsDead(le)
bool isMoving() const
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...
dvec_t dvtab[MAX_ROUTE]
#define Mem_AllocType(type)
Definition: mem.h:39
#define getDVdir(dv)
Definition: mathlib.h:249
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.
int team
int nextTime
Definition: e_main.h:31
void LE_SetThink(le_t *le, localEntityThinkFunc_t think)
uint8_t byte
Definition: ufotypes.h:34
leStep_t * stepList
int NET_ReadByte(dbuffer *buf)
Reads a byte from the netchannel.
Definition: netpack.cpp:234
void LET_StartPathMove(le_t *le)
Change the actors animation to walking.
#define LE_NotFoundError(entnum)