Xonotic
models.qc
Go to the documentation of this file.
1 #include "models.qh"
2 
3 #ifdef SVQC
4 #include <common/constants.qh>
8 #include <common/net_linked.qh>
9 #include <common/stats.qh>
10 #include <common/weapons/_all.qh>
12 
13 void g_model_setcolormaptoactivator(entity this, entity actor, entity trigger)
14 {
15  if(teamplay)
16  {
17  if(actor.team)
18  this.colormap = (actor.team - 1) * 0x11;
19  else
20  this.colormap = 0x00;
21  }
22  else
23  this.colormap = floor(random() * 256);
24  this.colormap |= BIT(10); // RENDER_COLORMAPPED
25 }
26 
27 void g_clientmodel_setcolormaptoactivator(entity this, entity actor, entity trigger)
28 {
29  g_model_setcolormaptoactivator(this, actor, trigger);
30  this.SendFlags |= (BIT(3) | BIT(0));
31 }
32 
33 void g_clientmodel_use(entity this, entity actor, entity trigger)
34 {
35  // Flag to set func_clientwall state
36  // 1 == deactivate, 2 == activate, 0 == do nothing
37  if(this.classname == "func_clientwall" || this.classname == "func_clientillusionary")
38  this.antiwall_flag = trigger.antiwall_flag;
39 
40  if (this.antiwall_flag == 1)
41  {
42  this.inactive = 1;
43  this.solid = SOLID_NOT;
44  }
45  else if (this.antiwall_flag == 2)
46  {
47  this.inactive = 0;
48  this.solid = this.default_solid;
49  }
50  g_clientmodel_setcolormaptoactivator(this, actor, trigger);
51 }
52 
53 void g_model_dropbyspawnflags(entity this)
54 {
55  if((this.spawnflags & 3) == 1) // ALIGN_ORIGIN
56  {
57  traceline(this.origin, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
58  setorigin(this, trace_endpos);
59  }
60  else if((this.spawnflags & 3) == 2) // ALIGN_BOTTOM
61  {
62  tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
63  setorigin(this, trace_endpos);
64  }
65  else if((this.spawnflags & 3) == 3) // ALIGN_ORIGIN | ALIGN_BOTTOM
66  {
67  traceline(this.origin, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
68  setorigin(this, trace_endpos - '0 0 1' * this.mins.z);
69  }
70 }
71 
72 void g_clientmodel_dropbyspawnflags(entity this)
73 {
74  vector o0;
75  o0 = this.origin;
76  g_model_dropbyspawnflags(this);
77  if(this.origin != o0)
78  this.SendFlags |= 2;
79 }
80 
81 bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
82 {
83  sf = sf & 0x0F;
84  if(this.angles != '0 0 0')
85  sf |= 0x10;
86  if(this.mins != '0 0 0' || this.maxs != '0 0 0')
87  sf |= 0x20;
88  if(this.colormap != 0)
89  sf |= 0x40;
90  if(this.lodmodelindex1)
91  sf |= 0x80;
92 
93  WriteHeader(MSG_ENTITY, ENT_CLIENT_WALL);
94  WriteByte(MSG_ENTITY, sf);
95 
96  if(sf & BIT(0))
97  {
98  if(sf & 0x40)
99  WriteShort(MSG_ENTITY, this.colormap);
100  WriteByte(MSG_ENTITY, this.skin);
101  }
102 
103  if(sf & BIT(1))
104  {
105  WriteVector(MSG_ENTITY, this.origin);
106  }
107 
108  if(sf & BIT(2))
109  {
110  if(sf & 0x10)
111  WriteAngleVector(MSG_ENTITY, this.angles);
112  }
113 
114  if(sf & BIT(3))
115  {
116  if(sf & 0x80)
117  {
118  WriteShort(MSG_ENTITY, this.lodmodelindex0);
119  WriteShort(MSG_ENTITY, bound(0, this.loddistance1, 32767));
120  WriteShort(MSG_ENTITY, this.lodmodelindex1);
121  WriteShort(MSG_ENTITY, bound(0, this.loddistance2, 32767));
122  WriteShort(MSG_ENTITY, this.lodmodelindex2);
123  }
124  else
125  WriteShort(MSG_ENTITY, this.modelindex);
126  WriteByte(MSG_ENTITY, this.solid);
127  WriteShort(MSG_ENTITY, floor(this.scale * 256));
128  if(sf & 0x20)
129  {
130  WriteVector(MSG_ENTITY, this.mins);
131  WriteVector(MSG_ENTITY, this.maxs);
132  }
133  WriteString(MSG_ENTITY, this.bgmscript);
134  if(this.bgmscript != "")
135  {
136  WriteByte(MSG_ENTITY, floor(this.bgmscriptattack * 64));
137  WriteByte(MSG_ENTITY, floor(this.bgmscriptdecay * 64));
138  WriteByte(MSG_ENTITY, floor(this.bgmscriptsustain * 255));
139  WriteByte(MSG_ENTITY, floor(this.bgmscriptrelease * 64));
140  WriteVector(MSG_ENTITY, this.movedir);
141  WriteByte(MSG_ENTITY, floor(this.lip * 255));
142  }
143  WriteShort(MSG_ENTITY, bound(0, this.fade_start, 32767));
144  WriteShort(MSG_ENTITY, bound(0, this.fade_end, 32767));
145  WriteByte(MSG_ENTITY, floor(this.alpha_max * 256));
146  WriteByte(MSG_ENTITY, floor(this.alpha_min * 256));
147  WriteByte(MSG_ENTITY, this.inactive);
148  WriteShort(MSG_ENTITY, this.fade_vertical_offset);
149  }
150 
151  return true;
152 }
153 
154 
155 #define G_MODEL_INIT(ent,sol) \
156  if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
157  if(!ent.scale) ent.scale = ent.modelscale; \
158  SetBrushEntityModel(ent,true); \
159  ent.use = g_model_setcolormaptoactivator; \
160  InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
161  if(!ent.solid) ent.solid = (sol); \
162  else if(ent.solid < 0) ent.solid = SOLID_NOT;
163 
164 #define G_CLIENTMODEL_INIT(ent,sol) \
165  if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
166  if(!ent.scale) ent.scale = ent.modelscale; \
167  SetBrushEntityModel(ent,true); \
168  ent.use = g_clientmodel_use; \
169  InitializeEntity(ent, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
170  if(!ent.solid) ent.solid = (sol); \
171  else if(ent.solid < 0) ent.solid = SOLID_NOT; \
172  if(!ent.bgmscriptsustain) ent.bgmscriptsustain = 1; \
173  else if(ent.bgmscriptsustain < 0) ent.bgmscriptsustain = 0; \
174  Net_LinkEntity(ent, true, 0, g_clientmodel_genericsendentity); \
175  ent.default_solid = sol;
176 
177 // non-solid model entities:
178 spawnfunc(misc_gamemodel) { this.angles_x = -this.angles.x; G_MODEL_INIT (this, SOLID_NOT) } // model entity
179 spawnfunc(misc_clientmodel) { this.angles_x = -this.angles.x; G_CLIENTMODEL_INIT(this, SOLID_NOT) } // model entity
180 spawnfunc(misc_models) { this.angles_x = -this.angles.x; G_MODEL_INIT (this, SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
181 
182 // non-solid brush entities:
183 spawnfunc(func_illusionary) { G_MODEL_INIT (this, SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
184 spawnfunc(func_clientillusionary) { G_CLIENTMODEL_INIT(this, SOLID_NOT) } // brush entity
185 
186 // solid brush entities
187 spawnfunc(func_wall) { G_MODEL_INIT (this, SOLID_BSP) } // Q1 name
188 spawnfunc(func_clientwall) { G_CLIENTMODEL_INIT(this, SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
189 spawnfunc(func_static) { G_MODEL_INIT (this, SOLID_BSP) } // DEPRECATED old alias name from some other game
190 #elif defined(CSQC)
191 .float alpha;
192 .float scale;
193 .vector movedir;
194 
195 void Ent_Wall_PreDraw(entity this)
196 {
197  float alph = this.alpha;
198  if (this.inactive)
199  {
200  alph = 0;
201  }
202  else
203  {
204  vector org = getpropertyvec(VF_ORIGIN);
205  if(!checkpvs(org, this))
206  alph = 0;
207  else if(this.fade_start || this.fade_end) {
208  vector offset = '0 0 0';
209  offset_z = this.fade_vertical_offset;
210  vector player_dist_math = org - this.origin - 0.5 * (this.mins + this.maxs) + offset;
211  if (this.fade_end == this.fade_start)
212  {
213  if (vdist(player_dist_math, >=, this.fade_start))
214  alph = 0;
215  else
216  alph = 1;
217  }
218  else
219  {
220  float player_dist = vlen(player_dist_math);
221  alph = (this.alpha_min + this.alpha_max * bound(0,
222  (this.fade_end - player_dist)
223  / (this.fade_end - this.fade_start), 1)) / 100.0;
224  }
225  }
226  else
227  {
228  alph = 1;
229  }
230  }
231  this.alpha = alph;
232  this.drawmask = (alph <= 0) ? 0 : MASK_NORMAL;
233 }
234 
235 void Ent_Wall_Draw(entity this)
236 {
237  float f;
238  var .vector fld;
239 
240  if(this.bgmscriptangular)
241  fld = angles;
242  else
243  fld = origin;
244  this.(fld) = this.saved;
245 
246  if(this.lodmodelindex1)
247  {
249  {
251  this.modelindex = this.lodmodelindex2;
252  else if(autocvar_cl_modeldetailreduction <= -1)
253  this.modelindex = this.lodmodelindex1;
254  else
255  this.modelindex = this.lodmodelindex0;
256  }
257  else
258  {
259  float distance = vlen(NearestPointOnBox(this, view_origin) - view_origin);
260  f = (distance * current_viewzoom + 100.0) * autocvar_cl_modeldetailreduction;
261  f *= 1.0 / bound(0.01, view_quality, 1);
262  if(this.lodmodelindex2 && f > this.loddistance2)
263  this.modelindex = this.lodmodelindex2;
264  else if(f > this.loddistance1)
265  this.modelindex = this.lodmodelindex1;
266  else
267  this.modelindex = this.lodmodelindex0;
268  }
269  }
270 
271  InterpolateOrigin_Do(this);
272 
273  this.saved = this.(fld);
274 
275  f = doBGMScript(this);
276  if(f >= 0)
277  {
278  if(this.lip < 0) // < 0: alpha goes from 1 to 1-|lip| when toggled (toggling subtracts lip)
279  this.alpha = 1 + this.lip * f;
280  else // > 0: alpha goes from 1-|lip| to 1 when toggled (toggling adds lip)
281  this.alpha = 1 - this.lip * (1 - f);
282  this.(fld) = this.(fld) + this.movedir * f;
283  }
284  else
285  this.alpha = 1;
286 
287  if(this.alpha >= ALPHA_MIN_VISIBLE)
288  this.drawmask = MASK_NORMAL;
289  else
290  this.drawmask = 0;
291 }
292 
293 void Ent_Wall_Remove(entity this)
294 {
295  strfree(this.bgmscript);
296 }
297 
298 NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
299 {
300  int f;
301  var .vector fld;
302 
305 
306  if(this.bgmscriptangular)
307  fld = angles;
308  else
309  fld = origin;
310  this.(fld) = this.saved;
311 
312  f = ReadByte();
313 
314  if(f & 1)
315  {
316  if(f & 0x40)
317  this.colormap = ReadShort();
318  else
319  this.colormap = 0;
320  this.skin = ReadByte();
321  }
322 
323  if(f & 2)
324  {
325  this.origin = ReadVector();
326  setorigin(this, this.origin);
327  }
328 
329  if(f & 4)
330  {
331  if(f & 0x10)
332  this.angles = ReadAngleVector();
333  else
334  this.angles = '0 0 0';
335  }
336 
337  if(f & 8)
338  {
339  if(f & 0x80)
340  {
341  this.lodmodelindex0 = ReadShort();
342  this.loddistance1 = ReadShort();
343  this.lodmodelindex1 = ReadShort();
344  this.loddistance2 = ReadShort();
345  this.lodmodelindex2 = ReadShort();
346  }
347  else
348  {
349  this.modelindex = ReadShort();
350  this.loddistance1 = 0;
351  this.loddistance2 = 0;
352  }
353  this.solid = ReadByte();
354  this.scale = ReadShort() / 256.0;
355  if(f & 0x20)
356  {
357  this.mins = ReadVector();
358  this.maxs = ReadVector();
359  }
360  else
361  this.mins = this.maxs = '0 0 0';
362  setsize(this, this.mins, this.maxs);
363 
364  string s = ReadString();
365  if(substring(s, 0, 1) == "<")
366  {
367  strcpy(this.bgmscript, substring(s, 1, -1));
368  this.bgmscriptangular = 1;
369  }
370  else
371  {
372  strcpy(this.bgmscript, s);
373  this.bgmscriptangular = 0;
374  }
375  if(this.bgmscript != "")
376  {
377  this.bgmscriptattack = ReadByte() / 64.0;
378  this.bgmscriptdecay = ReadByte() / 64.0;
379  this.bgmscriptsustain = ReadByte() / 255.0;
380  this.bgmscriptrelease = ReadByte() / 64.0;
381  this.movedir = ReadVector();
382  this.lip = ReadByte() / 255.0;
383  }
384  this.fade_start = ReadShort();
385  this.fade_end = ReadShort();
386  this.alpha_max = ReadByte() / 255.0;
387  this.alpha_min = ReadByte() / 255.0;
388  this.inactive = ReadByte();
389  this.fade_vertical_offset = ReadShort();
390  BGMScript_InitEntity(this);
391  }
392 
393  return = true;
394 
396 
397  this.saved = this.(fld);
398 
399  this.entremove = Ent_Wall_Remove;
400  this.draw = Ent_Wall_Draw;
401  if (isnew) IL_PUSH(g_drawables, this);
402  setpredraw(this, Ent_Wall_PreDraw);
403 }
404 #endif
const float SOLID_NOT
Definition: csprogsdefs.qc:244
void InterpolateOrigin_Note(entity this)
Definition: interpolate.qc:37
const float ALPHA_MIN_VISIBLE
Definition: main.qh:128
float colormap
Definition: csprogsdefs.qc:131
float alpha
Definition: items.qc:14
int iflags
Definition: interpolate.qh:26
float default_solid
Definition: models.qh:24
float alpha_max
Definition: models.qh:20
skin
Definition: ent_cs.qc:143
void InterpolateOrigin_Undo(entity this)
snap origin to iorigin2 (actual origin)
Definition: interpolate.qc:159
#define ReadString
float modelindex
Definition: csprogsdefs.qc:91
entity() spawn
float fade_start
Definition: models.qh:23
vector view_origin
Definition: main.qh:93
vector maxs
Definition: csprogsdefs.qc:113
float checkpvs(vector viewpos, entity viewee)
float current_viewzoom
Definition: main.qh:101
#define setpredraw(e, f)
Definition: self.qh:84
#define NET_HANDLE(id, param)
Definition: net.qh:12
int autocvar_cl_modeldetailreduction
entity to
Definition: self.qh:96
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
string classname
Definition: csprogsdefs.qc:107
float spawnflags
Definition: progsdefs.qc:191
#define strcpy(this, s)
Definition: string.qh:49
int lodmodelindex0
float alpha_min
Definition: models.qh:20
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
vector movedir
Definition: progsdefs.qc:203
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
vector mins
Definition: csprogsdefs.qc:113
float fade_vertical_offset
Definition: models.qh:23
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void BGMScript_InitEntity(entity e)
Definition: bgmscript.qc:116
vector trace_endpos
Definition: csprogsdefs.qc:37
int lodmodelindex2
float teamplay
Definition: progsdefs.qc:31
const float MASK_NORMAL
Definition: csprogsdefs.qc:164
float drawmask
Definition: csprogsdefs.qc:95
float scale
Definition: projectile.qc:14
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int IFLAG_ORIGIN
Definition: interpolate.qh:36
const float SOLID_BSP
Definition: csprogsdefs.qc:248
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float lip
Definition: subs.qh:40
float view_quality
Definition: main.qh:143
bool inactive
Definition: models.qh:19
int lodmodelindex1
setorigin(ent, v)
#define strfree(this)
Definition: string.qh:56
vector angles
Definition: csprogsdefs.qc:104
float antiwall_flag
Definition: triggers.qh:6
float doBGMScript(entity e)
Definition: bgmscript.qc:173
float fade_end
Definition: models.qh:23
void InterpolateOrigin_Do(entity this)
set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time
Definition: interpolate.qc:129
IntrusiveList g_drawables
Definition: main.qh:77
const int IFLAG_ANGLES
Definition: interpolate.qh:28
const float VF_ORIGIN
Definition: csprogsdefs.qc:182
float solid
Definition: csprogsdefs.qc:99