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