]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/tturrets/units/unit_ewheel.qc
Better walker and ewheel.
[divverent/nexuiz.git] / data / qcsrc / server / tturrets / units / unit_ewheel.qc
1 void turret_ewheel_projectile_explode()\r
2 {\r
3     vector org2;\r
4 \r
5     org2 = findbetterlocation (self.origin, 8);\r
6     pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1);\r
7     //w_deathtypestring = "saw the eweel. to late.";\r
8 #ifdef TURRET_DEBUG\r
9     float d;\r
10 \r
11     d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);\r
12     self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;\r
13     self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;\r
14 #else\r
15     RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);\r
16 #endif\r
17     sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);\r
18 \r
19     remove (self);\r
20 }\r
21 \r
22 \r
23 void ewheel_attack()\r
24 {\r
25     entity proj;\r
26     float i;\r
27 \r
28     for (i=0;i<1;++i)\r
29     {\r
30         turret_do_updates(self);\r
31 \r
32         sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM);\r
33         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);\r
34 \r
35         proj                    = spawn ();\r
36         setorigin(proj, self.tur_shotorg);\r
37         //setsize(proj, '-0.5 -0.5 -0.5', '0.5 0.5 0.5');\r
38         //setmodel(proj, "models/laser.mdl"); // precision set above\r
39         proj.classname       = "ewheel bolt";\r
40         proj.owner           = self;\r
41         proj.bot_dodge       = FALSE;\r
42         proj.bot_dodgerating = self.shot_dmg;\r
43         proj.think           = turret_ewheel_projectile_explode;\r
44         proj.nextthink       = time + 9;\r
45         proj.solid           = SOLID_BBOX;\r
46         proj.movetype        = MOVETYPE_FLYMISSILE;\r
47         proj.velocity        = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;\r
48         proj.angles          = vectoangles(proj.velocity);\r
49         proj.touch           = turret_ewheel_projectile_explode;\r
50         //proj.effects         = EF_LOWPRECISION |  EF_BRIGHTFIELD;\r
51         proj.enemy           = self.enemy;\r
52         proj.flags           = FL_PROJECTILE | FL_NOTARGET;\r
53 \r
54         CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);\r
55 \r
56         self.tur_head.frame += 2;\r
57 \r
58         if (self.tur_head.frame > 3)\r
59             self.tur_head.frame = 0;\r
60     }\r
61 \r
62 }\r
63 \r
64 float ewheel_moveverb_path(float eval)\r
65 {\r
66     switch (eval)\r
67     {\r
68     case VCM_EVAL:\r
69 \r
70         if (self.pathcurrent)\r
71             return verb.verb_static_value;\r
72 \r
73         return VS_CALL_NO;\r
74         break;\r
75 \r
76     case VCM_DO:\r
77         // Do we have a path?\r
78         if not(self.pathcurrent)\r
79             return VS_CALL_NO;\r
80         else\r
81         {\r
82             // Are we close enougth to a path node to switch to the next?\r
83             if (vlen(self.origin  - self.pathcurrent.origin) < 32)\r
84                 if (self.pathcurrent.path_next == world)\r
85                 {\r
86                     // Path endpoint reached\r
87                     pathlib_deletepath(self.pathcurrent.owner);\r
88                     self.pathcurrent = world;\r
89 \r
90                     if (self.pathgoal)\r
91                     {\r
92                         if (self.pathgoal.use)\r
93                             self.pathgoal.use();\r
94 \r
95                         if (self.pathgoal.enemy)\r
96                         {\r
97                             self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);\r
98                             self.pathgoal = self.pathgoal.enemy;\r
99                         }\r
100                     }\r
101                     else\r
102                         self.pathgoal = world;\r
103                 }\r
104                 else\r
105                     self.pathcurrent = self.pathcurrent.path_next;\r
106         }\r
107 \r
108 \r
109         if (self.pathcurrent)\r
110         {\r
111             switch (self.waterlevel)\r
112             {\r
113             case 0:\r
114             case 1:\r
115             case 2:\r
116             case 3:\r
117             }\r
118 \r
119             self.moveto = self.pathcurrent.origin;\r
120             self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);\r
121 \r
122             self.frame += 1;\r
123             movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);\r
124 \r
125             return VS_CALL_YES_DOING;\r
126         }\r
127         else\r
128             return VS_CALL_YES_DONE;\r
129 \r
130         break;\r
131 \r
132     case VCM_REMOVE:\r
133 \r
134         if (self.pathcurrent)\r
135             pathlib_deletepath(self.pathcurrent.owner);\r
136 \r
137         self.pathcurrent = world;\r
138 \r
139         return VS_CALL_YES_DONE;\r
140 \r
141         break;\r
142     }\r
143 \r
144     return VS_CALL_YES_DONE;\r
145 }\r
146 \r
147 float ewheel_moveverb_enemy(float eval)\r
148 {\r
149     switch (eval)\r
150     {\r
151     case VCM_EVAL:\r
152             if(self.enemy)\r
153                 return verb.verb_static_value;\r
154 \r
155         return VS_CALL_NO;\r
156 \r
157         break;\r
158 \r
159     case VCM_DO:\r
160 \r
161         self.moveto  = self.enemy.origin;\r
162         self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);\r
163 \r
164         if (self.tur_dist_enemy > self.target_range_optimal)\r
165         {\r
166             if ( self.tur_head.spawnshieldtime < 1 )\r
167             {\r
168                 self.frame += 2;\r
169                 movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);\r
170             }\r
171             else if (self.tur_head.spawnshieldtime < 2)\r
172             {\r
173                 self.frame += 1;\r
174                 movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);\r
175             }\r
176             else\r
177             {\r
178                 self.frame += 1;\r
179                 movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slower"),0.4);\r
180             }\r
181         }\r
182         else if (self.tur_dist_enemy < self.target_range_min)\r
183         {\r
184             self.frame -= 1;\r
185             movelib_move_simple(v_forward * -1,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);\r
186         }\r
187         else\r
188         {\r
189             movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));\r
190         }\r
191 \r
192         return VS_CALL_YES_DOING;\r
193     }\r
194 \r
195 \r
196     return VS_CALL_YES_DONE;\r
197 }\r
198 \r
199 float ewheel_moveverb_runaway(float eval)\r
200 {\r
201     switch (eval)\r
202     {\r
203     case VCM_EVAL:\r
204             if(self.enemy)\r
205             if(self.health < 50)\r
206                 return verb.verb_static_value;\r
207 \r
208             return VS_CALL_NO;\r
209         break;\r
210 \r
211     case VCM_DO:\r
212         self.steerto = (steerlib_push(self.enemy.origin) * 0.7) + (steerlib_traceavoid_flat(0.3, 500, '0 0 128') * 0.3);\r
213         self.moveto  = self.origin + self.steerto * 1000;\r
214 \r
215         self.frame += 2;\r
216         movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);\r
217 \r
218         return VS_CALL_YES_DOING;\r
219 \r
220         break;\r
221     }\r
222 \r
223     return VS_CALL_YES_DONE;\r
224 }\r
225 \r
226 float ewheel_moveverb_idle(float eval)\r
227 {\r
228     switch (eval)\r
229     {\r
230     case VCM_EVAL:\r
231             if(self.enemy)\r
232                 return VS_CALL_NO;\r
233 \r
234         return verb.verb_static_value;\r
235 \r
236         break;\r
237 \r
238     case VCM_DO:\r
239         self.moveto = self.origin;\r
240 \r
241         if(vlen(self.velocity))\r
242             movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));\r
243 \r
244         return VS_CALL_YES_DOING;\r
245     }\r
246 \r
247     return VS_CALL_YES_DONE;\r
248 }\r
249 \r
250 void ewheel_postthink()\r
251 {\r
252     float vz;\r
253     vector wish_angle,real_angle;\r
254 \r
255     vz = self.velocity_z;\r
256 \r
257     self.angles_x = anglemods(self.angles_x);\r
258     self.angles_y = anglemods(self.angles_y);\r
259 \r
260     self.angles_x *= -1;\r
261     makevectors(self.angles);\r
262     self.angles_x *= -1;\r
263 \r
264     wish_angle = normalize(self.steerto);\r
265     wish_angle = vectoangles(wish_angle);\r
266     real_angle = wish_angle - self.angles;\r
267     real_angle = shortangle_vxy(real_angle,self.tur_head.angles);\r
268 \r
269     self.tur_head.spawnshieldtime = fabs(real_angle_y);\r
270     real_angle_y  = bound(self.tur_head.aim_speed * -1,real_angle_y,self.tur_head.aim_speed);\r
271     self.angles_y = (self.angles_y + real_angle_y);\r
272 \r
273     // Simulate banking\r
274     self.angles_z = bound(-45,real_angle_y * -2.5,45);\r
275 \r
276     verbstack_pop(self.verbs_move);\r
277 \r
278     if (self.frame > 40)\r
279         self.frame = 1;\r
280 \r
281     if (self.frame < 1)\r
282         self.frame = 40;\r
283 \r
284 \r
285     self.velocity_z = vz;\r
286 }\r
287 \r
288 void ewheel_respawnhook()\r
289 {\r
290     entity e;\r
291 \r
292     setorigin(self,self.pos1);\r
293 \r
294     if (self.target != "")\r
295     {\r
296         e = find(world,targetname,self.target);\r
297         if (!e)\r
298         {\r
299             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");\r
300             self.target = "";\r
301         }\r
302 \r
303         if (e.classname != "turret_checkpoint")\r
304             dprint("Warning: not a turrret path\n");\r
305         else\r
306         {\r
307             self.pathcurrent = WALKER_PATH(self.origin,e.origin);\r
308             self.pathgoal = e;\r
309         }\r
310     }\r
311 }\r
312 \r
313 void ewheel_diehook()\r
314 {\r
315     turret_trowgib2(self.origin,self.velocity + v_up * 400,'-0.6 -0.2 -02',self,time + random() * 2 +3);\r
316 \r
317     if (self.pathcurrent)\r
318         pathlib_deletepath(self.pathcurrent.owner);\r
319 \r
320     self.pathcurrent = world;\r
321 \r
322     if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)\r
323     {\r
324         verbstack_flush(self.verbs_move);\r
325         remove(self.verbs_move);\r
326     }\r
327 \r
328 }\r
329 \r
330 void turret_ewheel_dinit()\r
331 {\r
332     entity e;\r
333 \r
334     if (self.netname == "")      self.netname     = "eWheel Turret";\r
335 \r
336     if (self.target != "")\r
337     {\r
338         e = find(world,targetname,self.target);\r
339         if (!e)\r
340         {\r
341             bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");\r
342             self.target = "";\r
343         }\r
344 \r
345         if (e.classname != "turret_checkpoint")\r
346             dprint("Warning: not a turrret path\n");\r
347         else\r
348             self.goalcurrent = e;\r
349     }\r
350 \r
351     self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;\r
352     self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_HEADATTACHED;\r
353     //self.aim_flags = TFL_AIM_SIMPLE;// TFL_AIM_LEAD | TFL_AIM_ZEASE;\r
354 \r
355     self.turret_respawnhook = ewheel_respawnhook;\r
356     self.turret_diehook = ewheel_diehook;\r
357 \r
358     if (turret_stdproc_init("ewheel_std") == 0)\r
359     {\r
360         remove(self);\r
361         return;\r
362     }\r
363 \r
364     self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;\r
365     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;\r
366     self.damage_flags          |= TFL_DMG_DEATH_NOGIBS;\r
367 \r
368     self.iscreature = TRUE;\r
369     self.movetype   = MOVETYPE_WALK;\r
370     self.solid      = SOLID_SLIDEBOX;\r
371     self.takedamage = DAMAGE_AIM;\r
372 \r
373     setmodel(self,"models/turrets/ewheel-base.md3");\r
374     setmodel(self.tur_head,"models/turrets/ewheel-gun1.md3");\r
375     setattachment(self.tur_head,self,"tag_head");\r
376 \r
377     self.pos1 = self.origin;\r
378 \r
379     self.idle_aim = '0 0 0';\r
380 \r
381     // Our fire routine\r
382     self.turret_firefunc  = ewheel_attack;\r
383     self.turret_postthink = ewheel_postthink;\r
384     self.tur_head.frame = 1;\r
385 \r
386     self.verbs_move = spawn();\r
387     verbstack_push(self.verbs_move, ewheel_moveverb_idle,   WVM_IDLE,  0);\r
388     verbstack_push(self.verbs_move, ewheel_moveverb_enemy,  WVM_ENEMY, 0);\r
389     verbstack_push(self.verbs_move, ewheel_moveverb_path,   WVM_PATH,  0);\r
390     verbstack_push(self.verbs_move, ewheel_moveverb_runaway,WVM_PANIC,  0);\r
391 \r
392     // Convert from dgr / sec to dgr / tic\r
393     self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");\r
394     self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);\r
395 \r
396     if (self.target != "")\r
397     {\r
398         e = find(world,targetname,self.target);\r
399         if (!e)\r
400         {\r
401             dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");\r
402             self.target = "";\r
403         }\r
404 \r
405         if (e.classname != "turret_checkpoint")\r
406             dprint("Warning: not a turrret path\n");\r
407         else\r
408         {\r
409             self.pathcurrent = WALKER_PATH(self.origin,e.origin);\r
410             self.pathgoal = e;\r
411         }\r
412     }\r
413 }\r
414 \r
415 void spawnfunc_turret_ewheel()\r
416 {\r
417     precache_model ("models/turrets/ewheel-base.md3");\r
418     precache_model ("models/turrets/ewheel-gun1.md3");\r
419 \r
420     self.think = turret_ewheel_dinit;\r
421     self.nextthink = time + 0.5;\r
422 }\r