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