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