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;
95 o0 = this.origin;
97 if(this.origin != o0)
98 this.SendFlags |= BIT(1);
99}
100
102{
103 sf = sf & 0x0F;
104 if(this.angles != '0 0 0')
105 sf |= 0x10;
106 if(this.mins != '0 0 0' || this.maxs != '0 0 0')
107 sf |= 0x20;
108 if(this.colormap != 0)
109 sf |= 0x40;
110 if(this.lodmodelindex1)
111 sf |= 0x80;
112
113 WriteHeader(MSG_ENTITY, ENT_CLIENT_WALL);
115
116 if(sf & BIT(0))
117 {
118 if(sf & 0x40)
121 }
122
123 if(sf & BIT(1))
124 {
125 WriteVector(MSG_ENTITY, this.origin);
126 }
127
128 if(sf & BIT(2))
129 {
130 if(sf & 0x10)
131 WriteAngleVector(MSG_ENTITY, this.angles);
132 }
133
134 if(sf & BIT(3))
135 {
136 if(sf & 0x80)
137 {
139 WriteShort(MSG_ENTITY, bound(0, this.loddistance1, 32767));
141 WriteShort(MSG_ENTITY, bound(0, this.loddistance2, 32767));
143 }
144 else
147 WriteShort(MSG_ENTITY, floor(this.scale * 256));
148 if(sf & 0x20)
149 {
150 WriteVector(MSG_ENTITY, this.mins);
151 WriteVector(MSG_ENTITY, this.maxs);
152 }
153 WriteString(MSG_ENTITY, this.bgmscript);
154 if(this.bgmscript != "")
155 {
156 WriteByte(MSG_ENTITY, floor(this.bgmscriptattack * 64));
157 WriteByte(MSG_ENTITY, floor(this.bgmscriptdecay * 64));
158 WriteByte(MSG_ENTITY, floor(this.bgmscriptsustain * 255));
159 WriteByte(MSG_ENTITY, floor(this.bgmscriptrelease * 64));
160 WriteVector(MSG_ENTITY, this.movedir);
161 WriteByte(MSG_ENTITY, floor(this.lip * 255));
162 }
163 WriteShort(MSG_ENTITY, bound(0, this.fade_start, 32767));
164 WriteShort(MSG_ENTITY, bound(0, this.fade_end, 32767));
165 WriteByte(MSG_ENTITY, floor(this.alpha_max * 256));
166 WriteByte(MSG_ENTITY, floor(this.alpha_min * 256));
169 }
170
171 return true;
172}
173
174void g_model_init(entity ent, float sol)
175{
176 if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS);
177 if(!ent.scale) ent.scale = ent.modelscale;
178
179 if(!ent.solid) ent.solid = (sol);
180 else if(ent.solid < 0) ent.solid = SOLID_NOT;
181 SetBrushEntityModel(ent,true); // called after setting .solid to ensure correct area grid linking/unlinking
182
185}
186
187void g_clientmodel_init(entity ent, float sol)
188{
189 if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS);
190 if(!ent.scale) ent.scale = ent.modelscale;
191
192 if(!ent.solid) ent.solid = (sol);
193 else if(ent.solid < 0) ent.solid = SOLID_NOT;
194 SetBrushEntityModel(ent,true); // called after setting .solid to ensure correct area grid linking/unlinking
195
196 ent.use = g_clientmodel_use;
198 ent.nextthink = time;
199 ent.oldorigin = ent.origin; // don't run an initial double update
201 if(!ent.bgmscriptsustain) ent.bgmscriptsustain = 1;
202 else if(ent.bgmscriptsustain < 0) ent.bgmscriptsustain = 0;
204 ent.default_solid = sol;
205}
206
207// non-solid model entities:
208spawnfunc(misc_gamemodel) { this.angles_x = -this.angles.x; g_model_init(this, SOLID_NOT); } // model entity
209spawnfunc(misc_clientmodel) { this.angles_x = -this.angles.x; g_clientmodel_init(this, SOLID_NOT); } // model entity
210spawnfunc(misc_models) { this.angles_x = -this.angles.x; g_model_init(this, SOLID_NOT); } // DEPRECATED old compat entity with confusing name, do not use
211
212// non-solid brush entities:
213spawnfunc(func_illusionary) { g_model_init(this, SOLID_NOT); } // Q1 name (WARNING: MISPREDICTED)
214spawnfunc(func_clientillusionary) { g_clientmodel_init(this, SOLID_NOT); } // brush entity
215
216// solid brush entities
217spawnfunc(func_wall) { g_model_init(this, SOLID_BSP); } // Q1 name
218spawnfunc(func_clientwall) { g_clientmodel_init(this, SOLID_BSP); } // brush entity (WARNING: MISPREDICTED)
219spawnfunc(func_static) { g_model_init(this, SOLID_BSP); } // DEPRECATED old alias name from some other game
220#elif defined(CSQC)
221.float alpha;
222.float scale;
223.vector movedir;
224
225void Ent_Wall_PreDraw(entity this)
226{
227 float alph = this.alpha;
228 if (this.inactive)
229 {
230 alph = 0;
231 }
232 else
233 {
234 vector org = getpropertyvec(VF_ORIGIN);
235 if(!checkpvs(org, this))
236 alph = 0;
237 else if(this.fade_start || this.fade_end) {
238 vector offset = '0 0 0';
239 offset_z = this.fade_vertical_offset;
240 vector player_dist_math = org - this.origin - 0.5 * (this.mins + this.maxs) + offset;
241 if (this.fade_end == this.fade_start)
242 {
243 if (vdist(player_dist_math, >=, this.fade_start))
244 alph = 0;
245 }
246 else
247 {
248 float player_dist = vlen(player_dist_math);
249 alph = (this.alpha_min + this.alpha_max * bound(0,
250 (this.fade_end - player_dist)
251 / (this.fade_end - this.fade_start), 1)) / 100.0;
252 }
253 }
254 }
255 this.alpha = alph;
256 if(this.alpha >= ALPHA_MIN_VISIBLE)
257 this.drawmask = MASK_NORMAL;
258 else
259 this.drawmask = 0;
260}
261
262void Ent_Wall_Draw(entity this)
263{
264 float f;
265 var .vector fld;
266
267 if(this.bgmscriptangular)
268 fld = angles;
269 else
270 fld = origin;
271 this.(fld) = this.saved;
272
273 CSQCModel_LOD_Apply(this, false);
274
276
277 this.saved = this.(fld);
278
279 f = doBGMScript(this);
280 if(f >= 0)
281 {
282 if(this.lip < 0) // < 0: alpha goes from 1 to 1-|lip| when toggled (toggling subtracts lip)
283 this.alpha = 1 + this.lip * f;
284 else // > 0: alpha goes from 1-|lip| to 1 when toggled (toggling adds lip)
285 this.alpha = 1 - this.lip * (1 - f);
286 this.(fld) = this.(fld) + this.movedir * f;
287 }
288 else
289 this.alpha = 1;
290}
291
292void Ent_Wall_Remove(entity this)
293{
294 strfree(this.bgmscript);
295}
296
297NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
298{
299 int f;
300 var .vector fld;
301
304
305 if(this.bgmscriptangular)
306 fld = angles;
307 else
308 fld = origin;
309 this.(fld) = this.saved;
310
311 f = ReadByte();
312
313 if(f & 1)
314 {
315 if(f & 0x40)
316 this.colormap = ReadShort();
317 else
318 this.colormap = 0;
319 this.skin = ReadByte();
320 }
321
322 if(f & 2)
323 {
324 this.origin = ReadVector();
325 setorigin(this, this.origin);
326 }
327
328 if(f & 4)
329 {
330 if(f & 0x10)
331 this.angles = ReadAngleVector();
332 else
333 this.angles = '0 0 0';
334 }
335
336 if(f & 8)
337 {
338 if(f & 0x80)
339 {
340 this.lodmodelindex0 = ReadShort();
341 this.loddistance1 = ReadShort();
342 this.lodmodelindex1 = ReadShort();
343 this.loddistance2 = ReadShort();
344 this.lodmodelindex2 = ReadShort();
345 this.modelindex = this.lodmodelindex0;
346 vector pmin = this.mins, pmax = this.maxs;
347 setmodelindex(this, this.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
348 setsize(this, pmin, pmax);
349 // if there's no second LOD model, fall back to the first
350 // avoids using the high quality model at a distance
351 if(!this.lodmodelindex2 && this.lodmodelindex1)
352 this.lodmodelindex2 = this.lodmodelindex1;
353 }
354 else
355 {
356 this.modelindex = ReadShort();
357 vector pmin = this.mins, pmax = this.maxs;
358 setmodelindex(this, this.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
359 setsize(this, pmin, pmax);
360 this.loddistance1 = 0;
361 this.loddistance2 = 0;
362 }
363 this.solid = ReadByte();
364 this.scale = ReadShort() / 256.0;
365 if(f & 0x20)
366 {
367 this.mins = ReadVector();
368 this.maxs = ReadVector();
369 }
370 else
371 this.mins = this.maxs = '0 0 0';
372 setsize(this, this.mins, this.maxs);
373
374 string s = ReadString();
375 if(substring(s, 0, 1) == "<")
376 {
377 strcpy(this.bgmscript, substring(s, 1, -1));
378 this.bgmscriptangular = 1;
379 }
380 else
381 {
382 strcpy(this.bgmscript, s);
383 this.bgmscriptangular = 0;
384 }
385 if(this.bgmscript != "")
386 {
387 this.bgmscriptattack = ReadByte() / 64.0;
388 this.bgmscriptdecay = ReadByte() / 64.0;
389 this.bgmscriptsustain = ReadByte() / 255.0;
390 this.bgmscriptrelease = ReadByte() / 64.0;
391 this.movedir = ReadVector();
392 this.lip = ReadByte() / 255.0;
393 }
394 this.fade_start = ReadShort();
395 this.fade_end = ReadShort();
396 this.alpha_max = ReadByte() / 255.0;
397 this.alpha_min = ReadByte() / 255.0;
398 this.inactive = ReadByte();
399 this.fade_vertical_offset = ReadShort();
401 }
402
403 return = true;
404
406
407 this.saved = this.(fld);
408
409 this.entremove = Ent_Wall_Remove;
410 this.draw = Ent_Wall_Draw;
411 if (isnew) IL_PUSH(g_drawables, this);
412 setpredraw(this, Ent_Wall_PreDraw);
413}
414#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:118
#define NET_HANDLE(id, param)
Definition net.qh:15
const int MSG_ENTITY
Definition net.qh:115
#define ReadVector()
Definition net.qh:367
#define ReadAngleVector()
Definition net.qh:369
#define WriteHeader(to, id)
Definition net.qh:221
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:123
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:174
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:101
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:187
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:420
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:2209