Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
gibs.qc
Go to the documentation of this file.
1#include "gibs.qh"
2
3REGISTER_NET_TEMP(net_gibsplash)
4
5#ifdef SVQC
6
7.int state;
8
10{
11 int channel = MSG_ONE;
12 msg_entity = to;
13 WriteHeader(channel, net_gibsplash);
14 WriteByte(channel, this.state); // actually type
15 WriteByte(channel, bound(1, this.cnt * 16, 255)); // gibbage amount multiplier
16 WriteShort(channel, floor(this.origin.x / 4)); // not using a coord here, as gibs don't need this accuracy
17 WriteShort(channel, floor(this.origin.y / 4)); // not using a coord here, as gibs don't need this accuracy
18 WriteShort(channel, floor(this.origin.z / 4)); // not using a coord here, as gibs don't need this accuracy
19 WriteShort(channel, this.oldorigin.x); // actually compressed velocity
20 return true;
21}
22
23void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker)
24{
25 if(g_cts) // no gibs in CTS
26 return;
27
28 entity e = new_pure(gibsplash);
29 e.cnt = amount;
30 e.state = type; // should stay smaller than 15
31 if(!sound_allowed(MSG_BROADCAST, gibowner) || !sound_allowed(MSG_BROADCAST, attacker))
32 e.state |= 0x40; // "silence" bit
33 e.state |= 8 * gibowner.species; // gib type, ranges from 0 to 15
34
35 // if this is a copied dead body, send the num of its player instead
36 // TODO: remove this field, read from model txt files
37 if(gibowner.classname == "body")
38 e.team = etof(gibowner.enemy);
39 else
40 e.team = etof(gibowner);
41
42 // origin is just data to be sent
43 //setorigin(e, org);
44 e.origin = org;
45 e.velocity = dir;
46
47 e.oldorigin_x = compressShortVector(e.velocity);
48
50 delete(e);
51}
52
53void Violence_GibSplash(entity source, float type, float amount, entity attacker)
54{
55 Violence_GibSplash_At(source.origin + source.view_ofs, source.velocity, type, amount, source, attacker);
56}
57#endif
58
59#ifdef CSQC
60
61.vector colormod;
62.bool silent;
63
64#include "rubble.qh"
66
67.float scale;
68.float alpha;
69.float cnt;
70.float gravity;
71
73{
74 delete(this);
75}
76
77string species_prefix(int specnum);
78
79void Gib_setmodel(entity gib, string mdlname, int specnum)
80{
81 switch(specnum)
82 {
86 if(specnum != SPECIES_ROBOT_SOLID || mdlname == "models/gibs/chunk.mdl")
87 {
88 if(mdlname == "models/gibs/bloodyskull.md3")
89 setmodel(gib, MDL_GIB_ROBO);
90 else
92 if(specnum == SPECIES_ROBOT_SHINY)
93 {
94 gib.skin = 1;
95 gib.colormod = '2 2 2';
96 }
97 gib.scale = 1;
98 break;
99 }
100 default:
101 _setmodel(gib, mdlname);
102 gib.skin = specnum;
103 break;
104 }
105}
106
107void new_te_bloodshower (int ef, vector org, float explosionspeed, int howmany)
108{
109 float i, pmod;
111 for (i = 0; i < 50 * pmod; ++i)
112 __pointparticles(ef, org, randomvec() * explosionspeed, howmany / 50);
113}
114
120
122{
123 // TODO maybe bounce of walls, make more gibs, etc.
124
126 {
127 Gib_Delete(this);
128 return;
129 }
130
131 if(!this.silent)
133 __pointparticles(_particleeffectnum(strcat(species_prefix(this.cnt), "blood")), this.origin + '0 0 1', '0 0 30', 10);
134
135 Gib_Delete(this);
136}
137
138void Gib_Draw(entity this)
139{
140 vector oldorg = this.origin;
141
143 if(wasfreed(this))
144 return;
145
146 if(gettouch(this) == Gib_Touch) // don't do this for the "chunk" thingie...
147 // TODO somehow make it spray in a direction dependent on this.angles
148 __trailparticles(this, _particleeffectnum(strcat(species_prefix(this.cnt), EFFECT_TR_SLIGHTBLOOD.eent_eff_name)), oldorg, this.origin);
149 else
150 __trailparticles(this, _particleeffectnum(strcat(species_prefix(this.cnt), EFFECT_TR_BLOOD.eent_eff_name)), oldorg, this.origin);
151
152 this.renderflags = 0;
153
154 // make gibs die faster at low view quality
155 // if view_quality is 0.5, we want to have them die twice as fast
156 this.nextthink -= frametime * (1 / bound(0.01, view_quality, 1.00) - 1);
157
158 this.alpha = bound(0, this.nextthink - time, 1);
159
160 if(this.alpha < ALPHA_MIN_VISIBLE)
161 {
162 this.drawmask = 0;
163 Gib_Delete(this);
164 }
165}
166
167void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent)
168{
169 entity gib;
170
171 // TODO remove some gibs according to cl_nogibs
172 gib = ListNewChildRubble(CasingsNGibs, new(gib));
174 gib.gravity = 1;
175 gib.solid = SOLID_CORPSE;
176 gib.cnt = specnum;
177 gib.silent = issilent;
178 gib.colormap = 4; // red
179 gib.colormap |= BIT(10); // RENDER_COLORMAPPED
180 Gib_setmodel(gib, mdlname, specnum);
181
182 setsize (gib, '-8 -8 -8', '8 8 8');
183
184 gib.draw = Gib_Draw;
185 IL_PUSH(g_drawables, gib);
186 if(destroyontouch)
187 settouch(gib, Gib_Touch);
188 else
190
191 // don't spawn gibs inside solid - just don't
192 if(org != safeorg)
193 {
194 tracebox(safeorg, gib.mins, gib.maxs, org, MOVE_NOMONSTERS, gib);
196 }
197
198 setorigin(gib, org);
200 gib.avelocity = prandomvec() * vlen(gib.velocity) * autocvar_cl_gibs_avelocity_scale;
201 gib.move_time = time;
202 gib.damageforcescale = autocvar_cl_gibs_damageforcescale;
203
204 gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
205 gib.drawmask = MASK_NORMAL;
206
208}
209
210NET_HANDLE(net_gibsplash, bool isNew)
211{
212 Net_Accept(net_gibsplash);
213
214 string gentle_prefix = "morphed_";
215
216 int type = ReadByte(); // gibbage type
217 int amount = ReadByte() / 16.0; // gibbage amount
218 vector org;
219 org.x = ReadShort() * 4 + 2;
220 org.y = ReadShort() * 4 + 2;
221 org.z = ReadShort() * 4 + 2;
222 vector vel = decompressShortVector(ReadShort());
223
224 return = true;
225
227 type |= 0x80; // set gentle bit
228
229 if(type & 0x80)
230 {
232 gentle_prefix = "";
233 else if(autocvar_cl_gentle_gibs == 3)
234 gentle_prefix = "happy_";
235 }
237 {
238 type |= 0x80;
239 gentle_prefix = "particlegibs_";
240 }
241
243 amount *= 1 - autocvar_cl_nogibs;
244
245 if(autocvar_ekg)
246 amount *= 5;
247
248 if(amount <= 0 || !isNew)
249 {
250 delete(this);
251 return;
252 }
253
254 setorigin(this, org); // for the sounds
255
256 int specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)
257 bool issilent = (type & 0x40);
258 type &= 0x87; // remove the species bits: bit 7 = gentle, bit 0,1,2 = kind of gib
259 string specstr = species_prefix(specnum);
260
261 switch(type)
262 {
263 case 0x01:
264 if(!issilent)
265 sound (this, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
266
267 if(prandom() < amount)
268 TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
269 new_te_bloodshower(_particleeffectnum(strcat(specstr, "bloodshower")), org, 1200, amount);
270 if(prandom() < amount)
271 TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent);
272
273 for(int c = 0; c < amount; ++c)
274 {
275 int randomvalue = amount - c;
276
277 if(prandom() < randomvalue)
278 TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
279 if(prandom() < randomvalue)
280 TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
281 if(prandom() < randomvalue)
282 TossGib ("models/gibs/chest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
283 if(prandom() < randomvalue)
284 TossGib ("models/gibs/smallchest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
285 if(prandom() < randomvalue)
286 TossGib ("models/gibs/leg1.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
287 if(prandom() < randomvalue)
288 TossGib ("models/gibs/leg2.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
289
290 // these splat on impact
291 if(prandom() < randomvalue)
292 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
293 if(prandom() < randomvalue)
294 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
295 if(prandom() < randomvalue)
296 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
297 if(prandom() < randomvalue)
298 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
299 }
300 break;
301 case 0x02:
302 __pointparticles(_particleeffectnum(strcat(specstr, "blood")), org, vel, amount * 16);
303 break;
304 case 0x03:
305 if(prandom() < amount)
306 TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization?
307 break;
308 case 0x81:
309 __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);
310 break;
311 case 0x82:
312 __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_hit")), org, vel, amount * 16);
313 break;
314 case 0x83:
315 // no gibs in gentle mode, sorry
316 break;
317 }
318 delete(this);
319}
320#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
float cnt
Definition powerups.qc:24
vector colormod
Definition powerups.qc:21
float alpha
Definition items.qc:13
float gravity
Definition items.qh:17
IntrusiveList g_drawables
Definition main.qh:91
float view_quality
Definition main.qh:174
float renderflags
Definition main.qh:111
const float ALPHA_MIN_VISIBLE
Definition main.qh:158
#define setmodel(this, m)
Definition model.qh:26
float compressShortVector(vector vec)
Definition util.qc:519
vector decompressShortVector(int data)
Definition util.qc:484
bool autocvar_cl_gentle
Definition util.qh:236
const int SPECIES_ROBOT_SOLID
Definition constants.qh:23
const int SPECIES_ROBOT_RUSTY
Definition constants.qh:26
const int SPECIES_ROBOT_SHINY
Definition constants.qh:27
const float MOVE_NOMONSTERS
float drawmask
float frametime
const float MASK_NORMAL
const float SOLID_CORPSE
float time
vector trace_endpos
float nextthink
float trace_dphitq3surfaceflags
vector origin
vector oldorigin
float Q3SURFACEFLAG_NOIMPACT
#define g_cts
Definition cts.qh:36
int state
bool silent
WriteByte(chan, ent.angles.y/DEC_FACTOR)
void Gib_setmodel(entity gib, string mdlname, int specnum)
Definition gibs.qc:79
string species_prefix(int specnum)
void Gib_Draw(entity this)
Definition gibs.qc:138
void Violence_GibSplash(entity source, float type, float amount, entity attacker)
Definition gibs.qc:53
void new_te_bloodshower(int ef, vector org, float explosionspeed, int howmany)
Definition gibs.qc:107
void TossGib(string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent)
Definition gibs.qc:167
bool Violence_GibSplash_SendEntity(entity this, entity to, int sf)
Definition gibs.qc:9
void Gib_Delete(entity this)
Definition gibs.qc:72
void Gib_Touch(entity this, entity toucher)
Definition gibs.qc:121
void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker)
Definition gibs.qc:23
void SUB_RemoveOnNoImpact(entity this, entity toucher)
Definition gibs.qc:115
float autocvar_cl_gibs_ticrate
Definition gibs.qh:13
int autocvar_cl_gentle_gibs
Definition gibs.qh:8
bool autocvar_cl_gibs_sloppy
Definition gibs.qh:12
float autocvar_cl_gibs_lifetime
Definition gibs.qh:10
float autocvar_cl_gibs_damageforcescale
Definition gibs.qh:9
bool autocvar_cl_nogibs
Definition gibs.qh:18
bool autocvar_cl_particlegibs
Definition gibs.qh:19
float autocvar_cl_gibs_velocity_up
Definition gibs.qh:17
int autocvar_cl_gibs_maxcount
Definition gibs.qh:11
float autocvar_cl_gibs_velocity_scale
Definition gibs.qh:15
int autocvar_ekg
Definition gibs.qh:4
float autocvar_cl_particles_quality
Definition gibs.qh:20
float autocvar_cl_gibs_avelocity_scale
Definition gibs.qh:16
float autocvar_cl_gibs_velocity_random
Definition gibs.qh:14
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define NET_HANDLE(id, param)
Definition net.qh:15
#define WriteHeader(to, id)
Definition net.qh:265
int ReadByte()
#define REGISTER_NET_TEMP(id)
Definition net.qh:31
float MSG_ONE
Definition menudefs.qc:56
float bound(float min, float value, float max)
float vlen(vector v)
void WriteShort(float data, float dest, float desto)
vector randomvec(void)
float floor(float f)
float MSG_BROADCAST
Definition menudefs.qc:55
#define etof(e)
Definition misc.qh:25
Model MDL_GIB_ROBO_RANDOM()
Definition all.inc:132
void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)
Definition movetypes.qc:835
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:66
#define NULL
Definition post.qh:14
entity msg_entity
Definition progsdefs.qc:63
float scale
Definition projectile.qc:14
float prandom()
Predictable random number generator (not seeded yet).
Definition random.qc:108
vector prandomvec()
Definition random.qc:120
void LimitedChildrenRubble(IntrusiveList list, string cname, int limit, void(entity) deleteproc, entity parent)
Definition rubble.qc:5
entity ListNewChildRubble(IntrusiveList list, entity child)
Definition rubble.qc:46
IntrusiveList CasingsNGibs
Definition rubble.qh:8
#define gettouch(e)
Definition self.qh:78
vector
Definition self.qh:96
vector org
Definition self.qh:96
entity entity toucher
Definition self.qh:76
#define settouch(e, f)
Definition self.qh:77
int dir
Definition impulse.qc:89
const int CH_PAIN
Definition sound.qh:18
const float VOL_BASE
Definition sound.qh:36
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
Sound SND_GIB_SPLAT_RANDOM()
Definition all.inc:215
bool sound_allowed(int to, entity e)
Definition all.qc:9
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52