]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/client/gibs.qc
Include gmqcc binaries for Windows and Linux
[voretournament/voretournament.git] / data / qcsrc / client / gibs.qc
1 .float silent;\r
2 \r
3 void Gib_Delete()\r
4 {\r
5         remove(self);\r
6 }\r
7 \r
8 string species_prefix(float specnum)\r
9 {\r
10         switch(specnum)\r
11         {\r
12                 case SPECIES_HUMAN:       return "";\r
13                 case SPECIES_ALIEN:       return "alien_";\r
14                 case SPECIES_ROBOT_SHINY: return "robot_";\r
15                 case SPECIES_ROBOT_RUSTY: return "robot_"; // use the same effects, only different gibs\r
16                 case SPECIES_ROBOT_SOLID: return "robot_"; // use the same effects, only different gibs\r
17                 case SPECIES_ANIMAL:      return "animal_";\r
18                 case SPECIES_RESERVED:    return "reserved_";\r
19                 default:         return "";\r
20         }\r
21 }\r
22 \r
23 void Gib_setmodel(entity gib, string mdlname, float specnum)\r
24 {\r
25         switch(specnum)\r
26         {\r
27                 case SPECIES_ROBOT_RUSTY:\r
28                 case SPECIES_ROBOT_SHINY:\r
29                 case SPECIES_ROBOT_SOLID:\r
30                         if(specnum != SPECIES_ROBOT_SOLID || mdlname == "models/gibs/chunk.mdl")\r
31                         {\r
32                                 if(mdlname == "models/gibs/bloodyskull.md3")\r
33                                         setmodel(gib, "models/gibs/robo.md3");\r
34                                 else\r
35                                         setmodel(gib, strcat("models/gibs/robo", ftos(floor(random() * 8) + 1), ".md3"));\r
36                                 if(specnum == SPECIES_ROBOT_SHINY)\r
37                                 {\r
38                                         gib.skin = 1;\r
39                                         gib.colormod = '2 2 2';\r
40                                 }\r
41                                 break;\r
42                         }\r
43                 default:\r
44                         setmodel(gib, mdlname);\r
45                         gib.skin = specnum;\r
46                         break;\r
47         }\r
48 }\r
49 \r
50 void new_te_bloodshower (float ef, vector org, float explosionspeed, float howmany)\r
51 {\r
52         float i, pmod;\r
53         pmod = cvar("cl_particles_quality");\r
54         for (i = 0; i < 50 * pmod; ++i)\r
55                 pointparticles(ef, org, randomvec() * explosionspeed, howmany / 50);\r
56 }\r
57 \r
58 void SUB_RemoveOnNoImpact()\r
59 {\r
60         if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)\r
61                 Gib_Delete();\r
62 }\r
63 \r
64 void Gib_Touch()\r
65 {\r
66         // TODO maybe bounce of walls, make more gibs, etc.\r
67 \r
68         if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)\r
69         {\r
70                 Gib_Delete();\r
71                 return;\r
72         }\r
73 \r
74         if(!self.silent)\r
75         {\r
76                 float vol;\r
77                 vol = VOL_BASE;\r
78                 if(self.scale) // sound volume dependent on gib size\r
79                         vol *= self.scale;\r
80                 vol = bound(0, vol, 1);\r
81 \r
82                 sound(self, CHAN_PAIN, strcat("misc/gib_splat0", ftos(floor(prandom() * 4 + 1)), ".wav"), vol, ATTN_NORM);\r
83         }\r
84         pointparticles(particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10);\r
85 \r
86         Gib_Delete();\r
87 }\r
88 \r
89 void Gib_Draw()\r
90 {\r
91         vector oldorg;\r
92         oldorg = self.origin;\r
93 \r
94         Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);\r
95         if(wasfreed(self))\r
96                 return;\r
97 \r
98         if(self.touch == Gib_Touch) // don't do this for the "chunk" thingie...\r
99                 trailparticles(self, particleeffectnum(strcat(species_prefix(self.cnt), "TR_SLIGHTBLOOD")), oldorg, self.origin);\r
100         else\r
101                 trailparticles(self, particleeffectnum(strcat(species_prefix(self.cnt), "TR_BLOOD")), oldorg, self.origin);\r
102 \r
103         self.renderflags = 0;\r
104         self.alpha = bound(0, self.nextthink - time, 1);\r
105 \r
106         if(self.alpha < ALPHA_MIN_VISIBLE)\r
107                 Gib_Delete();\r
108         else\r
109                 R_AddEntity(self);\r
110 }\r
111 \r
112 void TossGib (string mdlname, vector org, vector vconst, vector vrand, float specnum, float sz, float destroyontouch, float issilent)\r
113 {\r
114         entity gib;\r
115 \r
116         // TODO remove some gibs according to cl_nogibs\r
117         gib = RubbleNew("gib");\r
118         gib.move_movetype = MOVETYPE_BOUNCE;\r
119         gib.gravity = 1;\r
120         gib.solid = SOLID_CORPSE;\r
121         gib.cnt = specnum;\r
122         gib.silent = issilent;\r
123         Gib_setmodel(gib, mdlname, specnum);\r
124 \r
125         setsize (gib, '-8 -8 -8', '8 8 8');\r
126         gib.scale = sz;\r
127 \r
128         gib.draw = Gib_Draw;\r
129         if(destroyontouch)\r
130                 gib.move_touch = Gib_Touch;\r
131         else\r
132                 gib.move_touch = SUB_RemoveOnNoImpact;\r
133 \r
134         gib.move_origin = gib.origin = org;\r
135         gib.move_velocity = vconst * cvar_or("cl_gibs_velocity_scale", 1) + vrand * cvar_or("cl_gibs_velocity_random", 1) + '0 0 1' * cvar("cl_gibs_velocity_up");\r
136         gib.move_avelocity = prandomvec() * vlen(gib.move_velocity);\r
137         gib.move_time = time;\r
138         gib.damageforcescale = cvar_or("cl_gibs_damageforcescale", 3.5);\r
139 \r
140         gib.nextthink = time + cvar_or("cl_gibs_lifetime", 14) * (1 + prandom() * 0.15);\r
141 \r
142         RubbleLimit("gib", cvar_or("cl_gibs_maxcount",100), Gib_Delete);\r
143 }\r
144 \r
145 void Ent_GibSplash(float isNew)\r
146 {\r
147         float amount, type, specnum, sz;\r
148         vector org, vel;\r
149         string specstr;\r
150         float issilent;\r
151         string gentle_prefix;\r
152 \r
153         float c, randomvalue;\r
154 \r
155         type = ReadByte(); // gibbage type\r
156         amount = ReadByte() / 16.0; // gibbage amount\r
157         org_x = ReadShort() * 4 + 2;\r
158         org_y = ReadShort() * 4 + 2;\r
159         org_z = ReadShort() * 4 + 2;\r
160         vel = decompressShortVector(ReadShort());\r
161         sz = ReadCoord();\r
162 \r
163         if(cvar("cl_gentle"))\r
164                 type |= 0x80; // set gentle bit\r
165 \r
166         if(type & 0x80)\r
167         {\r
168                 if(cvar("cl_gentle") > 1)\r
169                         gentle_prefix = "";\r
170                 else\r
171                         gentle_prefix = "morphed_";\r
172         }\r
173         else if(cvar("cl_particlegibs"))\r
174         {\r
175                 type |= 0x80;\r
176                 gentle_prefix = "particlegibs_";\r
177         }\r
178 \r
179         if not(cvar("cl_gentle"))\r
180                 amount *= 1 - cvar("cl_nogibs");\r
181 \r
182         if(cvar("ekg"))\r
183                 amount *= 5;\r
184 \r
185         if(amount <= 0 || !isNew)\r
186                 return;\r
187 \r
188         self.origin = org; // for the sounds\r
189 \r
190         specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)\r
191         issilent = (type & 0x40);\r
192         type = type & 0x87; // remove the species bits: bit 7 = gentle, bit 0,1,2 = kind of gib\r
193         specstr = species_prefix(specnum);\r
194 \r
195         switch(type)\r
196         {\r
197                 case 0x01:\r
198                         if(!issilent)\r
199                         {\r
200                                 float vol;\r
201                                 vol = VOL_BASE;\r
202                                 if(sz) // sound volume dependent on gib size\r
203                                         vol *= sz;\r
204                                 vol = bound(0, vol, 1);\r
205 \r
206                                 sound (self, CHAN_PAIN, "misc/gib.wav", vol, ATTN_NORM);\r
207                         }\r
208 \r
209                         if(prandom() < amount)\r
210                                 TossGib ("models/gibs/eye.md3", org, vel, prandomvec() * 150, specnum, sz, 0, issilent);\r
211                         new_te_bloodshower(particleeffectnum(strcat(specstr, "bloodshower")), org, 1200, amount);\r
212                         if(prandom() < amount)\r
213                                 TossGib ("models/gibs/bloodyskull.md3", org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, sz, 0, issilent);\r
214 \r
215                         for(c = 0; c < amount; ++c)\r
216                         {\r
217                                 randomvalue = amount - c;\r
218 \r
219                                 if(prandom() < randomvalue)\r
220                                         TossGib ("models/gibs/arm.md3", org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,sz,0, issilent);\r
221                                 if(prandom() < randomvalue)\r
222                                         TossGib ("models/gibs/arm.md3", org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,sz,0, issilent);\r
223                                 if(prandom() < randomvalue)\r
224                                         TossGib ("models/gibs/chest.md3", org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,sz,0, issilent);\r
225                                 if(prandom() < randomvalue)\r
226                                         TossGib ("models/gibs/smallchest.md3", org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,sz,0, issilent);\r
227                                 if(prandom() < randomvalue)\r
228                                         TossGib ("models/gibs/leg1.md3", org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,sz,0, issilent);\r
229                                 if(prandom() < randomvalue)\r
230                                         TossGib ("models/gibs/leg2.md3", org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,sz,0, issilent);\r
231 \r
232                                 // these splat on impact\r
233                                 if(prandom() < randomvalue)\r
234                                         TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,sz,1, issilent);\r
235                                 if(prandom() < randomvalue)\r
236                                         TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,sz,1, issilent);\r
237                                 if(prandom() < randomvalue)\r
238                                         TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,sz,1, issilent);\r
239                                 if(prandom() < randomvalue)\r
240                                         TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,sz,1, issilent);\r
241                         }\r
242                         break;\r
243                 case 0x02:\r
244                         pointparticles(particleeffectnum(strcat(specstr, "blood")), org, vel, amount * 16);\r
245                         break;\r
246                 case 0x03:\r
247                         if(prandom() < amount)\r
248                                 TossGib ("models/gibs/chunk.mdl", org, vel, prandomvec() * (prandom() * 30 + 20), specnum, sz, 1, issilent); // TODO maybe adjust to more randomization?\r
249                         break;\r
250                 case 0x81:\r
251                         pointparticles(particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);\r
252                         break;\r
253                 case 0x82:\r
254                         pointparticles(particleeffectnum(strcat(gentle_prefix, "damage_hit")), org, vel, amount * 16);\r
255                         break;\r
256                 case 0x83:\r
257                         // no gibs in gentle mode, sorry\r
258                         break;\r
259         }\r
260 }\r
261 \r
262 void GibSplash_Precache()\r
263 {\r
264         precache_model("models/gibs/chunk.mdl");\r
265         precache_model("models/gibs/leg1.md3");\r
266         precache_model("models/gibs/leg2.md3");\r
267         precache_model("models/gibs/chest.md3");\r
268         precache_model("models/gibs/smallchest.md3");\r
269         precache_model("models/gibs/arm.md3");\r
270         precache_model("models/gibs/bloodyskull.md3");\r
271         precache_model("models/gibs/eye.md3");\r
272 \r
273         precache_model("models/gibs/robo.md3");\r
274         precache_model("models/gibs/robo1.md3");\r
275         precache_model("models/gibs/robo2.md3");\r
276         precache_model("models/gibs/robo3.md3");\r
277         precache_model("models/gibs/robo4.md3");\r
278         precache_model("models/gibs/robo5.md3");\r
279         precache_model("models/gibs/robo6.md3");\r
280         precache_model("models/gibs/robo7.md3");\r
281         precache_model("models/gibs/robo8.md3");\r
282 \r
283         precache_sound ("misc/gib.wav");\r
284     precache_sound ("misc/gib_splat01.wav");\r
285     precache_sound ("misc/gib_splat02.wav");\r
286     precache_sound ("misc/gib_splat03.wav");\r
287     precache_sound ("misc/gib_splat04.wav");\r
288 }\r