]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/turrets/turret/tesla.qc
Turrets: cleanup
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / turrets / turret / tesla.qc
1 #ifndef TUR_TESLA_H
2 #define TUR_TESLA_H
3 REGISTER_TURRET(
4 /* TUR_##id   */ TESLA,
5 /* function   */ t_tesla,
6 /* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
7 /* mins,maxs  */ '-60 -60 0', '60 60 128',
8 /* model          */ "tesla_base.md3",
9 /* head_model */ "tesla_head.md3",
10 /* netname        */ "tesla",
11 /* fullname   */ _("Tesla Coil")
12 );
13 #endif
14
15 #ifdef IMPLEMENTATION
16 #ifdef SVQC
17 entity toast(entity from, float range, float damage)
18 {SELFPARAM();
19     entity e;
20     entity etarget = world;
21     float d,dd;
22     float r;
23
24     dd = range + 1;
25
26     e = findradius(from.origin,range);
27     while (e)
28     {
29         if ((e.railgunhit != 1) && (e != from))
30         {
31             r = turret_validate_target(self,e,self.target_validate_flags);
32             if (r > 0)
33             {
34                 traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
35                 if (trace_fraction == 1.0)
36                 {
37                     d = vlen(e.origin - from.origin);
38                     if (d < dd)
39                     {
40                         dd = d;
41                         etarget = e;
42                     }
43                 }
44             }
45         }
46         e = e.chain;
47     }
48
49     if (etarget)
50     {
51         te_csqc_lightningarc(from.origin,etarget.origin);
52         Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
53         etarget.railgunhit = 1;
54     }
55
56     return etarget;
57 }
58
59 float turret_tesla_firecheck()
60 {SELFPARAM();
61     // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
62     float do_target_scan = 0;
63
64     if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
65         do_target_scan = 1;
66
67     // Old target (if any) invalid?
68     if(self.target_validate_time < time)
69     if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
70     {
71         self.enemy = world;
72         self.target_validate_time = time + 0.5;
73         do_target_scan = 1;
74     }
75
76     // But never more often then g_turrets_targetscan_mindelay!
77     if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
78         do_target_scan = 0;
79
80     if(do_target_scan)
81     {
82         self.enemy = turret_select_target();
83         self.target_select_time = time;
84     }
85
86     if(!turret_firecheck())
87         return 0;
88
89     if(self.enemy)
90         return 1;
91
92     return 0;
93 }
94
95 void spawnfunc_turret_tesla() { SELFPARAM(); if(!turret_initialize(TUR_TESLA.m_id)) remove(self); }
96
97 float t_tesla(float req)
98 {SELFPARAM();
99     switch(req)
100     {
101         case TR_ATTACK:
102         {
103             entity e, t;
104             float d, r, i;
105
106             d = self.shot_dmg;
107             r = self.target_range;
108             e = spawn();
109             setorigin(e,self.tur_shotorg);
110
111             self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
112
113             t = toast(e,r,d);
114             remove(e);
115
116             if (t == world) return true;
117
118             self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
119
120             self.attack_finished_single = time + self.shot_refire;
121             for (i = 0; i < 10; ++i)
122             {
123                 d *= 0.75;
124                 r *= 0.85;
125                 t = toast(t, r, d);
126                 if (t == world) break;
127
128             }
129
130             e = findchainfloat(railgunhit, 1);
131             while (e)
132             {
133                 e.railgunhit = 0;
134                 e = e.chain;
135             }
136
137             return true;
138         }
139         case TR_THINK:
140         {
141             if(!self.active)
142             {
143                 self.tur_head.avelocity = '0 0 0';
144                 return true;
145             }
146
147             if(self.ammo < self.shot_dmg)
148             {
149                 self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
150             }
151             else
152             {
153                 self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
154
155                 if(self.attack_finished_single > time)
156                     return true;
157
158                 float f;
159                 f = (self.ammo / self.ammo_max);
160                 f = f * f;
161                 if(f > random())
162                     if(random() < 0.1)
163                         te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
164             }
165
166             return true;
167         }
168         case TR_DEATH:
169         {
170             return true;
171         }
172         case TR_SETUP:
173         {
174             self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
175                                  TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
176
177             self.turret_firecheckfunc = turret_tesla_firecheck;
178             self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
179                                TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
180
181             self.firecheck_flags        = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
182             self.shoot_flags            = TFL_SHOOT_CUSTOM;
183             self.ammo_flags                     = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
184             self.aim_flags                      = TFL_AIM_NO;
185             self.track_flags            = TFL_TRACK_NO;
186
187             return true;
188         }
189         case TR_PRECACHE:
190         {
191             return true;
192         }
193     }
194
195     return true;
196 }
197
198 #endif // SVQC
199 #ifdef CSQC
200 float t_tesla(float req)
201 {
202     switch(req)
203     {
204         case TR_SETUP:
205         {
206             return true;
207         }
208         case TR_PRECACHE:
209         {
210             return true;
211         }
212     }
213
214     return true;
215 }
216
217 #endif // CSQC
218 #endif // REGISTER_TURRET