]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/tfcombat.c
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@767 f962a42d-fe04-0410-a3ab-8c8b0445ebaa
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / tfcombat.c
1 void () T_MissileTouch;\r
2 void () info_player_start;\r
3 void (entity targ, entity attacker) ClientObituary;\r
4 void (entity Goal, entity AP, float addb) DoResults;\r
5 float (entity Goal, entity AP) Activated;\r
6 float (entity targ, entity attacker, float damage) TeamEqualiseDamage;\r
7 \r
8 // Death MSG Caller\r
9 float deathmsg; // Gonna have to make this work with NexTF's\r
10 \r
11 //compiler-satisfying vars (Add these to defs)\r
12 .void() th_die;                                                                 // Note to self: figure out wtf these 2 do\r
13 .void(entity attacker, float damage) th_pain;   ////\r
14 float skill;    // Skill level. Moot in NexTF (no SP, and bots use some other var)\r
15 .float super_damage_finished; //quad damage over <- convert this to work with nex!\r
16 entity damage_attacker;\r
17 .float immune_to_check;         // as it says\r
18 float rj;       // not sure, really..\r
19 \r
20 \r
21 // COMBAT\r
22 void () monster_death_use =\r
23 {\r
24         local entity ent;\r
25         local entity otemp;\r
26         local entity stemp;\r
27 \r
28         if ((self.flags & 1))\r
29         {\r
30                 self.flags = (self.flags - 1);\r
31         }\r
32         if ((self.flags & 2))\r
33         {\r
34                 self.flags = (self.flags - 2);\r
35         }\r
36         if (!self.target)\r
37         {\r
38                 return;\r
39         }\r
40         activator = self.enemy;\r
41         SUB_UseTargets ();\r
42 };\r
43 \r
44 float (entity targ, entity inflictor) CanDamage =\r
45 {\r
46         if ((targ.movetype == 7))\r
47         {\r
48                 traceline (inflictor.origin, (0.5 * (targ.absmin + targ.absmax)), 1, self);\r
49                 if ((trace_fraction == 1))\r
50                 {\r
51                         return (1);\r
52                 }\r
53                 if ((trace_ent == targ))\r
54                 {\r
55                         return (1);\r
56                 }\r
57                 return (0);\r
58         }\r
59         traceline (inflictor.origin, targ.origin, 1, self);\r
60         if ((trace_fraction == 1))\r
61         {\r
62                 return (1);\r
63         }\r
64         traceline (inflictor.origin, (targ.origin + '15 15 0'), 1, self);\r
65         if ((trace_fraction == 1))\r
66         {\r
67                 return (1);\r
68         }\r
69         traceline (inflictor.origin, (targ.origin + '-15 -15 0'), 1, self);\r
70         if ((trace_fraction == 1))\r
71         {\r
72                 return (1);\r
73         }\r
74         traceline (inflictor.origin, (targ.origin + '-15 15 0'), 1, self);\r
75         if ((trace_fraction == 1))\r
76         {\r
77                 return (1);\r
78         }\r
79         traceline (inflictor.origin, (targ.origin + '15 -15 0'), 1, self);\r
80         if ((trace_fraction == 1))\r
81         {\r
82                 return (1);\r
83         }\r
84         return (0);\r
85 };\r
86 \r
87 void (entity targ, entity attacker) Killed =\r
88 {\r
89         local entity oself;\r
90         local string db;\r
91 \r
92         oself = self;\r
93         self = targ;\r
94         if ((self.health < -99))\r
95         {\r
96                 self.health = -99;\r
97         }\r
98         if (((self.movetype == 7) || (self.movetype == 0)))\r
99         {\r
100                 self.th_die ();\r
101                 self = oself;\r
102                 return;\r
103         }\r
104         if (self.classname == "building_tesla")\r
105         {\r
106                 self.th_die ();\r
107                 self = oself;\r
108                 return;\r
109         }\r
110         self.enemy = attacker;\r
111         if ((self.flags & 32))\r
112         {\r
113                 killed_monsters = (killed_monsters + 1);\r
114                 WriteByte (2, 27);\r
115         }\r
116 //      ClientObituary (self, attacker);                // causing crash :/\r
117 //      Obituary (attacker, targ, deathmsg);\r
118         self.takedamage = 0;\r
119         self.touch = SUB_Null;\r
120         monster_death_use ();\r
121 //      self.th_die ();\r
122 // (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force\r
123         PlayerKilled (0, targ, attacker, 0, deathmsg);\r
124         self = oself;\r
125 };\r
126 \r
127 void (entity targ, entity inflictor, entity attacker, float damage) T_Damage =\r
128 {\r
129         local vector dir;\r
130         local entity oldself;\r
131         local entity te;\r
132         local float save;\r
133         local float take;\r
134 \r
135         local float damagearmor;\r
136 \r
137         if (targ.team_no < 1 && targ.classname != "func_button" && targ.classname != "door" && targ.classname != "building_tesla")                      // TEMP\r
138         {                                                               ////\r
139                 return;                                         ////\r
140         }                                                               ////\r
141 \r
142         /*if (targ.classname == "building_tesla")\r
143         {\r
144                 targ.health = (targ.health - take);\r
145                 if ((targ.health <= 0))\r
146                 {\r
147                         Killed (targ, attacker);\r
148                 }\r
149                 return;\r
150         }*/\r
151         if (!targ.takedamage)\r
152         {\r
153                 return;\r
154         }\r
155         if ((attacker.classname == "player"))\r
156         {\r
157                 damage = (damage * 0.9);\r
158         }\r
159         if ((attacker.classname == "player"))\r
160         {\r
161                 if ((attacker.super_damage_finished > time))\r
162                 {\r
163                         damage = (damage * 4);\r
164                 }\r
165                 if (((targ.classname != "player") && (targ.classname != "bot") && (targ.classname != "building_tesla")))\r
166                 {\r
167                         if (!Activated (targ, attacker))\r
168                         {\r
169                                 if ((targ.else_goal != 0))\r
170                                 {\r
171                                         te = Findgoal (targ.else_goal);\r
172                                         if (te)\r
173                                         {\r
174                                                 AttemptToActivate (te, attacker, targ);\r
175                                         }\r
176                                 }\r
177                                 return;\r
178                         }\r
179                 }\r
180         }\r
181         damage_attacker = attacker;\r
182         if ((teamplay & (64 | 32)))\r
183         {\r
184                 damage = TeamEqualiseDamage (targ, attacker, damage);\r
185         }\r
186         save = ceil ((targ.armortype * damage));\r
187         if ((save >= targ.armorvalue))\r
188         {\r
189                 save = targ.armorvalue;\r
190                 targ.armortype = 0;\r
191                 targ.armorclass = 0;\r
192                 targ.items = (targ.items - (targ.items & ((8192 | 16384) | 32768)));\r
193         }\r
194 \r
195         targ.armorvalue = (targ.armorvalue - save);\r
196         take = ceil ((damage - save));\r
197         if ((targ.flags & 8))\r
198         {\r
199                 targ.dmg_take = (targ.dmg_take + take);\r
200                 targ.dmg_save = (targ.dmg_save + save);\r
201                 targ.dmg_inflictor = inflictor;\r
202         }\r
203         if (((inflictor != world) && (targ.movetype == 3)))\r
204         {\r
205                 targ.immune_to_check = (time + (damage / 20));\r
206                 dir = (targ.origin - ((inflictor.absmin + inflictor.absmax) * 0.5));\r
207                 dir = normalize (dir);\r
208                 if ((((damage < 60) & ((attacker.classname == "player") & (targ.classname == "player"))) & (attacker.netname != targ.netname)))\r
209                 {\r
210                         targ.velocity = (targ.velocity + ((dir * damage) * 11));\r
211                 }\r
212                 else\r
213                 {\r
214                         targ.velocity = (targ.velocity + ((dir * damage) * 8));\r
215                 }\r
216                 if ((((rj > 1) & ((attacker.classname == "player") & (targ.classname == "player"))) & (attacker.netname == targ.netname)))\r
217                 {\r
218                         targ.velocity = (targ.velocity + ((dir * damage) * rj));\r
219                 }\r
220         }\r
221         if ((targ.flags & 64))\r
222         {\r
223                 return;\r
224         }\r
225         if ((targ.invincible_finished >= time))\r
226         {\r
227                 if ((self.invincible_sound < time))\r
228                 {\r
229                         sound (targ, 3, "items/protect3.wav", 1, 1);\r
230                         self.invincible_sound = (time + 2);\r
231                 }\r
232                 return;\r
233         }\r
234         if (((attacker.classname == "player") && ((targ.classname == "player") || (targ.classname == "building_sentrygun"))))\r
235         {\r
236                 if ((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)))\r
237                 {\r
238                         if ((teamplay & 16))\r
239                         {\r
240                                 return;\r
241                         }\r
242                         else\r
243                         {\r
244                                 if ((teamplay & 8))\r
245                                 {\r
246                                         take = (take / 2);\r
247                                 }\r
248                         }\r
249                 }\r
250         }\r
251 \r
252         //                      MOVED HERE FROM PlayerDamage -- need to port the rest\r
253         // how much damage to deal to armor\r
254         damagearmor = bound(0, damage * 0.2 * (targ.armorvalue / 50) * cvar("g_balance_armor_takedamage"), targ.armorvalue);\r
255         // how much damage armor blocks\r
256         save = bound(0, damage * (targ.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
257         // how much damage to deal to player\r
258         take = bound(0, damage - save, damage);\r
259         targ.armorvalue = targ.armorvalue - damagearmor;\r
260         DelayArmorRegen(targ);\r
261 \r
262         if (((take < 1) && (take != 0)))\r
263         {\r
264                 take = 1;\r
265         }\r
266         targ.health = (targ.health - take);\r
267 \r
268         if (((attacker.classname == "player") && (((((((targ.classname == "player") || (targ.classname == "building_sentrygun")) || (targ.classname == "building_tesla")) || (targ.classname == "building_teleporter")) || (targ.classname == "building_camera")) || (targ.classname == "monster_helo")) || (targ.classname == "laser_drone"))))\r
269         {\r
270                 if ((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)))\r
271                 {\r
272                         if ((teamplay & 16))\r
273                         {\r
274                                 return;\r
275                         }\r
276                         else\r
277                         {\r
278                                 if ((teamplay & 8))\r
279                                 {\r
280                                         take = take / 2;\r
281                                 }\r
282                         }\r
283                 }\r
284         }\r
285 \r
286         if ((targ.armorvalue < 1))\r
287         {\r
288                 targ.armorclass = 0;\r
289                 targ.armorvalue = 0;\r
290         }\r
291         if ((targ.health <= 0))\r
292         {\r
293                 Killed (targ, attacker);\r
294                 return;\r
295         }\r
296         oldself = self;\r
297         self = targ;\r
298         if (self.th_pain)\r
299         {\r
300                 self.th_pain (attacker, take);\r
301                 if ((skill >= 3))\r
302                 {\r
303                         self.pain_finished = (time + 5);\r
304                 }\r
305         }\r
306         self = oldself;\r
307 };\r
308 \r
309 void (entity targ, entity inflictor, entity attacker, float damage, float T_flags, float T_AttackType) TF_T_Damage =\r
310 {\r
311         local vector dir;\r
312         local entity oldself;\r
313         local entity te;\r
314         local float save;\r
315         local float take;\r
316         local float olddmsg;\r
317         local float no_damage;\r
318         local float moment;\r
319 \r
320         if (targ.team_no < 1 && targ.classname != "func_button" && targ.classname != "door" && targ.classname != "building_tesla")                      // TEMP\r
321         {                                                               ////\r
322                 return;                                         ////\r
323         }                                                               ////\r
324         if ((targ.takedamage == 0))\r
325         {\r
326                 return;\r
327         }\r
328         if ((T_AttackType & 256))\r
329         {\r
330                 targ.health = damage;\r
331                 return;\r
332         }\r
333         /*if (cease_fire) // this aint needed\r
334         {\r
335                 return;\r
336         }*/\r
337         no_damage = 0;\r
338         if ((attacker.classname == "player"))\r
339         {\r
340                 damage = (damage * 0.9);\r
341                 if ((attacker.super_damage_finished > time))\r
342                 {\r
343                         damage = (damage * 4);\r
344                 }\r
345                 if ((((((((((((targ.classname != "player") && (targ.classname != "bot")) && (targ.classname != "building_tesla")) && (targ.classname != "building_sentrygun")) && (targ.classname != "building_dispenser")) && (targ.classname != "trip_bomb")) && (targ.classname != "building_teleporter")) && (targ.classname != "building_camera")) && (targ.classname != "probe")) && (targ.classname != "monster_helo")) && (targ.classname != "laser_drone")))\r
346                 {\r
347                         if (!Activated (targ, attacker))\r
348                         {\r
349                                 if ((targ.else_goal != 0))\r
350                                 {\r
351                                         te = Findgoal (targ.else_goal);\r
352                                         if (te)\r
353                                         {\r
354                                                 AttemptToActivate (te, attacker, targ);\r
355                                         }\r
356                                 }\r
357                                 return;\r
358                         }\r
359                 }\r
360         }\r
361         damage_attacker = attacker;\r
362         if ((teamplay & (64 | 32)))\r
363         {\r
364                 damage = TeamEqualiseDamage (targ, attacker, damage);\r
365         }\r
366         if (((targ.armorclass != 0) && (T_AttackType != 0)))\r
367         {\r
368                 if (((targ.armorclass & 1) && (T_AttackType & 1)))\r
369                 {\r
370                         damage = floor ((damage * 0.5));\r
371                 }\r
372                 if (((targ.armorclass & 2) && (T_AttackType & 2)))\r
373                 {\r
374                         damage = floor ((damage * 0.5));\r
375                 }\r
376                 if (((targ.armorclass & 4) && (T_AttackType & 4)))\r
377                 {\r
378                         damage = floor ((damage * 0.5));\r
379                 }\r
380                 if (((targ.armorclass & 8) && (T_AttackType & 8)))\r
381                 {\r
382                         damage = floor ((damage * 0.5));\r
383                 }\r
384                 if (((targ.armorclass & 16) && (T_AttackType & 16)))\r
385                 {\r
386                         damage = floor ((damage * 0.5));\r
387                 }\r
388         }\r
389         if ((T_flags & 1))\r
390         {\r
391                 take = damage;\r
392                 save = 0;\r
393         }\r
394         else\r
395         {\r
396                 save = ceil ((targ.armortype * damage));\r
397                 if ((((((attacker.classname == "player") && (targ.team_no > 0)) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
398                 {\r
399                         if ((T_AttackType & 4))\r
400                         {\r
401                                 if ((teamplay & 1024))\r
402                                 {\r
403                                         save = 0;\r
404                                 }\r
405                                 else\r
406                                 {\r
407                                         if ((teamplay & 512))\r
408                                         {\r
409                                                 save = (save / 2);\r
410                                         }\r
411                                 }\r
412                         }\r
413                         else\r
414                         {\r
415                                 if ((teamplay & 256))\r
416                                 {\r
417                                         save = 0;\r
418                                 }\r
419                                 else\r
420                                 {\r
421                                         if ((teamplay & 128))\r
422                                         {\r
423                                                 save = (save / 2);\r
424                                         }\r
425                                 }\r
426                         }\r
427                 }\r
428                 if ((save >= targ.armorvalue))\r
429                 {\r
430                         save = targ.armorvalue;\r
431                         targ.armortype = 0;\r
432                         targ.armorclass = 0;\r
433                         targ.items = (targ.items - (targ.items & ((8192 | 16384) | 32768)));\r
434                 }\r
435                 targ.armorvalue = (targ.armorvalue - save);\r
436                 take = ceil ((damage - save));\r
437         }\r
438         if ((targ.flags & 8))\r
439         {\r
440                 targ.dmg_take = (targ.dmg_take + take);\r
441                 targ.dmg_save = (targ.dmg_save + save);\r
442                 targ.dmg_inflictor = inflictor;\r
443         }\r
444         if ((((inflictor != world) && (targ.movetype == 3)) && !(targ.tfstate & 65536)))\r
445         {\r
446                 if ((deathmsg != 9))\r
447                 {\r
448                         targ.immune_to_check = (time + (damage / 20));\r
449                         dir = (targ.origin - ((inflictor.absmin + inflictor.absmax) * 0.5));\r
450                         dir = normalize (dir);\r
451                         /*if ((targ.class == 6)) // moot function -- NexTF doesnt have an HWGuy\r
452                         {\r
453                                 moment = (damage / 4);\r
454                                 if ((damage <= 50))\r
455                                 {\r
456                                         moment = 0;\r
457                                 }\r
458                         }\r
459                         else*/\r
460                         {\r
461                                 moment = damage;\r
462                         }\r
463                         if ((((moment < 60) && ((attacker.classname == "player") && (targ.classname == "player"))) && (attacker.netname != targ.netname)))\r
464                         {\r
465                                 targ.velocity = (targ.velocity + ((dir * moment) * 11));\r
466                         }\r
467                         else\r
468                         {\r
469                                 targ.velocity = (targ.velocity + ((dir * moment) * 8));\r
470                         }\r
471                         if ((((rj > 1) && ((attacker.classname == "player") && (targ.classname == "player"))) && (attacker.netname == targ.netname)))\r
472                         {\r
473                                 targ.velocity = (targ.velocity + ((dir * moment) * rj));\r
474                         }\r
475                 }\r
476         }\r
477         if ((targ.flags & 64))\r
478         {\r
479                 return;\r
480         }\r
481         if ((targ.invincible_finished >= time))\r
482         {\r
483                 if ((self.invincible_sound < time))\r
484                 {\r
485                         sound (targ, 3, "items/protect3.wav", 1, 1);\r
486                         self.invincible_sound = (time + 2);\r
487                 }\r
488                 return;\r
489         }\r
490 //      if (((attacker.classname == "player") && (((((targ.classname == "player") || (targ.classname == "building_sentrygun")) || (targ.classname == "building_dispenser")) || (targ.classname == "building_teleporter_entrance")) || (targ.classname == "building_teleporter_exit"))))\r
491         if (((attacker.classname == "player") && ((((((targ.classname == "player") || (targ.classname == "building_sentrygun")) || (targ.classname == "building_tesla")) || (targ.classname == "building_teleporter")) || (targ.classname == "building_camera")) || (targ.classname == "laser_drone"))))\r
492         {\r
493                 if (((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
494                 {\r
495                         if ((T_AttackType & 4))\r
496                         {\r
497                                 if ((teamplay & 16))\r
498                                 {\r
499                                         no_damage = 1;\r
500                                 }\r
501                                 else\r
502                                 {\r
503                                         if ((teamplay & 8))\r
504                                         {\r
505                                                 take = (take / 2);\r
506                                         }\r
507                                 }\r
508                         }\r
509                         else\r
510                         {\r
511                                 if ((teamplay & 4))\r
512                                 {\r
513                                         no_damage = 1;\r
514                                 }\r
515                                 else\r
516                                 {\r
517                                         if ((teamplay & 2))\r
518                                         {\r
519                                                 take = (take / 2);\r
520                                         }\r
521                                 }\r
522                         }\r
523                 }\r
524         }\r
525         if ((T_flags & 4))\r
526         {\r
527                 if ((targ == attacker))\r
528                 {\r
529                         return;\r
530                 }\r
531         }\r
532 \r
533         local float damagearmor;\r
534         //                      MOVED HERE FROM PlayerDamage -- need to port the rest\r
535         // how much damage to deal to armor\r
536         damagearmor = bound(0, damage * 0.2 * (targ.armorvalue / 50) * cvar("g_balance_armor_takedamage"), targ.armorvalue);\r
537         // how much damage armor blocks\r
538         save = bound(0, damage * (targ.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
539         // how much damage to deal to player\r
540         take = bound(0, damage - save, damage);\r
541         targ.armorvalue = targ.armorvalue - damagearmor;\r
542         DelayArmorRegen(targ);\r
543 \r
544         if ((take < 1))\r
545         {\r
546                 take = 1;\r
547         }\r
548         take = rint (take);\r
549         if ((no_damage == 0))\r
550         {\r
551                 targ.health = (targ.health - take);\r
552         }\r
553         if (((attacker.classname == "player") && (((((targ.classname == "player") || (targ.classname == "building_sentrygun")) || (targ.classname == "building_dispenser")) || (targ.classname == "building_teleporter_entrance")) || (targ.classname == "building_teleporter_exit"))))\r
554         {\r
555                 if (((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
556                 {\r
557                         olddmsg = deathmsg;\r
558                         if ((T_AttackType & 4))\r
559                         {\r
560                                 deathmsg = 37;\r
561                                 if ((teamplay & 16384))\r
562                                 {\r
563                                         TF_T_Damage (attacker, world, world, take, 1, 0);\r
564                                 }\r
565                                 else\r
566                                 {\r
567                                         if ((teamplay & 8192))\r
568                                         {\r
569                                                 TF_T_Damage (attacker, world, world, (take / 2), 1, 0);\r
570                                         }\r
571                                 }\r
572                         }\r
573                         else\r
574                         {\r
575                                 deathmsg = 37;\r
576                                 if ((teamplay & 4096))\r
577                                 {\r
578                                         TF_T_Damage (attacker, world, world, take, 1, 0);\r
579                                 }\r
580                                 else\r
581                                 {\r
582                                         if ((teamplay & 2048))\r
583                                         {\r
584                                                 TF_T_Damage (attacker, world, world, (take / 2), 1, 0);\r
585                                         }\r
586                                 }\r
587                         }\r
588                         deathmsg = olddmsg;\r
589                 }\r
590         }\r
591         if ((no_damage == 1))\r
592         {\r
593                 return;\r
594         }\r
595         if ((targ.armorvalue < 1))\r
596         {\r
597                 targ.armorclass = 0;\r
598                 targ.armorvalue = 0;\r
599         }\r
600         if ((targ.health <= 0))\r
601         {\r
602                 if ((((inflictor.classname == "detpack") && (inflictor.weaponmode == 1)) && (inflictor.enemy == targ)))\r
603                 {\r
604                         deathmsg = 16;\r
605                 }\r
606                 Killed (targ, attacker);\r
607                 return;\r
608         }\r
609         oldself = self;\r
610         self = targ;\r
611         if (self.th_pain)\r
612         {\r
613                 self.th_pain (attacker, take);\r
614                 if ((skill >= 3))\r
615                 {\r
616                         self.pain_finished = (time + 5);\r
617                 }\r
618         }\r
619         self = oldself;\r
620 };\r
621 \r
622 void (entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =\r
623 {\r
624         local float points;\r
625         local entity head;\r
626         local entity te;\r
627         local vector org;                                                       ////\r
628 \r
629         head = findradius (inflictor.origin, (damage + 40));\r
630         while (head)\r
631         {\r
632                 if ((head != ignore))\r
633                 {\r
634                         if (head.takedamage)\r
635                         {\r
636                                 org = (head.origin + ((head.mins + head.maxs) * 0.5));\r
637                                 points = (0.5 * vlen ((inflictor.origin - org)));\r
638                                 if ((points < 0))\r
639                                 {\r
640                                         points = 0;\r
641                                 }\r
642                                 points = (damage - points);\r
643                                 if ((head == attacker))\r
644                                 {\r
645                                         points = (points * 0.75);\r
646                                 }\r
647                                 if ((points > 0))\r
648                                 {\r
649                                         if (CanDamage (head, inflictor))\r
650                                         {\r
651                                                 if ((head.classname == "monster_shambler"))\r
652                                                 {\r
653                                                         T_Damage (head, inflictor, attacker, (points * 0.5));\r
654                                                 }\r
655                                                 else\r
656                                                 {\r
657                                                         TF_T_Damage (head, inflictor, attacker, points, 2, 4);\r
658                                                 }\r
659                                         }\r
660                                 }\r
661                         }\r
662                 }\r
663                 head = head.chain;\r
664         }\r
665 };\r