Merge branch 'master' into Mario/vaporizer_damage
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / tturrets / units / unit_ewheel.qc
1 const float ewheel_amin_stop = 0;
2 const float ewheel_amin_fwd_slow = 1;
3 const float ewheel_amin_fwd_fast = 2;
4 const float ewheel_amin_bck_slow = 3;
5 const float ewheel_amin_bck_fast = 4;
6
7 void ewheel_attack()
8 {
9     float i;
10     entity _mis;
11
12     for (i = 0; i < 1; ++i)
13     {
14         turret_do_updates(self);
15
16         _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, true, true); // WEAPONTODO: this is not a projectile made by the blaster, add separate effect for it
17         _mis.missile_flags = MIF_SPLASH;
18
19         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
20
21         self.tur_head.frame += 2;
22
23         if (self.tur_head.frame > 3)
24             self.tur_head.frame = 0;
25     }
26
27 }
28 //#define EWHEEL_FANCYPATH
29 void ewheel_move_path()
30 {
31 #ifdef EWHEEL_FANCYPATH
32     // Are we close enougth to a path node to switch to the next?
33     if (vlen(self.origin  - self.pathcurrent.origin) < 64)
34         if (self.pathcurrent.path_next == world)
35         {
36             // Path endpoint reached
37             pathlib_deletepath(self.pathcurrent.owner);
38             self.pathcurrent = world;
39
40             if (self.pathgoal)
41             {
42                 if (self.pathgoal.use)
43                     self.pathgoal.use();
44
45                 if (self.pathgoal.enemy)
46                 {
47                     self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
48                     self.pathgoal = self.pathgoal.enemy;
49                 }
50             }
51             else
52                 self.pathgoal = world;
53         }
54         else
55             self.pathcurrent = self.pathcurrent.path_next;
56
57 #else
58     if (vlen(self.origin - self.pathcurrent.origin) < 64)
59         self.pathcurrent = self.pathcurrent.enemy;
60 #endif
61
62     if (self.pathcurrent)
63     {
64
65         self.moveto = self.pathcurrent.origin;
66         self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
67
68         movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4);
69     }
70 }
71
72 void  ewheel_move_enemy()
73 {
74
75     float newframe;
76
77     self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
78
79     //self.steerto = steerlib_standoff(self.enemy.origin,self.target_range_optimal);
80     //self.steerto = steerlib_beamsteer(self.steerto,1024,64,68,256);
81     self.moveto  = self.origin + self.steerto * 128;
82
83     if (self.tur_dist_enemy > self.target_range_optimal)
84     {
85         if ( self.tur_head.spawnshieldtime < 1 )
86         {
87             newframe = ewheel_amin_fwd_fast;
88             movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4);
89         }
90         else if (self.tur_head.spawnshieldtime < 2)
91         {
92
93             newframe = ewheel_amin_fwd_slow;
94             movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4);
95        }
96         else
97         {
98             newframe = ewheel_amin_fwd_slow;
99             movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slower, 0.4);
100         }
101     }
102     else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
103     {
104         newframe = ewheel_amin_bck_slow;
105         movelib_move_simple(v_forward * -1, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4);
106     }
107     else
108     {
109         newframe = ewheel_amin_stop;
110         movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop);
111     }
112
113     turrets_setframe(newframe , false);
114
115     /*if(self.frame != newframe)
116     {
117         self.frame = newframe;
118         self.SendFlags |= TNSF_ANIM;
119         self.anim_start_time = time;
120     }*/
121 }
122
123
124 void ewheel_move_idle()
125 {
126     if(self.frame != 0)
127     {
128         self.SendFlags |= TNSF_ANIM;
129         self.anim_start_time = time;
130     }
131
132     self.frame = 0;
133     if (vlen(self.velocity))
134         movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop);
135 }
136
137 void ewheel_postthink()
138 {
139     float vz;
140     vector wish_angle, real_angle;
141
142     vz = self.velocity.z;
143
144     self.angles_x = anglemods(self.angles.x);
145     self.angles_y = anglemods(self.angles.y);
146
147     fixedmakevectors(self.angles);
148
149     wish_angle = normalize(self.steerto);
150     wish_angle = vectoangles(wish_angle);
151     real_angle = wish_angle - self.angles;
152     real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
153
154     self.tur_head.spawnshieldtime = fabs(real_angle.y);
155     real_angle.y = bound(-self.tur_head.aim_speed, real_angle.y, self.tur_head.aim_speed);
156     self.angles_y = (self.angles.y + real_angle.y);
157
158     if(self.enemy)
159         ewheel_move_enemy();
160     else if(self.pathcurrent)
161         ewheel_move_path();
162     else
163         ewheel_move_idle();
164
165
166     self.velocity_z = vz;
167
168     if(vlen(self.velocity))
169         self.SendFlags |= TNSF_MOVE;
170 }
171
172 void ewheel_respawnhook()
173 {
174     entity e;
175
176     // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
177     if(self.movetype != MOVETYPE_WALK)
178                 return;
179
180     self.velocity = '0 0 0';
181     self.enemy = world;
182
183     setorigin(self, self.pos1);
184
185     if (self.target != "")
186     {
187         e = find(world,targetname,self.target);
188         if (!e)
189         {
190             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
191             self.target = "";
192         }
193
194         if (e.classname != "turret_checkpoint")
195             dprint("Warning: not a turrret path\n");
196         else
197         {
198
199 #ifdef EWHEEL_FANCYPATH
200             self.pathcurrent = WALKER_PATH(self.origin,e.origin);
201             self.pathgoal = e;
202 #else
203             self.pathcurrent  = e;
204 #endif
205         }
206     }
207 }
208
209 void ewheel_diehook()
210 {
211     self.velocity = '0 0 0';
212
213 #ifdef EWHEEL_FANCYPATH
214     if (self.pathcurrent)
215         pathlib_deletepath(self.pathcurrent.owner);
216 #endif
217     self.pathcurrent = world;
218 }
219
220 void turret_ewheel_dinit()
221 {
222     entity e;
223
224     if (self.netname == "")
225         self.netname     = "eWheel Turret";
226
227     if (self.target != "")
228     {
229         e = find(world,targetname,self.target);
230         if (!e)
231         {
232             bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
233             self.target = "";
234         }
235
236         if (e.classname != "turret_checkpoint")
237             dprint("Warning: not a turrret path\n");
238         else
239             self.goalcurrent = e;
240     }
241
242     self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
243     self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM ;
244     self.turret_respawnhook = ewheel_respawnhook;
245
246     self.turret_diehook = ewheel_diehook;
247
248     if (turret_stdproc_init("ewheel_std", "models/turrets/ewheel-base2.md3", "models/turrets/ewheel-gun1.md3", TID_EWHEEL) == 0)
249     {
250         remove(self);
251         return;
252     }
253
254     self.frame = 1;
255     self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
256     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
257     self.iscreature = true;
258     self.teleportable = TELEPORT_NORMAL;
259     self.damagedbycontents = true;
260     self.movetype   = MOVETYPE_WALK;
261     self.solid      = SOLID_SLIDEBOX;
262     self.takedamage = DAMAGE_AIM;
263     self.idle_aim   = '0 0 0';
264     self.pos1       = self.origin;
265
266     setsize(self, '-32 -32 0', '32 32 48');
267
268     // Our fire routine
269     self.turret_firefunc  = ewheel_attack;
270     self.turret_postthink = ewheel_postthink;
271     self.tur_head.frame = 1;
272
273     // Convert from dgr / sec to dgr / tic
274     self.tur_head.aim_speed = autocvar_g_turrets_unit_ewheel_turnrate;
275     self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
276
277     //setorigin(self,self.origin + '0 0 128');
278     if (self.target != "")
279     {
280         e = find(world,targetname,self.target);
281         if (!e)
282         {
283             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
284             self.target = "";
285         }
286
287         if (e.classname != "turret_checkpoint")
288             dprint("Warning: not a turrret path\n");
289         else
290         {
291 #ifdef EWHEEL_FANCYPATH
292             self.pathcurrent = WALKER_PATH(self.origin, e.origin);
293             self.pathgoal = e;
294 #else
295             self.pathcurrent = e;
296 #endif
297         }
298     }
299 }
300
301 void spawnfunc_turret_ewheel()
302 {
303     g_turrets_common_precash();
304
305     precache_model ("models/turrets/ewheel-base2.md3");
306     precache_model ("models/turrets/ewheel-gun1.md3");
307
308     self.think = turret_ewheel_dinit;
309     self.nextthink = time + 0.5;
310 }