UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
e_event_actorshoot.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 "../../../../renderer/r_mesh.h"
28 #include "../../../../renderer/r_mesh_anim.h"
29 #include "e_event_actorshoot.h"
30 
36 int CL_ActorDoShootTime (const eventRegister_t* self, dbuffer* msg, eventTiming_t* eventTiming)
37 {
38  int flags, dummy;
39  int objIdx, surfaceFlags;
40  int weap_fds_idx, fd_idx;
41  shoot_types_t shootType;
42  vec3_t muzzle, impact;
43  int eventTime = eventTiming->shootTime;
44 
45  /* read data */
46  NET_ReadFormat(msg, self->formatString, &dummy, &dummy, &dummy, &objIdx, &weap_fds_idx, &fd_idx, &shootType, &flags,
47  &surfaceFlags, &muzzle, &impact, &dummy);
48 
49  const objDef_t* obj = INVSH_GetItemByIDX(objIdx);
50  const fireDef_t* fd = FIRESH_GetFiredef(obj, weap_fds_idx, fd_idx);
51 
52  if (!(flags & SF_BOUNCED)) {
53  /* shooting */
54  if (fd->speed > 0.0 && !CL_OutsideMap(impact, UNIT_SIZE * 10)) {
55  eventTiming->impactTime = eventTiming->shootTime + 1000 * VectorDist(muzzle, impact) / fd->speed;
56  } else {
57  eventTiming->impactTime = eventTiming->shootTime;
58  }
59  if (!cls.isOurRound())
60  eventTiming->nextTime = CL_GetNextTime(self, eventTiming, eventTiming->impactTime + 1400);
61  else
62  eventTiming->nextTime = CL_GetNextTime(self, eventTiming, eventTiming->impactTime + 400);
63  if (fd->delayBetweenShots > 0.0)
64  eventTiming->shootTime += 1000 / fd->delayBetweenShots;
65  } else {
66  /* only a bounced shot */
67  eventTime = eventTiming->impactTime;
68  if (fd->speed > 0.0) {
69  eventTiming->impactTime += 1000 * VectorDist(muzzle, impact) / fd->speed;
70  eventTiming->nextTime = CL_GetNextTime(self, eventTiming, eventTiming->impactTime);
71  }
72  }
73  eventTiming->parsedDeath = false;
74 
75  return eventTime;
76 }
77 
88 static void CL_ActorGetMuzzle (const le_t* actor, vec3_t muzzle, shoot_types_t shootType)
89 {
90  if (actor == nullptr)
91  return;
92 
93  const Item* weapon;
94  const char* tag;
95  if (IS_SHOT_RIGHT(shootType)) {
96  tag = "tag_rweapon";
97  weapon = actor->getRightHandItem();
98  } else {
99  tag = "tag_lweapon";
100  weapon = actor->getLeftHandItem();
101  }
102 
103  if (!weapon || !weapon->def())
104  return;
105 
106  const objDef_t* od = weapon->def();
107  const model_t* model = cls.modelPool[od->idx];
108  if (!model)
109  Com_Error(ERR_DROP, "Model for item %s is not precached", od->id);
110 
111  /* not every weapon has a muzzle tag assigned */
112  if (R_GetTagIndexByName(model, "tag_muzzle") == -1)
113  return;
114 
115  float modifiedMatrix[16];
116  if (!R_GetTagMatrix(actor->model1, tag, actor->as.frame, modifiedMatrix))
117  Com_Error(ERR_DROP, "Could not find tag %s for actor model %s", tag, actor->model1->name);
118 
119  float mc[16];
120  GLMatrixAssemble(actor->origin, actor->angles, mc);
121 
122  float matrix[16];
123  GLMatrixMultiply(mc, modifiedMatrix, matrix);
124 
125  R_GetTagMatrix(model, "tag_muzzle", 0, modifiedMatrix);
126  GLMatrixMultiply(matrix, modifiedMatrix, mc);
127 
128  muzzle[0] = mc[12];
129  muzzle[1] = mc[13];
130  muzzle[2] = mc[14];
131 }
132 
140 void CL_ActorDoShoot (const eventRegister_t* self, dbuffer* msg)
141 {
142  vec3_t muzzle, impact;
143  int flags, normal, shooterEntnum, victimEntnum;
144  int objIdx;
145  int first;
146  weaponFireDefIndex_t weapFdsIdx;
147  fireDefIndex_t fdIdx;
148  int surfaceFlags;
149  shoot_types_t shootType;
150 
151  /* read data */
152  NET_ReadFormat(msg, self->formatString, &shooterEntnum, &victimEntnum, &first, &objIdx, &weapFdsIdx, &fdIdx, &shootType, &flags, &surfaceFlags, &muzzle, &impact, &normal);
153 
154  le_t* leVictim;
155  if (victimEntnum != SKIP_LOCAL_ENTITY) {
156  leVictim = LE_Get(victimEntnum);
157  if (!leVictim)
158  LE_NotFoundError(victimEntnum);
159  } else {
160  leVictim = nullptr;
161  }
162 
163  /* get shooter le */
164  le_t* leShooter = LE_Get(shooterEntnum);
165 
166  /* get the fire def */
167  const objDef_t* obj = INVSH_GetItemByIDX(objIdx);
168  const fireDef_t* fd = FIRESH_GetFiredef(obj, weapFdsIdx, fdIdx);
169 
170  CL_ActorGetMuzzle(leShooter, muzzle, shootType);
171 
172  /* add effect le */
173  LE_AddProjectile(fd, flags, muzzle, impact, normal, leVictim);
174 
175  /* start the sound */
176  if ((first || !fd->soundOnce) && fd->fireSound != nullptr && !(flags & SF_BOUNCED))
178 
179  /* do actor related stuff */
180  if (!leShooter)
181  return; /* maybe hidden or inuse is false? */
182 
183  if (!LE_IsActor(leShooter))
184  Com_Error(ERR_DROP, "Can't shoot, LE not an actor (type: %i)", leShooter->type);
185 
186  /* no animations for hidden actors */
187  if (leShooter->type == ET_ACTORHIDDEN)
188  return;
189 
190  if (LE_IsDead(leShooter)) {
191  Com_DPrintf(DEBUG_CLIENT, "Can't shoot, actor dead or stunned.\n");
192  return;
193  }
194 
195  /* Animate - we have to check if it is right or left weapon usage. */
196  if (IS_SHOT_RIGHT(shootType)) {
197  R_AnimChange(&leShooter->as, leShooter->model1, LE_GetAnim("shoot", leShooter->right, leShooter->left, leShooter->state));
198  R_AnimAppend(&leShooter->as, leShooter->model1, LE_GetAnim("stand", leShooter->right, leShooter->left, leShooter->state));
199  } else if (IS_SHOT_LEFT(shootType)) {
200  R_AnimChange(&leShooter->as, leShooter->model1, LE_GetAnim("shoot", leShooter->left, leShooter->right, leShooter->state));
201  R_AnimAppend(&leShooter->as, leShooter->model1, LE_GetAnim("stand", leShooter->left, leShooter->right, leShooter->state));
202  } else if (IS_SHOT_HEADGEAR(shootType)) {
203  if (fd->irgoggles) {
204  leShooter->state |= RF_IRGOGGLESSHOT;
205  if (LE_IsSelected(leShooter))
207  }
208  } else {
209  /* no animation for headgear (yet) */
210  Com_Error(ERR_DROP, "CL_ActorDoShoot: Invalid shootType given (entnum: %i, shootType: %i).\n", shootType, shooterEntnum);
211  }
212 }
animState_t as
Item * getLeftHandItem() const
void GLMatrixAssemble(const vec3_t origin, const vec3_t angles, float *matrix)
Builds an opengl translation and rotation matrix.
Definition: mathlib.cpp:325
const char * LE_GetAnim(const char *anim, int right, int left, int state)
Get the correct animation for the given actor state and weapons.
this is a fire definition for our weapons/ammo
Definition: inv_shared.h:110
bool soundOnce
Definition: inv_shared.h:135
#define RF_IRGOGGLESSHOT
Definition: r_entity.h:52
float angles[3]
bool isOurRound() const
Definition: client.h:106
int CL_GetNextTime(const eventRegister_t *event, eventTiming_t *eventTiming, int nextTime)
Definition: e_main.cpp:203
void LE_AddProjectile(const fireDef_t *fd, int flags, const vec3_t muzzle, const vec3_t impact, int normal, le_t *leVictim)
const objDef_t * def(void) const
Definition: inv_shared.h:469
#define VectorDist(a, b)
Definition: vector.h:69
bool R_GetTagMatrix(const model_t *mod, const char *tagName, int frame, float matrix[16])
Definition: r_mesh.cpp:189
void CL_ActorDoShoot(const eventRegister_t *self, dbuffer *msg)
Shoot with weapon.
void NET_ReadFormat(dbuffer *buf, const char *format,...)
The user-friendly version of NET_ReadFormat that reads variable arguments from a buffer according to ...
Definition: netpack.cpp:533
bool S_LoadAndPlaySample(const char *s, const vec3_t origin, float attenuation, float volume)
does what the name implies in just one function to avoid exposing s_sample_t
Definition: s_main.cpp:314
bool CL_OutsideMap(const vec3_t position, const float delta)
Checks whether give position is still inside the map borders.
float speed
Definition: inv_shared.h:143
float fireAttenuation
Definition: inv_shared.h:120
vec3_t origin
int shootTime
Definition: e_main.h:32
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
bool LE_IsActor(const le_t *le)
Checks whether the given le is a living actor.
void R_AnimChange(animState_t *as, const model_t *mod, const char *name)
Changes the animation for md2 models.
CL_ParseEvent timers and vars.
Definition: e_main.h:30
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
#define SKIP_LOCAL_ENTITY
Definition: q_shared.h:255
#define IS_SHOT_RIGHT(x)
Determine whether the selected shoot type is for the item in the right hand, either shooting or react...
Definition: q_shared.h:243
int frame
Definition: r_entity.h:55
Item * getRightHandItem() const
client_static_t cls
Definition: cl_main.cpp:83
item instance data, with linked list capability
Definition: inv_shared.h:402
float delayBetweenShots
Definition: inv_shared.h:155
const fireDef_t * FIRESH_GetFiredef(const objDef_t *obj, const weaponFireDefIndex_t weapFdsIdx, const fireDefIndex_t fdIdx)
Get the fire definitions for a given object.
Definition: inv_shared.cpp:385
int right
#define ERR_DROP
Definition: common.h:211
#define DEBUG_CLIENT
Definition: defines.h:59
model_t * modelPool[MAX_OBJDEFS]
Definition: client.h:96
rendererData_t refdef
Definition: r_main.cpp:45
int32_t shoot_types_t
Available shoot types - also see the ST_ constants.
Definition: q_shared.h:206
le_t * LE_Get(int entnum)
Searches all local entities for the one with the searched entnum.
#define IS_SHOT_HEADGEAR(x)
Determine whether the selected shoot type is for the item in the headgear slot.
Definition: q_shared.h:245
#define IS_SHOT_LEFT(x)
Determine whether the selected shoot type is for the item in the left hand, either shooting or reacti...
Definition: q_shared.h:241
#define LE_IsSelected(le)
int32_t fireDefIndex_t
Definition: inv_shared.h:78
model_t * model1
const char * fireSound
Definition: inv_shared.h:117
char name[MAX_QPATH]
Definition: r_model.h:44
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
#define RDF_IRGOGGLES
Definition: cl_renderer.h:35
Struct that defines one particular event with all its callbacks and data.
Definition: e_main.h:42
int CL_ActorDoShootTime(const eventRegister_t *self, dbuffer *msg, eventTiming_t *eventTiming)
Decides if following events should be delayed. If the projectile has a speed value assigned...
#define UNIT_SIZE
Definition: defines.h:121
int32_t weaponFireDefIndex_t
Definition: inv_shared.h:77
a local entity
void GLMatrixMultiply(const float a[16], const float b[16], float c[16])
Multiply 4*4 matrix by 4*4 matrix.
Definition: mathlib.cpp:350
int R_GetTagIndexByName(const model_t *mod, const char *tagName)
Searches the tag data for the given name.
Definition: r_mesh.cpp:247
entity_type_t type
#define SND_VOLUME_WEAPONS
Definition: s_main.h:43
#define LE_IsDead(le)
bool parsedDeath
Definition: e_main.h:35
int impactTime
Definition: e_main.h:33
vec_t vec3_t[3]
Definition: ufotypes.h:39
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
Definition: inv_shared.cpp:266
int nextTime
Definition: e_main.h:31
void R_AnimAppend(animState_t *as, const model_t *mod, const char *name)
Appends a new animation to the current running one.
Definition: r_mesh_anim.cpp:84
#define SF_BOUNCED
Definition: q_shared.h:251
static void CL_ActorGetMuzzle(const le_t *actor, vec3_t muzzle, shoot_types_t shootType)
Calculates the muzzle for the current weapon the actor is shooting with.
int state
const char * id
Definition: inv_shared.h:268
bool irgoggles
Definition: inv_shared.h:140
#define LE_NotFoundError(entnum)
int left