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