]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/tfcombat.c
Added new GameC with class selection and random class selection working
[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         self.enemy = attacker;\r
105         if ((self.flags & 32))\r
106         {\r
107                 killed_monsters = (killed_monsters + 1);\r
108                 WriteByte (2, 27);\r
109         }\r
110 //      ClientObituary (self, attacker);                // causing crash :/\r
111 //      Obituary (attacker, targ, deathmsg);\r
112         self.takedamage = 0;\r
113         self.touch = SUB_Null;\r
114         monster_death_use ();\r
115 //      self.th_die ();\r
116 // (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force\r
117         PlayerKilled (0, targ, attacker, 0, deathmsg);\r
118         self = oself;\r
119 };\r
120 \r
121 void (entity targ, entity inflictor, entity attacker, float damage) T_Damage =\r
122 {\r
123         local vector dir;\r
124         local entity oldself;\r
125         local entity te;\r
126         local float save;\r
127         local float take;\r
128 \r
129         local float damagearmor;\r
130 \r
131         if (targ.team_no < 1 && targ.classname != "func_button" && targ.classname != "door")                    // TEMP\r
132         {                                                               ////\r
133                 return;                                         ////\r
134         }                                                               ////\r
135 \r
136         if (!targ.takedamage)\r
137         {\r
138                 return;\r
139         }\r
140         if ((attacker.classname == "player"))\r
141         {\r
142                 damage = (damage * 0.9);\r
143         }\r
144         if ((attacker.classname == "player"))\r
145         {\r
146                 if ((attacker.super_damage_finished > time))\r
147                 {\r
148                         damage = (damage * 4);\r
149                 }\r
150                 if (((targ.classname != "player") && (targ.classname != "bot")))\r
151                 {\r
152                         if (!Activated (targ, attacker))\r
153                         {\r
154                                 if ((targ.else_goal != 0))\r
155                                 {\r
156                                         te = Findgoal (targ.else_goal);\r
157                                         if (te)\r
158                                         {\r
159                                                 AttemptToActivate (te, attacker, targ);\r
160                                         }\r
161                                 }\r
162                                 return;\r
163                         }\r
164                 }\r
165         }\r
166         damage_attacker = attacker;\r
167         if ((teamplay & (64 | 32)))\r
168         {\r
169                 damage = TeamEqualiseDamage (targ, attacker, damage);\r
170         }\r
171         save = ceil ((targ.armortype * damage));\r
172         if ((save >= targ.armorvalue))\r
173         {\r
174                 save = targ.armorvalue;\r
175                 targ.armortype = 0;\r
176                 targ.armorclass = 0;\r
177                 targ.items = (targ.items - (targ.items & ((8192 | 16384) | 32768)));\r
178         }\r
179 \r
180         targ.armorvalue = (targ.armorvalue - save);\r
181         take = ceil ((damage - save));\r
182         if ((targ.flags & 8))\r
183         {\r
184                 targ.dmg_take = (targ.dmg_take + take);\r
185                 targ.dmg_save = (targ.dmg_save + save);\r
186                 targ.dmg_inflictor = inflictor;\r
187         }\r
188         if (((inflictor != world) && (targ.movetype == 3)))\r
189         {\r
190                 targ.immune_to_check = (time + (damage / 20));\r
191                 dir = (targ.origin - ((inflictor.absmin + inflictor.absmax) * 0.5));\r
192                 dir = normalize (dir);\r
193                 if ((((damage < 60) & ((attacker.classname == "player") & (targ.classname == "player"))) & (attacker.netname != targ.netname)))\r
194                 {\r
195                         targ.velocity = (targ.velocity + ((dir * damage) * 11));\r
196                 }\r
197                 else\r
198                 {\r
199                         targ.velocity = (targ.velocity + ((dir * damage) * 8));\r
200                 }\r
201                 if ((((rj > 1) & ((attacker.classname == "player") & (targ.classname == "player"))) & (attacker.netname == targ.netname)))\r
202                 {\r
203                         targ.velocity = (targ.velocity + ((dir * damage) * rj));\r
204                 }\r
205         }\r
206         if ((targ.flags & 64))\r
207         {\r
208                 return;\r
209         }\r
210         if ((targ.invincible_finished >= time))\r
211         {\r
212                 if ((self.invincible_sound < time))\r
213                 {\r
214                         sound (targ, 3, "items/protect3.wav", 1, 1);\r
215                         self.invincible_sound = (time + 2);\r
216                 }\r
217                 return;\r
218         }\r
219         if (((attacker.classname == "player") && ((targ.classname == "player") || (targ.classname == "building_sentrygun"))))\r
220         {\r
221                 if ((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)))\r
222                 {\r
223                         if ((teamplay & 16))\r
224                         {\r
225                                 return;\r
226                         }\r
227                         else\r
228                         {\r
229                                 if ((teamplay & 8))\r
230                                 {\r
231                                         take = (take / 2);\r
232                                 }\r
233                         }\r
234                 }\r
235         }\r
236 \r
237         //                      MOVED HERE FROM PlayerDamage -- need to port the rest\r
238         // how much damage to deal to armor\r
239         damagearmor = bound(0, damage * 0.2 * (targ.armorvalue / 50) * cvar("g_balance_armor_takedamage"), targ.armorvalue);\r
240         // how much damage armor blocks\r
241         save = bound(0, damage * (targ.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
242         // how much damage to deal to player\r
243         take = bound(0, damage - save, damage);\r
244         targ.armorvalue = targ.armorvalue - damagearmor;\r
245         DelayArmorRegen(targ);\r
246 \r
247         if (((take < 1) && (take != 0)))\r
248         {\r
249                 take = 1;\r
250         }\r
251         targ.health = (targ.health - take);\r
252         if ((targ.armorvalue < 1))\r
253         {\r
254                 targ.armorclass = 0;\r
255                 targ.armorvalue = 0;\r
256         }\r
257         if ((targ.health <= 0))\r
258         {\r
259                 Killed (targ, attacker);\r
260                 return;\r
261         }\r
262         oldself = self;\r
263         self = targ;\r
264         if (self.th_pain)\r
265         {\r
266                 self.th_pain (attacker, take);\r
267                 if ((skill >= 3))\r
268                 {\r
269                         self.pain_finished = (time + 5);\r
270                 }\r
271         }\r
272         self = oldself;\r
273 };\r
274 \r
275 void (entity targ, entity inflictor, entity attacker, float damage, float T_flags, float T_AttackType) TF_T_Damage =\r
276 {\r
277         local vector dir;\r
278         local entity oldself;\r
279         local entity te;\r
280         local float save;\r
281         local float take;\r
282         local float olddmsg;\r
283         local float no_damage;\r
284         local float moment;\r
285 \r
286         if (targ.team_no < 1 && targ.classname != "func_button" && targ.classname != "door")                    // TEMP\r
287         {                                                               ////\r
288                 return;                                         ////\r
289         }                                                               ////\r
290         if ((targ.takedamage == 0))\r
291         {\r
292                 return;\r
293         }\r
294         if ((T_AttackType & 256))\r
295         {\r
296                 targ.health = damage;\r
297                 return;\r
298         }\r
299         /*if (cease_fire) // this aint needed\r
300         {\r
301                 return;\r
302         }*/\r
303         no_damage = 0;\r
304         if ((attacker.classname == "player"))\r
305         {\r
306                 damage = (damage * 0.9);\r
307                 if ((attacker.super_damage_finished > time))\r
308                 {\r
309                         damage = (damage * 4);\r
310                 }\r
311                 if (((((((targ.classname != "player") && (targ.classname != "bot")) && (targ.classname != "building_sentrygun")) && (targ.classname != "building_dispenser")) && (targ.classname != "building_teleporter_entrance")) && (targ.classname != "building_teleporter_exit")))\r
312                 {\r
313                         if (!Activated (targ, attacker))\r
314                         {\r
315                                 if ((targ.else_goal != 0))\r
316                                 {\r
317                                         te = Findgoal (targ.else_goal);\r
318                                         if (te)\r
319                                         {\r
320                                                 AttemptToActivate (te, attacker, targ);\r
321                                         }\r
322                                 }\r
323                                 return;\r
324                         }\r
325                 }\r
326         }\r
327         damage_attacker = attacker;\r
328         if ((teamplay & (64 | 32)))\r
329         {\r
330                 damage = TeamEqualiseDamage (targ, attacker, damage);\r
331         }\r
332         if (((targ.armorclass != 0) && (T_AttackType != 0)))\r
333         {\r
334                 if (((targ.armorclass & 1) && (T_AttackType & 1)))\r
335                 {\r
336                         damage = floor ((damage * 0.5));\r
337                 }\r
338                 if (((targ.armorclass & 2) && (T_AttackType & 2)))\r
339                 {\r
340                         damage = floor ((damage * 0.5));\r
341                 }\r
342                 if (((targ.armorclass & 4) && (T_AttackType & 4)))\r
343                 {\r
344                         damage = floor ((damage * 0.5));\r
345                 }\r
346                 if (((targ.armorclass & 8) && (T_AttackType & 8)))\r
347                 {\r
348                         damage = floor ((damage * 0.5));\r
349                 }\r
350                 if (((targ.armorclass & 16) && (T_AttackType & 16)))\r
351                 {\r
352                         damage = floor ((damage * 0.5));\r
353                 }\r
354         }\r
355         if ((T_flags & 1))\r
356         {\r
357                 take = damage;\r
358                 save = 0;\r
359         }\r
360         else\r
361         {\r
362                 save = ceil ((targ.armortype * damage));\r
363                 if ((((((attacker.classname == "player") && (targ.team_no > 0)) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
364                 {\r
365                         if ((T_AttackType & 4))\r
366                         {\r
367                                 if ((teamplay & 1024))\r
368                                 {\r
369                                         save = 0;\r
370                                 }\r
371                                 else\r
372                                 {\r
373                                         if ((teamplay & 512))\r
374                                         {\r
375                                                 save = (save / 2);\r
376                                         }\r
377                                 }\r
378                         }\r
379                         else\r
380                         {\r
381                                 if ((teamplay & 256))\r
382                                 {\r
383                                         save = 0;\r
384                                 }\r
385                                 else\r
386                                 {\r
387                                         if ((teamplay & 128))\r
388                                         {\r
389                                                 save = (save / 2);\r
390                                         }\r
391                                 }\r
392                         }\r
393                 }\r
394                 if ((save >= targ.armorvalue))\r
395                 {\r
396                         save = targ.armorvalue;\r
397                         targ.armortype = 0;\r
398                         targ.armorclass = 0;\r
399                         targ.items = (targ.items - (targ.items & ((8192 | 16384) | 32768)));\r
400                 }\r
401                 targ.armorvalue = (targ.armorvalue - save);\r
402                 take = ceil ((damage - save));\r
403         }\r
404         if ((targ.flags & 8))\r
405         {\r
406                 targ.dmg_take = (targ.dmg_take + take);\r
407                 targ.dmg_save = (targ.dmg_save + save);\r
408                 targ.dmg_inflictor = inflictor;\r
409         }\r
410         if ((((inflictor != world) && (targ.movetype == 3)) && !(targ.tfstate & 65536)))\r
411         {\r
412                 if ((deathmsg != 9))\r
413                 {\r
414                         targ.immune_to_check = (time + (damage / 20));\r
415                         dir = (targ.origin - ((inflictor.absmin + inflictor.absmax) * 0.5));\r
416                         dir = normalize (dir);\r
417                         /*if ((targ.class == 6)) // moot function -- NexTF doesnt have an HWGuy\r
418                         {\r
419                                 moment = (damage / 4);\r
420                                 if ((damage <= 50))\r
421                                 {\r
422                                         moment = 0;\r
423                                 }\r
424                         }\r
425                         else*/\r
426                         {\r
427                                 moment = damage;\r
428                         }\r
429                         if ((((moment < 60) && ((attacker.classname == "player") && (targ.classname == "player"))) && (attacker.netname != targ.netname)))\r
430                         {\r
431                                 targ.velocity = (targ.velocity + ((dir * moment) * 11));\r
432                         }\r
433                         else\r
434                         {\r
435                                 targ.velocity = (targ.velocity + ((dir * moment) * 8));\r
436                         }\r
437                         if ((((rj > 1) && ((attacker.classname == "player") && (targ.classname == "player"))) && (attacker.netname == targ.netname)))\r
438                         {\r
439                                 targ.velocity = (targ.velocity + ((dir * moment) * rj));\r
440                         }\r
441                 }\r
442         }\r
443         if ((targ.flags & 64))\r
444         {\r
445                 return;\r
446         }\r
447         if ((targ.invincible_finished >= time))\r
448         {\r
449                 if ((self.invincible_sound < time))\r
450                 {\r
451                         sound (targ, 3, "items/protect3.wav", 1, 1);\r
452                         self.invincible_sound = (time + 2);\r
453                 }\r
454                 return;\r
455         }\r
456         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
457         {\r
458                 if (((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
459                 {\r
460                         if ((T_AttackType & 4))\r
461                         {\r
462                                 if ((teamplay & 16))\r
463                                 {\r
464                                         no_damage = 1;\r
465                                 }\r
466                                 else\r
467                                 {\r
468                                         if ((teamplay & 8))\r
469                                         {\r
470                                                 take = (take / 2);\r
471                                         }\r
472                                 }\r
473                         }\r
474                         else\r
475                         {\r
476                                 if ((teamplay & 4))\r
477                                 {\r
478                                         no_damage = 1;\r
479                                 }\r
480                                 else\r
481                                 {\r
482                                         if ((teamplay & 2))\r
483                                         {\r
484                                                 take = (take / 2);\r
485                                         }\r
486                                 }\r
487                         }\r
488                 }\r
489         }\r
490         if ((T_flags & 4))\r
491         {\r
492                 if ((targ == attacker))\r
493                 {\r
494                         return;\r
495                 }\r
496         }\r
497 \r
498         local float damagearmor;\r
499         //                      MOVED HERE FROM PlayerDamage -- need to port the rest\r
500         // how much damage to deal to armor\r
501         damagearmor = bound(0, damage * 0.2 * (targ.armorvalue / 50) * cvar("g_balance_armor_takedamage"), targ.armorvalue);\r
502         // how much damage armor blocks\r
503         save = bound(0, damage * (targ.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
504         // how much damage to deal to player\r
505         take = bound(0, damage - save, damage);\r
506         targ.armorvalue = targ.armorvalue - damagearmor;\r
507         DelayArmorRegen(targ);\r
508 \r
509         if ((take < 1))\r
510         {\r
511                 take = 1;\r
512         }\r
513         take = rint (take);\r
514         if ((no_damage == 0))\r
515         {\r
516                 targ.health = (targ.health - take);\r
517         }\r
518         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
519         {\r
520                 if (((((targ.team_no > 0) && (targ.team_no == attacker.team_no)) && (targ != attacker)) && (T_flags & 2)))\r
521                 {\r
522                         olddmsg = deathmsg;\r
523                         if ((T_AttackType & 4))\r
524                         {\r
525                                 deathmsg = 37;\r
526                                 if ((teamplay & 16384))\r
527                                 {\r
528                                         TF_T_Damage (attacker, world, world, take, 1, 0);\r
529                                 }\r
530                                 else\r
531                                 {\r
532                                         if ((teamplay & 8192))\r
533                                         {\r
534                                                 TF_T_Damage (attacker, world, world, (take / 2), 1, 0);\r
535                                         }\r
536                                 }\r
537                         }\r
538                         else\r
539                         {\r
540                                 deathmsg = 37;\r
541                                 if ((teamplay & 4096))\r
542                                 {\r
543                                         TF_T_Damage (attacker, world, world, take, 1, 0);\r
544                                 }\r
545                                 else\r
546                                 {\r
547                                         if ((teamplay & 2048))\r
548                                         {\r
549                                                 TF_T_Damage (attacker, world, world, (take / 2), 1, 0);\r
550                                         }\r
551                                 }\r
552                         }\r
553                         deathmsg = olddmsg;\r
554                 }\r
555         }\r
556         if ((no_damage == 1))\r
557         {\r
558                 return;\r
559         }\r
560         if ((targ.armorvalue < 1))\r
561         {\r
562                 targ.armorclass = 0;\r
563                 targ.armorvalue = 0;\r
564         }\r
565         if ((targ.health <= 0))\r
566         {\r
567                 if ((((inflictor.classname == "detpack") && (inflictor.weaponmode == 1)) && (inflictor.enemy == targ)))\r
568                 {\r
569                         deathmsg = 16;\r
570                 }\r
571                 Killed (targ, attacker);\r
572                 return;\r
573         }\r
574         oldself = self;\r
575         self = targ;\r
576         if (self.th_pain)\r
577         {\r
578                 self.th_pain (attacker, take);\r
579                 if ((skill >= 3))\r
580                 {\r
581                         self.pain_finished = (time + 5);\r
582                 }\r
583         }\r
584         self = oldself;\r
585 };\r
586 \r
587 void (entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =\r
588 {\r
589         local float points;\r
590         local entity head;\r
591         local entity te;\r
592         local vector org;                                                       ////\r
593 \r
594         head = findradius (inflictor.origin, (damage + 40));\r
595         while (head)\r
596         {\r
597                 if ((head != ignore))\r
598                 {\r
599                         if (head.takedamage)\r
600                         {\r
601                                 org = (head.origin + ((head.mins + head.maxs) * 0.5));\r
602                                 points = (0.5 * vlen ((inflictor.origin - org)));\r
603                                 if ((points < 0))\r
604                                 {\r
605                                         points = 0;\r
606                                 }\r
607                                 points = (damage - points);\r
608                                 if ((head == attacker))\r
609                                 {\r
610                                         points = (points * 0.75);\r
611                                 }\r
612                                 if ((points > 0))\r
613                                 {\r
614                                         if (CanDamage (head, inflictor))\r
615                                         {\r
616                                                 if ((head.classname == "monster_shambler"))\r
617                                                 {\r
618                                                         T_Damage (head, inflictor, attacker, (points * 0.5));\r
619                                                 }\r
620                                                 else\r
621                                                 {\r
622                                                         TF_T_Damage (head, inflictor, attacker, points, 2, 4);\r
623                                                 }\r
624                                         }\r
625                                 }\r
626                         }\r
627                 }\r
628                 head = head.chain;\r
629         }\r
630 };\r