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;
141 oldorg = this.origin;
142
144 if(wasfreed(this))
145 return;
146
147 if(gettouch(this) == Gib_Touch) // don't do this for the "chunk" thingie...
148 // TODO somehow make it spray in a direction dependent on this.angles
149 __trailparticles(this, _particleeffectnum(strcat(species_prefix(this.cnt), EFFECT_TR_SLIGHTBLOOD.eent_eff_name)), oldorg, this.origin);
150 else
151 __trailparticles(this, _particleeffectnum(strcat(species_prefix(this.cnt), EFFECT_TR_BLOOD.eent_eff_name)), oldorg, this.origin);
152
153 this.renderflags = 0;
154
155 // make gibs die faster at low view quality
156 // if view_quality is 0.5, we want to have them die twice as fast
157 this.nextthink -= frametime * (1 / bound(0.01, view_quality, 1.00) - 1);
158
159 this.alpha = bound(0, this.nextthink - time, 1);
160
161 if(this.alpha < ALPHA_MIN_VISIBLE)
162 {
163 this.drawmask = 0;
164 Gib_Delete(this);
165 }
166}
167
168void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent)
169{
170 entity gib;
171
172 // TODO remove some gibs according to cl_nogibs
173 gib = ListNewChildRubble(CasingsNGibs, new(gib));
175 gib.gravity = 1;
176 gib.solid = SOLID_CORPSE;
177 gib.cnt = specnum;
178 gib.silent = issilent;
179 gib.colormap = 4; // red
180 gib.colormap |= BIT(10); // RENDER_COLORMAPPED
181 Gib_setmodel(gib, mdlname, specnum);
182
183 setsize (gib, '-8 -8 -8', '8 8 8');
184
185 gib.draw = Gib_Draw;
186 IL_PUSH(g_drawables, gib);
187 if(destroyontouch)
188 settouch(gib, Gib_Touch);
189 else
191
192 // don't spawn gibs inside solid - just don't
193 if(org != safeorg)
194 {
195 tracebox(safeorg, gib.mins, gib.maxs, org, MOVE_NOMONSTERS, gib);
197 }
198
199 setorigin(gib, org);
201 gib.avelocity = prandomvec() * vlen(gib.velocity) * autocvar_cl_gibs_avelocity_scale;
202 gib.move_time = time;
203 gib.damageforcescale = autocvar_cl_gibs_damageforcescale;
204
205 gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
206 gib.drawmask = MASK_NORMAL;
207
209}
210
211NET_HANDLE(net_gibsplash, bool isNew)
212{
213 Net_Accept(net_gibsplash);
214
215 string gentle_prefix = "morphed_";
216
217 int type = ReadByte(); // gibbage type
218 int amount = ReadByte() / 16.0; // gibbage amount
219 vector org;
220 org.x = ReadShort() * 4 + 2;
221 org.y = ReadShort() * 4 + 2;
222 org.z = ReadShort() * 4 + 2;
223 vector vel = decompressShortVector(ReadShort());
224
225 return = true;
226
228 type |= 0x80; // set gentle bit
229
230 if(type & 0x80)
231 {
233 gentle_prefix = "";
234 else if(autocvar_cl_gentle_gibs == 3)
235 gentle_prefix = "happy_";
236 }
238 {
239 type |= 0x80;
240 gentle_prefix = "particlegibs_";
241 }
242
244 amount *= 1 - autocvar_cl_nogibs;
245
246 if(autocvar_ekg)
247 amount *= 5;
248
249 if(amount <= 0 || !isNew)
250 {
251 delete(this);
252 return;
253 }
254
255 setorigin(this, org); // for the sounds
256
257 int specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)
258 bool issilent = (type & 0x40);
259 type = type & 0x87; // remove the species bits: bit 7 = gentle, bit 0,1,2 = kind of gib
260 string specstr = species_prefix(specnum);
261
262 switch(type)
263 {
264 case 0x01:
265 if(!issilent)
266 sound (this, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
267
268 if(prandom() < amount)
269 TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
270 new_te_bloodshower(_particleeffectnum(strcat(specstr, "bloodshower")), org, 1200, amount);
271 if(prandom() < amount)
272 TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent);
273
274 for(int c = 0; c < amount; ++c)
275 {
276 int randomvalue = amount - c;
277
278 if(prandom() < randomvalue)
279 TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
280 if(prandom() < randomvalue)
281 TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
282 if(prandom() < randomvalue)
283 TossGib ("models/gibs/chest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
284 if(prandom() < randomvalue)
285 TossGib ("models/gibs/smallchest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
286 if(prandom() < randomvalue)
287 TossGib ("models/gibs/leg1.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
288 if(prandom() < randomvalue)
289 TossGib ("models/gibs/leg2.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
290
291 // these splat on impact
292 if(prandom() < randomvalue)
293 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
294 if(prandom() < randomvalue)
295 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
296 if(prandom() < randomvalue)
297 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
298 if(prandom() < randomvalue)
299 TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
300 }
301 break;
302 case 0x02:
303 __pointparticles(_particleeffectnum(strcat(specstr, "blood")), org, vel, amount * 16);
304 break;
305 case 0x03:
306 if(prandom() < amount)
307 TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization?
308 break;
309 case 0x81:
310 __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);
311 break;
312 case 0x82:
313 __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_hit")), org, vel, amount * 16);
314 break;
315 case 0x83:
316 // no gibs in gentle mode, sorry
317 break;
318 }
319 delete(this);
320}
321#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:521
vector decompressShortVector(int data)
Definition util.qc:486
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:168
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 Net_Accept(classname)
Definition net.qh:201
#define WriteHeader(to, id)
Definition net.qh:221
int ReadByte()
#define REGISTER_NET_TEMP(id)
Definition net.qh:28
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:121
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:50