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