5 float autocvar_g_turrets_unit_ewheel_speed_fast;
6 float autocvar_g_turrets_unit_ewheel_speed_slow;
7 float autocvar_g_turrets_unit_ewheel_speed_slower;
8 float autocvar_g_turrets_unit_ewheel_speed_stop;
9 float autocvar_g_turrets_unit_ewheel_turnrate;
11 const int ewheel_anim_stop = 0;
12 const int ewheel_anim_fwd_slow = 1;
13 const int ewheel_anim_fwd_fast = 2;
14 const int ewheel_anim_bck_slow = 3;
15 const int ewheel_anim_bck_fast = 4;
17 void ewheel_move_path(entity this)
19 // Are we close enough to a path node to switch to the next?
20 if (vdist(this.origin - this.pathcurrent.origin, <, 64)) {
21 #ifdef EWHEEL_FANCYPATH
22 if (this.pathcurrent.path_next == NULL) {
23 // Path endpoint reached
24 pathlib_deletepath(this.pathcurrent.owner);
25 this.pathcurrent = NULL;
28 if (this.pathgoal.use) {
29 this.pathgoal.use(this.pathgoal, NULL, NULL);
32 if (this.pathgoal.enemy) {
33 this.pathcurrent = pathlib_astar(this, this.pathgoal.origin, this.pathgoal.enemy.origin);
34 this.pathgoal = this.pathgoal.enemy;
40 this.pathcurrent = this.pathcurrent.path_next;
43 this.pathcurrent = this.pathcurrent.enemy;
47 if (this.pathcurrent) {
48 this.moveto = this.pathcurrent.origin;
49 this.steerto = steerlib_attract2(this, this.moveto, 0.5, 500, 0.95);
51 movelib_move_simple(this, v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
55 void ewheel_move_enemy(entity this)
59 this.steerto = steerlib_arrive(this, this.enemy.origin, this.target_range_optimal);
61 this.moveto = this.origin + this.steerto * 128;
63 if (this.tur_dist_enemy > this.target_range_optimal) {
64 if (this.tur_head.spawnshieldtime < 1) {
65 newframe = ewheel_anim_fwd_fast;
66 movelib_move_simple(this, v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
67 } else if (this.tur_head.spawnshieldtime < 2) {
68 newframe = ewheel_anim_fwd_slow;
69 movelib_move_simple(this, v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
71 newframe = ewheel_anim_fwd_slow;
72 movelib_move_simple(this, v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
74 } else if (this.tur_dist_enemy < this.target_range_optimal * 0.5) {
75 newframe = ewheel_anim_bck_slow;
76 movelib_move_simple(this, v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
78 newframe = ewheel_anim_stop;
79 movelib_brake_simple(this, (autocvar_g_turrets_unit_ewheel_speed_stop));
82 turrets_setframe(this, newframe, false);
85 void ewheel_move_idle(entity this)
87 if (this.frame != 0) {
88 this.SendFlags |= TNSF_ANIM;
89 this.anim_start_time = time;
94 movelib_brake_simple(this, (autocvar_g_turrets_unit_ewheel_speed_stop));
98 void ewheel_findtarget(entity this)
100 entity e = find(NULL, targetname, this.target);
102 LOG_TRACE("Initital waypoint for ewheel does NOT exist, fix your map!");
106 if (e.classname != "turret_checkpoint") {
107 LOG_TRACE("Warning: not a turret path");
109 #ifdef EWHEEL_FANCYPATH
110 this.pathcurrent = pathlib_astar(this, this.origin, e.origin);
113 this.pathcurrent = e;
118 spawnfunc(turret_ewheel)
120 if (!turret_initialize(this, TUR_EWHEEL)) {
125 METHOD(EWheel, tr_think, void(EWheel thistur, entity it))
127 vector wish_angle, real_angle;
129 float vz = it.velocity_z;
131 it.angles_x = anglemods(it.angles_x);
132 it.angles_y = anglemods(it.angles_y);
134 fixedmakevectors(it.angles);
136 wish_angle = normalize(it.steerto);
137 wish_angle = vectoangles(wish_angle);
138 real_angle = wish_angle - it.angles;
139 real_angle = shortangle_vxy(real_angle, it.tur_head.angles);
141 it.tur_head.spawnshieldtime = fabs(real_angle_y);
142 real_angle_y = bound(-it.tur_head.aim_speed, real_angle_y, it.tur_head.aim_speed);
143 it.angles_y = (it.angles_y + real_angle_y);
146 ewheel_move_enemy(it);
147 } else if (it.pathcurrent) {
148 ewheel_move_path(it);
150 ewheel_move_idle(it);
156 it.SendFlags |= TNSF_MOVE;
160 METHOD(EWheel, tr_death, void(EWheel this, entity it))
162 it.velocity = '0 0 0';
164 #ifdef EWHEEL_FANCYPATH
165 if (it.pathcurrent) {
166 pathlib_deletepath(it.pathcurrent.owner);
169 it.pathcurrent = NULL;
172 METHOD(EWheel, tr_setup, void(EWheel this, entity it))
174 if (it.move_movetype == MOVETYPE_WALK) {
175 it.velocity = '0 0 0';
178 setorigin(it, it.pos1);
180 if (it.target != "") {
181 InitializeEntity(it, ewheel_findtarget, INITPRIO_FINDTARGET);
185 it.iscreature = true;
186 it.teleportable = TELEPORT_NORMAL;
187 if (!it.damagedbycontents) {
188 IL_PUSH(g_damagedbycontents, it);
190 it.damagedbycontents = true;
191 set_movetype(it, MOVETYPE_WALK);
192 it.solid = SOLID_SLIDEBOX;
193 it.takedamage = DAMAGE_AIM;
194 it.idle_aim = '0 0 0';
196 it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
197 it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
198 it.frame = it.tur_head.frame = 1;
199 it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
201 // Convert from dgr / sec to dgr / tic
202 it.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
203 it.tur_head.aim_speed = it.tur_head.aim_speed / (1 / it.ticrate);
209 void ewheel_draw(entity this)
213 dt = time - this.move_time;
214 this.move_time = time;
219 fixedmakevectors(this.angles);
220 setorigin(this, this.origin + this.velocity * dt);
221 this.tur_head.angles += dt * this.tur_head.avelocity;
223 if (this.health < 127) {
224 if (random() < 0.05) {
225 te_spark(this.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
230 METHOD(EWheel, tr_setup, void(EWheel this, entity it))
233 set_movetype(it, MOVETYPE_BOUNCE);
235 it.draw = ewheel_draw;