]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/turrets/turret/ewheel.qc
Turrets: cleanup
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / turrets / turret / ewheel.qc
1 #ifndef TUR_EWHEEL_H
2 #define TUR_EWHEEL_H
3 REGISTER_TURRET(
4 /* TUR_##id   */ EWHEEL,
5 /* function   */ t_ewheel,
6 /* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
7 /* mins,maxs  */ '-32 -32 0', '32 32 48',
8 /* model      */ "ewheel-base2.md3",
9 /* head_model */ "ewheel-gun1.md3",
10 /* netname    */ "ewheel",
11 /* fullname   */ _("eWheel Turret")
12 );
13 #endif
14
15 #ifdef IMPLEMENTATION
16 #ifdef SVQC
17 float autocvar_g_turrets_unit_ewheel_speed_fast;
18 float autocvar_g_turrets_unit_ewheel_speed_slow;
19 float autocvar_g_turrets_unit_ewheel_speed_slower;
20 float autocvar_g_turrets_unit_ewheel_speed_stop;
21 float autocvar_g_turrets_unit_ewheel_turnrate;
22
23 const float ewheel_anim_stop = 0;
24 const float ewheel_anim_fwd_slow = 1;
25 const float ewheel_anim_fwd_fast = 2;
26 const float ewheel_anim_bck_slow = 3;
27 const float ewheel_anim_bck_fast = 4;
28
29 //#define EWHEEL_FANCYPATH
30 void ewheel_move_path()
31 {SELFPARAM();
32 #ifdef EWHEEL_FANCYPATH
33     // Are we close enougth to a path node to switch to the next?
34     if (vlen(self.origin  - self.pathcurrent.origin) < 64)
35         if (self.pathcurrent.path_next == world)
36         {
37             // Path endpoint reached
38             pathlib_deletepath(self.pathcurrent.owner);
39             self.pathcurrent = world;
40
41             if (self.pathgoal)
42             {
43                 if (self.pathgoal.use)
44                     self.pathgoal.use();
45
46                 if (self.pathgoal.enemy)
47                 {
48                     self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
49                     self.pathgoal = self.pathgoal.enemy;
50                 }
51             }
52             else
53                 self.pathgoal = world;
54         }
55         else
56             self.pathcurrent = self.pathcurrent.path_next;
57
58 #else
59     if (vlen(self.origin - self.pathcurrent.origin) < 64)
60         self.pathcurrent = self.pathcurrent.enemy;
61 #endif
62
63     if (self.pathcurrent)
64     {
65
66         self.moveto = self.pathcurrent.origin;
67         self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
68
69         movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
70     }
71 }
72
73 void ewheel_move_enemy()
74 {SELFPARAM();
75     float newframe;
76
77     self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
78
79     self.moveto  = self.origin + self.steerto * 128;
80
81     if (self.tur_dist_enemy > self.target_range_optimal)
82     {
83         if ( self.tur_head.spawnshieldtime < 1 )
84         {
85             newframe = ewheel_anim_fwd_fast;
86             movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
87         }
88         else if (self.tur_head.spawnshieldtime < 2)
89         {
90
91             newframe = ewheel_anim_fwd_slow;
92             movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
93        }
94         else
95         {
96             newframe = ewheel_anim_fwd_slow;
97             movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
98         }
99     }
100     else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
101     {
102         newframe = ewheel_anim_bck_slow;
103         movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
104     }
105     else
106     {
107         newframe = ewheel_anim_stop;
108         movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
109     }
110
111     turrets_setframe(newframe, false);
112 }
113
114 void ewheel_move_idle()
115 {SELFPARAM();
116     if(self.frame != 0)
117     {
118         self.SendFlags |= TNSF_ANIM;
119         self.anim_start_time = time;
120     }
121
122     self.frame = 0;
123     if (vlen(self.velocity))
124         movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
125 }
126
127 void spawnfunc_turret_ewheel() { SELFPARAM(); if(!turret_initialize(TUR_EWHEEL.m_id)) remove(self); }
128
129 float t_ewheel(float req)
130 {SELFPARAM();
131     switch(req)
132     {
133         case TR_ATTACK:
134         {
135             float i;
136             entity _mis;
137
138             for (i = 0; i < 1; ++i)
139             {
140                 turret_do_updates(self);
141
142                 _mis = turret_projectile(SND(LASERGUN_FIRE), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
143                 _mis.missile_flags = MIF_SPLASH;
144
145                 Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
146
147                 self.tur_head.frame += 2;
148
149                 if (self.tur_head.frame > 3)
150                     self.tur_head.frame = 0;
151             }
152
153             return true;
154         }
155         case TR_THINK:
156         {
157             float vz;
158             vector wish_angle, real_angle;
159
160             vz = self.velocity_z;
161
162             self.angles_x = anglemods(self.angles_x);
163             self.angles_y = anglemods(self.angles_y);
164
165             fixedmakevectors(self.angles);
166
167             wish_angle = normalize(self.steerto);
168             wish_angle = vectoangles(wish_angle);
169             real_angle = wish_angle - self.angles;
170             real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
171
172             self.tur_head.spawnshieldtime = fabs(real_angle_y);
173             real_angle_y  = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
174             self.angles_y = (self.angles_y + real_angle_y);
175
176             if(self.enemy)
177                 ewheel_move_enemy();
178             else if(self.pathcurrent)
179                 ewheel_move_path();
180             else
181                 ewheel_move_idle();
182
183             self.velocity_z = vz;
184
185             if(vlen(self.velocity))
186                 self.SendFlags |= TNSF_MOVE;
187
188             return true;
189         }
190         case TR_DEATH:
191         {
192             self.velocity = '0 0 0';
193
194 #ifdef EWHEEL_FANCYPATH
195             if (self.pathcurrent)
196                 pathlib_deletepath(self.pathcurrent.owner);
197 #endif
198             self.pathcurrent = world;
199
200             return true;
201         }
202         case TR_SETUP:
203         {
204             entity e;
205
206             if(self.movetype == MOVETYPE_WALK)
207             {
208                 self.velocity = '0 0 0';
209                 self.enemy = world;
210
211                 setorigin(self, self.pos1);
212
213                 if (self.target != "")
214                 {
215                     e = find(world, targetname, self.target);
216                     if (!e)
217                     {
218                         LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
219                         self.target = "";
220                     }
221
222                     if (e.classname != "turret_checkpoint")
223                         LOG_TRACE("Warning: not a turrret path\n");
224                     else
225                     {
226
227 #ifdef EWHEEL_FANCYPATH
228                         self.pathcurrent = WALKER_PATH(self.origin,e.origin);
229                         self.pathgoal = e;
230 #else
231                         self.pathcurrent  = e;
232 #endif
233                     }
234                 }
235             }
236
237             self.iscreature                             = true;
238             self.teleportable                   = TELEPORT_NORMAL;
239             self.damagedbycontents              = true;
240             self.movetype                               = MOVETYPE_WALK;
241             self.solid                                  = SOLID_SLIDEBOX;
242             self.takedamage                             = DAMAGE_AIM;
243             self.idle_aim                               = '0 0 0';
244             self.pos1                                   = self.origin;
245             self.target_select_flags    = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
246             self.target_validate_flags  = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
247             self.frame                                  = self.tur_head.frame = 1;
248             self.ammo_flags                             = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
249
250             // Convert from dgr / sec to dgr / tic
251             self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
252             self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
253
254             return true;
255         }
256         case TR_PRECACHE:
257         {
258             return true;
259         }
260     }
261
262     return true;
263 }
264
265 #endif // SVQC
266 #ifdef CSQC
267
268 void ewheel_draw()
269 {SELFPARAM();
270     float dt;
271
272     dt = time - self.move_time;
273     self.move_time = time;
274     if(dt <= 0)
275         return;
276
277     fixedmakevectors(self.angles);
278     setorigin(self, self.origin + self.velocity * dt);
279     self.tur_head.angles += dt * self.tur_head.move_avelocity;
280     self.angles_y = self.move_angles_y;
281
282     if (self.health < 127)
283     if(random() < 0.05)
284         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
285 }
286
287 float t_ewheel(float req)
288 {SELFPARAM();
289     switch(req)
290     {
291         case TR_SETUP:
292         {
293             self.gravity                = 1;
294             self.movetype               = MOVETYPE_BOUNCE;
295             self.move_movetype  = MOVETYPE_BOUNCE;
296             self.move_origin    = self.origin;
297             self.move_time              = time;
298             self.draw                   = ewheel_draw;
299
300             return true;
301         }
302         case TR_PRECACHE:
303         {
304             return true;
305         }
306     }
307
308     return true;
309 }
310
311 #endif // CSQC
312 #endif // REGISTER_TURRET