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