fix crosshair effects
[divverent/nexuiz.git] / data / qcsrc / client / damage.qc
1 .float silent;
2
3 void Ent_DamageInfo(float isNew)
4 {
5         float hittype, dmg, rad, edge, thisdmg, forcemul;
6         float issilent;
7         vector force, org, thisforce;
8         entity oldself;
9
10         oldself = self;
11
12         hittype = ReadShort();
13
14         issilent = (hittype & 0x8000);
15         hittype = (hittype & 0x7FFF);
16
17         org_x = ReadCoord();
18         org_y = ReadCoord();
19         org_z = ReadCoord();
20
21         dmg = ReadByte();
22         rad = ReadByte();
23         edge = ReadByte();
24         force = decompressShortVector(ReadShort());
25
26         if not(isNew)
27                 return;
28
29         if(rad < 0)
30         {
31                 rad = -rad;
32                 forcemul = -1;
33         }
34         else
35                 forcemul = 1;
36         
37         for(self = findradius(org, rad); self; self = self.chain)
38         {
39                 if(rad)
40                 {
41                         thisdmg = vlen(self.origin - org) / rad;
42                         if(thisdmg >= 1)
43                                 continue;
44                         if(dmg)
45                         {
46                                 thisdmg = dmg + (edge - dmg) * thisdmg;
47                                 thisforce = forcemul * vlen(force) * (thisdmg / dmg) * normalize(self.origin - org);
48                         }
49                         else
50                         {
51                                 thisdmg = 0;
52                                 thisforce = forcemul * vlen(force) * normalize(self.origin - org);
53                         }
54                 }
55                 else
56                 {
57                         thisdmg = dmg;
58                         thisforce = forcemul * force;
59                 }
60
61                 //print("check ", ftos(num_for_edict(self)), " ", self.classname, "\n");
62                 //print(ftos(self.damageforcescale), "\n");
63                 //print(vtos(thisforce), "\n");
64                 if(self.damageforcescale)
65                         if(vlen(thisforce))
66                         {
67                                 self.move_velocity = self.move_velocity + self.damageforcescale * thisforce;
68                                 self.move_flags &~= FL_ONGROUND;
69                                 //print("pushed ", ftos(num_for_edict(self)), " loose\n");
70                         }
71
72                 if(issilent)
73                         self.silent = 1;
74
75                 if(self.event_damage)
76                         self.event_damage(thisdmg, hittype, org, thisforce);
77         }
78
79         self = oldself;
80
81         // TODO spawn particle effects and sounds based on hittype
82         
83         if(!DEATH_ISSPECIAL(hittype))
84         {
85                 float hitwep, secondary, bounce, headshot;
86                 vector org2, backoff;
87                 float r;
88
89                 hitwep = DEATH_WEAPONOFWEAPONDEATH(hittype);
90                 secondary = hittype & HITTYPE_SECONDARY;
91                 bounce = hittype & HITTYPE_BOUNCE;
92                 headshot = hittype & HITTYPE_HEADSHOT;
93                 r = prandom();
94
95                 traceline(org - normalize(force) * 16, org + normalize(force) * 16, MOVE_NOMONSTERS, world);
96                 if(trace_fraction < 1 && hitwep != WEP_NEX && hitwep != WEP_MINSTANEX)
97                         backoff = trace_plane_normal;
98                 else
99                         backoff = -1 * normalize(force);
100
101                 setorigin(self, org + backoff * 2); // for sound() calls
102
103                 switch(hitwep)
104                 {
105                         case WEP_LASER:
106                                 org2 = org + backoff * 6;
107                                 pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1);
108                                 if(!issilent)
109                                         sound(self, CHAN_PROJECTILE, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
110                                 break;
111                         case WEP_SHOTGUN:
112                                 org2 = org + backoff * 2;
113                                 pointparticles(particleeffectnum("shotgun_impact"), org2, backoff * 1000, 1);
114                                 if(!issilent)
115                                 {
116                                         if(r < 0.05)
117                                                 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
118                                         else if(r < 0.1)
119                                                 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
120                                         else if(r < 0.2)
121                                                 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
122                                 }
123                                 break;
124                         case WEP_UZI:
125                                 org2 = org + backoff * 2;
126                                 pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1);
127                                 if(!issilent)
128                                         if(r < 0.05)
129                                                 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
130                                         else if(r < 0.1)
131                                                 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
132                                         else if(r < 0.2)
133                                                 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
134                                 break;
135                         case WEP_GRENADE_LAUNCHER:
136                                 org2 = org + backoff * 12;
137                                 pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
138                                 if(!issilent)
139                                         sound(self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
140                                 break;
141                         case WEP_ELECTRO:
142                                 org2 = org + backoff * 6;
143                                 if(secondary)
144                                 {
145                                         pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1);
146                                         if(!issilent)
147                                                 sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
148                                 }
149                                 else
150                                 {
151                                         if(bounce)
152                                         {
153                                                 // this is sent as "primary bounce" to distinguish it from secondary bounced balls
154                                                 pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1);
155                                                 if(!issilent)
156                                                         sound(self, CHAN_PROJECTILE, "weapons/electro_impact_combo.wav", VOL_BASE, ATTN_NORM);
157                                         }
158                                         else
159                                         {
160                                                 pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1);
161                                                 if(!issilent)
162                                                         sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
163                                         }
164                                 }
165                                 break;
166                         case WEP_CRYLINK:
167                                 org2 = org + backoff * 2;
168                                 if(secondary)
169                                 {
170                                         pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1);
171                                         if(!issilent)
172                                                 sound(self, CHAN_PROJECTILE, "weapons/crylink_impact2.wav", VOL_BASE, ATTN_NORM);
173                                 }
174                                 else
175                                 {
176                                         pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1);
177                                         if(!issilent)
178                                                 sound(self, CHAN_PROJECTILE, "weapons/crylink_impact.wav", VOL_BASE, ATTN_NORM);
179                                 }
180                                 break;
181                         case WEP_NEX:
182                                 org2 = org + backoff * 6;
183                                 pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
184                                 if(!issilent)
185                                         sound(self, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
186                                 break;
187                         case WEP_HAGAR:
188                                 org2 = org + backoff * 6;
189                                 pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
190                                 if(!issilent)
191                                 {
192                                         if (r<0.15)
193                                                 sound(self, CHAN_PROJECTILE, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM);
194                                         else if (r<0.7)
195                                                 sound(self, CHAN_PROJECTILE, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM);
196                                         else
197                                                 sound(self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
198                                 }
199                                 break;
200                         case WEP_ROCKET_LAUNCHER:
201                                 org2 = org + backoff * 12;
202                                 pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
203                                 if(!issilent)
204                                         sound(self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
205                                 break;
206                         case WEP_PORTO:
207                                 print("Since when does Porto send DamageInfo?\n");
208                                 break;
209                         case WEP_MINSTANEX:
210                                 org2 = org + backoff * 6;
211                                 pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
212                                 if(!issilent)
213                                         sound(self, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
214                                 break;
215                         case WEP_HOOK:
216                                 org2 = org + backoff * 2;
217                                 pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1);
218                                 if(!issilent)
219                                         sound(self, CHAN_PROJECTILE, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM);
220                                 break;
221                         case WEP_HLAC:
222                                 org2 = org + backoff * 6;
223                                 pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1);
224                                 if(!issilent)
225                                         sound(self, CHAN_PROJECTILE, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
226                                 break;
227                         case WEP_CAMPINGRIFLE:
228                                 org2 = org + backoff * 2;
229                                 pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1);
230                                 if(!issilent)
231                                 {
232                                         if(r < 0.2)
233                                                 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
234                                         else if(r < 0.4)
235                                                 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
236                                         else if(r < 0.5)
237                                                 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
238                                 }
239                                 break;
240                         case WEP_TUBA:
241                                 break;
242                         case WEP_FIREBALL:
243                                 if(secondary)
244                                 {
245                                         org2 = org + backoff * 16;
246                                         pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1);
247                                         if(!issilent)
248                                                 sound(self, CHAN_PROJECTILE, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM * 0.25); // long range boom
249                                 }
250                                 else
251                                 {
252                                         // firemine goes out silently
253                                 }
254                                 break;
255                         default:
256                                 dprint("Unhandled damage of weapon ", ftos(hitwep), "\n");
257                                 break;
258                 }
259         }
260 }
261
262 void DamageInfo_Precache()
263 {
264         precache_sound("weapons/crylink_impact2.wav");
265         precache_sound("weapons/crylink_impact.wav");
266         precache_sound("weapons/electro_impact.wav");
267         precache_sound("weapons/electro_impact_combo.wav");
268         precache_sound("weapons/grenade_impact.wav");
269         precache_sound("weapons/hagexp1.wav");
270         precache_sound("weapons/hagexp2.wav");
271         precache_sound("weapons/hagexp3.wav");
272         precache_sound("weapons/flacexp1.wav");
273         precache_sound("weapons/flacexp2.wav");
274         precache_sound("weapons/flacexp3.wav");
275         precache_sound("weapons/hookbomb_impact.wav");
276         precache_sound("weapons/laserimpact.wav");
277         precache_sound("weapons/neximpact.wav");
278         precache_sound("weapons/ric1.wav");
279         precache_sound("weapons/ric2.wav");
280         precache_sound("weapons/ric3.wav");
281         precache_sound("weapons/rocket_impact.wav");
282         precache_sound("weapons/fireball_impact.wav");
283         precache_sound("weapons/fireball_impact2.wav");
284 }