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