]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/tturrets/units/unit_tessla.qc
Make most server includes order insensitive
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / tturrets / units / unit_tessla.qc
1 #include "../../csqceffects.qh"
2
3 void spawnfunc_turret_tesla();
4 void turret_tesla_dinit();
5 void turret_tesla_fire();
6
7 entity toast(entity from, float range, float damage)
8 {
9     entity e;
10     entity etarget = world;
11     float d,dd;
12     float r;
13
14     dd = range + 1;
15
16     e = findradius(from.origin,range);
17     while (e)
18     {
19         if ((e.railgunhit != 1) && (e != from))
20         {
21             r = turret_validate_target(self,e,self.target_validate_flags);
22             if (r > 0)
23             {
24                 traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
25                 if (trace_fraction == 1.0)
26                 {
27                     d = vlen(e.origin - from.origin);
28                     if (d < dd)
29                     {
30                         dd = d;
31                         etarget = e;
32                     }
33                 }
34             }
35         }
36         e = e.chain;
37     }
38
39     if (etarget)
40     {
41         te_csqc_lightningarc(from.origin,etarget.origin);
42         Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
43         etarget.railgunhit = 1;
44     }
45
46     return etarget;
47 }
48
49 float turret_tesla_firecheck()
50 {
51     // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
52     float do_target_scan = 0;
53
54     if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
55         do_target_scan = 1;
56
57     // Old target (if any) invalid?
58     if(self.target_validate_time < time)
59     if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
60     {
61         self.enemy = world;
62         self.target_validate_time = time + 0.5;
63         do_target_scan = 1;
64     }
65
66     // But never more often then g_turrets_targetscan_mindelay!
67     if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
68         do_target_scan = 0;
69
70     if(do_target_scan)
71     {
72         self.enemy = turret_select_target();
73         self.target_select_time = time;
74     }
75
76     if (!turret_stdproc_firecheck())
77         return 0;
78
79     if(self.enemy)
80         return 1;
81
82     return 0;
83 }
84
85
86 void turret_tesla_fire()
87 {
88     entity e, t;
89     float d, r, i;
90
91     d = self.shot_dmg;
92     r = self.target_range;
93     e = spawn();
94     setorigin(e,self.tur_shotorg);
95
96     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
97
98     t = toast(e,r,d);
99     remove(e);
100
101     if (t == world) return;
102
103     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
104
105     self.attack_finished_single = time + self.shot_refire;
106     for (i = 0; i < 10; ++i)
107     {
108         d *= 0.75;
109         r *= 0.85;
110         t = toast(t, r, d);
111         if (t == world) break;
112
113     }
114
115     e = findchainfloat(railgunhit, 1);
116     while (e)
117     {
118         e.railgunhit = 0;
119         e = e.chain;
120     }
121 }
122
123 void turret_tesla_postthink()
124 {
125     if (!self.active)
126     {
127         self.tur_head.avelocity = '0 0 0';
128         return;
129     }
130
131     if(self.ammo < self.shot_dmg)
132     {
133         self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
134     }
135     else
136     {
137         self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
138
139         if(self.attack_finished_single > time)
140             return;
141
142         float f;
143         f = (self.ammo / self.ammo_max);
144         f = f * f;
145         if(f > random())
146             if(random() < 0.1)
147                 te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
148     }
149 }
150
151
152 void turret_tesla_dinit()
153 {
154     if (self.netname == "")      self.netname     = "Tesla Coil";
155
156     self.turrcaps_flags      = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
157
158     self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
159                                TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
160
161     self.firecheck_flags     = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_OWM_AMMO;
162     self.shoot_flags         = TFL_SHOOT_CUSTOM;
163     self.ammo_flags          = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
164     self.aim_flags           = TFL_AIM_NO;
165     self.track_flags         = TFL_TRACK_NO;
166
167     if (turret_stdproc_init("tesla_std", "models/turrets/tesla_base.md3", "models/turrets/tesla_head.md3", TID_TESLA) == 0)
168     {
169         remove(self);
170         return;
171     }
172     setsize(self,'-60 -60 0','60 60 128');
173
174     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
175                                  TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
176
177     self.turret_firefunc      = turret_tesla_fire;
178     self.turret_postthink     = turret_tesla_postthink;
179     self.turret_firecheckfunc = turret_tesla_firecheck;
180 }
181
182 /*QUAKED turret_tesla (0 .5 .8) ?
183 */
184 void spawnfunc_turret_tesla()
185 {
186     precache_model ("models/turrets/tesla_head.md3");
187     precache_model ("models/turrets/tesla_base.md3");
188
189
190     self.think = turret_tesla_dinit;
191     self.nextthink = time + 0.5;
192 }
193