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
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)
void WriteByte(float data, float dest, float desto)
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:67
#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:74
vector
Definition self.qh:92
vector org
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
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