3f7acdac95941704784826b51b367eb18b7c94df
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / tturrets / units / unit_ewheel.qc
1 #define ewheel_amin_stop 0
2 #define ewheel_amin_fwd_slow 1
3 #define ewheel_amin_fwd_fast 2
4 #define ewheel_amin_bck_slow 3
5 #define ewheel_amin_bck_fast 4
6
7 float ewheel_speed_fast;
8 float ewheel_speed_slow;
9 float ewheel_speed_slower;
10 float ewheel_speed_stop;
11
12 void turret_ewheel_loadcvars()
13 {
14     ewheel_speed_fast   = cvar("g_turrets_unit_ewheel_speed_fast");
15     ewheel_speed_slow   = cvar("g_turrets_unit_ewheel_speed_slow");
16     ewheel_speed_slower = cvar("g_turrets_unit_ewheel_speed_slower");
17     ewheel_speed_stop   = cvar("g_turrets_unit_ewheel_speed_stop");
18 }
19
20 void turret_ewheel_projectile_explode()
21 {
22     vector org2;
23
24     org2 = findbetterlocation (self.origin, 8);
25     pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1);
26     //w_deathtypestring = "saw the eweel. to late.";
27 #ifdef TURRET_DEBUG
28     float d;
29
30     d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
31     self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
32     self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
33 #else
34     RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
35 #endif
36     sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
37
38     remove (self);
39 }
40
41
42 void ewheel_attack()
43 {
44     entity proj;
45     float i;
46
47     for (i = 0; i < 1; ++i)
48     {
49         turret_do_updates(self);
50
51         sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM);
52         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
53
54         proj                    = spawn ();
55         setorigin(proj, self.tur_shotorg);
56         proj.classname       = "ewheel bolt";
57         proj.owner           = self;
58         proj.bot_dodge       = FALSE;
59         proj.bot_dodgerating = self.shot_dmg;
60         proj.think           = turret_ewheel_projectile_explode;
61         proj.nextthink       = time + 9;
62         proj.solid           = SOLID_BBOX;
63         proj.movetype        = MOVETYPE_FLYMISSILE;
64         proj.velocity        = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
65         proj.touch           = turret_ewheel_projectile_explode;
66         proj.enemy           = self.enemy;
67         proj.flags           = FL_PROJECTILE | FL_NOTARGET;
68
69         CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);
70
71         self.tur_head.frame += 2;
72
73         if (self.tur_head.frame > 3)
74             self.tur_head.frame = 0;
75     }
76
77 }
78
79 void ewheel_move_path()
80 {
81
82     // Are we close enougth to a path node to switch to the next?
83     if (vlen(self.origin  - self.pathcurrent.origin) < 64)
84         if (self.pathcurrent.path_next == world)
85         {
86             // Path endpoint reached
87             pathlib_deletepath(self.pathcurrent.owner);
88             self.pathcurrent = world;
89
90             if (self.pathgoal)
91             {
92                 if (self.pathgoal.use)
93                     self.pathgoal.use();
94
95                 if (self.pathgoal.enemy)
96                 {
97                     self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
98                     self.pathgoal = self.pathgoal.enemy;
99                 }
100             }
101             else
102                 self.pathgoal = world;
103         }
104         else
105             self.pathcurrent = self.pathcurrent.path_next;
106
107
108
109     if (self.pathcurrent)
110     {
111
112         self.moveto = self.pathcurrent.origin;
113         self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
114
115         movelib_move_simple(v_forward, ewheel_speed_fast, 0.4);
116
117         return;
118     }
119 }
120
121 void  ewheel_move_enemy()
122 {
123
124     self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
125
126     //self.steerto = steerlib_standoff(self.enemy.origin,self.target_range_optimal);
127     //self.steerto = steerlib_beamsteer(self.steerto,1024,64,68,256);
128     self.moveto  = self.origin + self.steerto * 128;
129
130     if (self.tur_dist_enemy > self.target_range_optimal)
131     {
132         if ( self.tur_head.spawnshieldtime < 1 )
133         {
134             self.frame = ewheel_amin_fwd_fast;
135             movelib_move_simple(v_forward, ewheel_speed_fast, 0.4);
136         }
137         else if (self.tur_head.spawnshieldtime < 2)
138         {
139
140             self.frame = ewheel_amin_fwd_slow;
141             movelib_move_simple(v_forward, ewheel_speed_slow, 0.4);
142        }
143         else
144         {
145             self.frame = ewheel_amin_fwd_slow;
146             movelib_move_simple(v_forward, ewheel_speed_slower, 0.4);
147         }
148     }
149     else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
150     {
151         self.frame = ewheel_amin_bck_slow;
152         movelib_move_simple(v_forward * -1, ewheel_speed_slow, 0.4);
153     }
154     else
155     {
156         self.frame = ewheel_amin_stop;
157         movelib_beak_simple(ewheel_speed_stop);
158     }
159 }
160
161
162 void ewheel_move_idle()
163 {
164     self.frame = 0;
165     if (vlen(self.velocity))
166         movelib_beak_simple(ewheel_speed_stop);
167 }
168
169 void ewheel_postthink()
170 {
171     float vz;
172     vector wish_angle,real_angle;
173
174     vz = self.velocity_z;
175
176     self.angles_x = anglemods(self.angles_x);
177     self.angles_y = anglemods(self.angles_y);
178
179     //self.angles_x *= -1;
180     fixedmakevectors(self.angles);
181     //self.angles_x *= -1;
182
183     wish_angle = normalize(self.steerto);
184     wish_angle = vectoangles(wish_angle);
185     real_angle = wish_angle - self.angles;
186     real_angle = shortangle_vxy(real_angle,self.tur_head.angles);
187
188     self.tur_head.spawnshieldtime = fabs(real_angle_y);
189     real_angle_y  = bound(-self.tur_head.aim_speed,real_angle_y,self.tur_head.aim_speed);
190     self.angles_y = (self.angles_y + real_angle_y);
191
192     // Simulate banking
193     self.angles_z = bound(-45,real_angle_y * -2.5,45);
194
195     if(self.enemy)
196         ewheel_move_enemy();
197     else if(self.pathcurrent)
198         ewheel_move_path();
199     else
200         ewheel_move_idle();
201
202
203     self.velocity_z = vz;
204 }
205
206 void ewheel_respawnhook()
207 {
208     entity e;
209
210     setorigin(self,self.pos1);
211
212     if (self.target != "")
213     {
214         e = find(world,targetname,self.target);
215         if (!e)
216         {
217             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
218             self.target = "";
219         }
220
221         if (e.classname != "turret_checkpoint")
222             dprint("Warning: not a turrret path\n");
223         else
224         {
225             self.pathcurrent = WALKER_PATH(self.origin,e.origin);
226             self.pathgoal = e;
227         }
228     }
229 }
230
231 void ewheel_diehook()
232 {
233     turret_trowgib2(self.origin,self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2);
234
235     self.velocity = '0 0 0';
236
237     if (self.pathcurrent)
238         pathlib_deletepath(self.pathcurrent.owner);
239
240     self.pathcurrent = world;
241
242     /*
243     if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
244     {
245         verbstack_flush(self.verbs_move);
246         remove(self.verbs_move);
247     }
248     */
249
250 }
251
252 void turret_ewheel_dinit()
253 {
254     entity e;
255
256     if (self.netname == "")      self.netname     = "eWheel Turret";
257
258     if (self.target != "")
259     {
260         e = find(world,targetname,self.target);
261         if (!e)
262         {
263             bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
264             self.target = "";
265         }
266
267         if (e.classname != "turret_checkpoint")
268             dprint("Warning: not a turrret path\n");
269         else
270             self.goalcurrent = e;
271     }
272
273     self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
274     self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM ;
275     self.turret_respawnhook = ewheel_respawnhook;
276
277     self.turret_diehook = ewheel_diehook;
278
279     if (turret_stdproc_init("ewheel_std",0,"models/turrets/ewheel-base2.md3","models/turrets/ewheel-gun1.md3") == 0)
280     {
281         remove(self);
282         return;
283     }
284
285     self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
286     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
287     self.damage_flags          |= TFL_DMG_DEATH_NOGIBS;
288
289     self.iscreature = TRUE;
290     self.movetype   = MOVETYPE_WALK;
291     self.solid      = SOLID_SLIDEBOX;
292     self.takedamage = DAMAGE_AIM;
293
294     setsize(self,'-32 -32 0', '32 32 48');
295
296     self.pos1 = self.origin;
297
298     self.idle_aim = '0 0 0';
299
300     // Our fire routine
301     self.turret_firefunc  = ewheel_attack;
302     self.turret_postthink = ewheel_postthink;
303     self.tur_head.frame = 1;
304
305     // Convert from dgr / sec to dgr / tic
306     self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");
307     self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
308
309     if (self.target != "")
310     {
311         e = find(world,targetname,self.target);
312         if (!e)
313         {
314             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
315             self.target = "";
316         }
317
318         if (e.classname != "turret_checkpoint")
319             dprint("Warning: not a turrret path\n");
320         else
321         {
322             self.pathcurrent = WALKER_PATH(self.origin,e.origin);
323             self.pathgoal = e;
324         }
325     }
326 }
327
328 void spawnfunc_turret_ewheel()
329 {
330     g_turrets_common_precash();
331
332     precache_model ("models/turrets/ewheel-base2.md3");
333     precache_model ("models/turrets/ewheel-gun1.md3");
334
335     turret_ewheel_loadcvars();
336
337     self.think = turret_ewheel_dinit;
338     self.nextthink = time + 0.5;
339 }