seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead; set to 2 to active the effect only when the corpse doesn't move anymore"
seta cl_eventchase_nexball 1 "camera goes into 3rd person mode when in nexball game-mode"
seta cl_eventchase_distance 140 "final camera distance"
+seta cl_eventchase_generator_distance 400 "final camera distance while viewing generator explosion"
seta cl_eventchase_speed 1.3 "how fast the camera slides back, 0 is instant"
seta cl_eventchase_maxs "12 12 8" "max size of eventchase camera bbox"
seta cl_eventchase_mins "-12 -12 -8" "min size of eventchase camera bbox"
seta cl_eventchase_viewoffset "0 0 20" "viewoffset of eventchase camera"
+seta cl_eventchase_generator_viewoffset "0 0 80" "viewoffset of eventchase camera while viewing generator explosion"
//nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining
set teamplay_lockonrestart 0 "it set to 1 in a team-based game, the teams are locked once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)"
set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed"
-// fragmessage: This allows extra information to be displayed with the frag centerprints.
-set sv_fraginfo 1 "Enable extra frag message information, 0 = Never display, 1 = Display only in warmup mode; 2 = Always display"
-set sv_fraginfo_ping 1 "Enable ping display information, 0 = Never display, 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
-set sv_fraginfo_handicap 1 "Enable handicap display information, 0 = Never display, 1 = Only when the player has handicap on, 2 = Always display (Displays Off if disabled)"
-set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0 = Never display, 1 = Always display (Only available for the person who was killed)"
-
// use default physics
set sv_friction_on_land 0
set sv_friction_slick 0.5
// onslaught
// ===========
set g_onslaught 0 "Onslaught: take control points towards the enemy generator and then destroy it"
+set g_onslaught_point_limit 1 "Onslaught point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_onslaught_warmup 5
+set g_onslaught_round_timelimit 280
+set g_onslaught_debug 0 "show debug prints in onslaught"
+set g_onslaught_teleport_radius 200 "Allows teleporting from a control point to another"
+set g_onslaught_teleport_wait 5 "Time before player can teleport again"
+set g_onslaught_spawn_choose 1 "Allow players to choose the control point to be spawned at"
+set g_onslaught_click_radius 500 "When choosing from the map, this level of precision is required"
+
set g_onslaught_gen_health 2500
+set g_onslaught_allow_vehicle_touch 0
set g_onslaught_cp_health 1000
set g_onslaught_cp_buildhealth 100
set g_onslaught_cp_buildtime 5
set g_onslaught_cp_proxydecap 0 "de-capture controlpoints by standing close to them"
set g_onslaught_cp_proxydecap_distance 512
set g_onslaught_cp_proxydecap_dps 100
+set g_onslaught_shield_force 100
set g_onslaught_spawn_at_controlpoints 0
+set g_onslaught_spawn_at_controlpoints_chance 0.5
+set g_onslaught_spawn_at_controlpoints_random 0
set g_onslaught_spawn_at_generator 0
+set g_onslaught_spawn_at_generator_chance 0
+set g_onslaught_spawn_at_generator_random 0
// ======
float autocvar_cl_hitsound_antispam_time;
int autocvar_cl_eventchase_death = 1;
int autocvar_cl_eventchase_nexball = 1;
+vector autocvar_cl_eventchase_generator_viewoffset = '0 0 80';
+float autocvar_cl_eventchase_generator_distance = 400;
float autocvar_cl_eventchase_distance = 140;
float autocvar_cl_eventchase_speed = 1.3;
vector autocvar_cl_eventchase_maxs = '12 12 8';
case "radar":
{
if(argv(2))
- hud_panel_radar_maximized = InterpretBoolean(argv(2));
+ HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)),0);
else
- hud_panel_radar_maximized = !hud_panel_radar_maximized;
+ HUD_Radar_Show_Maximized(!hud_panel_radar_maximized,0);
+ return;
+ }
+
+ case "clickradar":
+ {
+ HUD_Radar_Show_Maximized(!hud_panel_radar_mouse,1);
return;
}
}
--- /dev/null
+#include "controlpoint.qh"
+#include "gibs.qh"
+#include "teamradar.qh"
+
+bool cpicon_precached;
+.int count;
+.float pain_finished;
+
+.bool iscaptured;
+
+.vector cp_origin, cp_bob_origin;
+.float cp_bob_spd;
+
+.vector cp_bob_dmg;
+
+.vector punchangle;
+
+.float max_health;
+
+.entity icon_realmodel;
+
+void cpicon_precache()
+{
+ if(cpicon_precached)
+ return; // already precached
+
+ precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
+ precache_model("models/onslaught/controlpoint_icon.md3");
+
+ cpicon_precached = true;
+}
+
+void cpicon_draw()
+{
+ if(time < self.move_time) { return; }
+
+ if(self.cp_bob_dmg_z > 0)
+ self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * frametime;
+ else
+ self.cp_bob_dmg_z = 0;
+ self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
+ self.cp_bob_spd = self.cp_bob_spd + 1.875 * frametime;
+ self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+
+ if(!self.iscaptured) self.alpha = self.health / self.max_health;
+
+ if(self.iscaptured)
+ {
+ if (self.punchangle_x > 0)
+ {
+ self.punchangle_x = self.punchangle_x - 60 * frametime;
+ if (self.punchangle_x < 0)
+ self.punchangle_x = 0;
+ }
+ else if (self.punchangle_x < 0)
+ {
+ self.punchangle_x = self.punchangle_x + 60 * frametime;
+ if (self.punchangle_x > 0)
+ self.punchangle_x = 0;
+ }
+
+ if (self.punchangle_y > 0)
+ {
+ self.punchangle_y = self.punchangle_y - 60 * frametime;
+ if (self.punchangle_y < 0)
+ self.punchangle_y = 0;
+ }
+ else if (self.punchangle_y < 0)
+ {
+ self.punchangle_y = self.punchangle_y + 60 * frametime;
+ if (self.punchangle_y > 0)
+ self.punchangle_y = 0;
+ }
+
+ if (self.punchangle_z > 0)
+ {
+ self.punchangle_z = self.punchangle_z - 60 * frametime;
+ if (self.punchangle_z < 0)
+ self.punchangle_z = 0;
+ }
+ else if (self.punchangle_z < 0)
+ {
+ self.punchangle_z = self.punchangle_z + 60 * frametime;
+ if (self.punchangle_z > 0)
+ self.punchangle_z = 0;
+ }
+
+ self.angles_x = self.punchangle_x;
+ self.angles_y = self.punchangle_y + self.move_angles_y;
+ self.angles_z = self.punchangle_z;
+ self.move_angles_y = self.move_angles_y + 45 * frametime;
+ }
+
+ setorigin(self, self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
+}
+
+void cpicon_damage(float hp)
+{
+ if(!self.iscaptured) { return; }
+
+ if(hp < self.max_health * 0.25)
+ setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
+ else if(hp < self.max_health * 0.50)
+ setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
+ else if(hp < self.max_health * 0.75)
+ setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
+ else if(hp <= self.max_health || hp >= self.max_health)
+ setmodel(self, "models/onslaught/controlpoint_icon.md3");
+
+ self.punchangle = (2 * randomvec() - '1 1 1') * 45;
+
+ self.cp_bob_dmg_z = (2 * random() - 1) * 15;
+ self.pain_finished = time + 1;
+ self.colormod = '2 2 2';
+
+ setsize(self, CPICON_MIN, CPICON_MAX);
+}
+
+void cpicon_construct()
+{
+ self.netname = "Control Point Icon";
+
+ setmodel(self, "models/onslaught/controlpoint_icon.md3");
+ setsize(self, CPICON_MIN, CPICON_MAX);
+
+ if(self.icon_realmodel == world)
+ {
+ self.icon_realmodel = spawn();
+ setmodel(self.icon_realmodel, "null");
+ setorigin(self.icon_realmodel, self.origin);
+ setsize(self.icon_realmodel, CPICON_MIN, CPICON_MAX);
+ self.icon_realmodel.movetype = MOVETYPE_NOCLIP;
+ self.icon_realmodel.solid = SOLID_NOT;
+ self.icon_realmodel.move_origin = self.icon_realmodel.origin;
+ }
+
+ if(self.iscaptured) { self.icon_realmodel.solid = SOLID_BBOX; }
+
+ self.move_movetype = MOVETYPE_NOCLIP;
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.drawmask = MASK_NORMAL;
+ self.alpha = 1;
+ self.draw = cpicon_draw;
+ self.cp_origin = self.origin;
+ self.cp_bob_origin = '0 0 0.1';
+ self.cp_bob_spd = 0;
+}
+
+.vector glowmod;
+void cpicon_changeteam()
+{
+ if(self.team)
+ {
+ self.glowmod = Team_ColorRGB(self.team - 1);
+ self.teamradar_color = Team_ColorRGB(self.team - 1);
+ self.colormap = 1024 + (self.team - 1) * 17;
+ }
+ else
+ {
+ self.colormap = 1024;
+ self.glowmod = '1 1 0';
+ self.teamradar_color = '1 1 0';
+ }
+}
+
+void ent_cpicon()
+{
+ int sf = ReadByte();
+
+ if(sf & CPSF_SETUP)
+ {
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.health = ReadByte();
+ self.max_health = ReadByte();
+ self.count = ReadByte();
+ self.team = ReadByte();
+ self.iscaptured = ReadByte();
+
+ if(!self.count)
+ self.count = (self.health - self.max_health) * frametime;
+
+ cpicon_changeteam();
+ cpicon_precache();
+ cpicon_construct();
+ }
+
+ if(sf & CPSF_STATUS)
+ {
+ int _tmp = ReadByte();
+ if(_tmp != self.team)
+ {
+ self.team = _tmp;
+ cpicon_changeteam();
+ }
+
+ _tmp = ReadByte();
+
+ if(_tmp != self.health)
+ cpicon_damage(_tmp);
+
+ self.health = _tmp;
+ }
+}
--- /dev/null
+#ifndef CONTROLPOINT_H
+#define CONTROLPOINT_H
+
+const vector CPICON_MIN = '-32 -32 -9';
+const vector CPICON_MAX = '32 32 25';
+
+const int CPSF_STATUS = 4;
+const int CPSF_SETUP = 8;
+
+void ent_cpicon();
+void cpicon_precache();
+
+#endif
#include "gibs.qh"
#include "prandom.qh"
-#include "../common/vehicles/cl_vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_TURRET_WALK_MEELE:
+ case DEATH_TURRET_WALK_MELEE:
sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("TE_SPARK"), self.origin, w_backoff * 1000, 1);
break;
--- /dev/null
+#include "generator.qh"
+
+bool generator_precached;
+.int count;
+.float max_health;
+
+vector randompos(vector m1, vector m2)
+{
+ vector v;
+ m2 = m2 - m1;
+ v_x = m2_x * random() + m1_x;
+ v_y = m2_y * random() + m1_y;
+ v_z = m2_z * random() + m1_z;
+ return v;
+}
+
+void generator_precache()
+{
+ if(generator_precached)
+ return; // already precached
+
+ precache_model("models/onslaught/generator.md3");
+ precache_model("models/onslaught/generator_dead.md3");
+ precache_model("models/onslaught/generator_dmg1.md3");
+ precache_model("models/onslaught/generator_dmg2.md3");
+ precache_model("models/onslaught/generator_dmg3.md3");
+ precache_model("models/onslaught/generator_dmg4.md3");
+ precache_model("models/onslaught/generator_dmg5.md3");
+ precache_model("models/onslaught/generator_dmg6.md3");
+ precache_model("models/onslaught/generator_dmg7.md3");
+ precache_model("models/onslaught/generator_dmg8.md3");
+ precache_model("models/onslaught/generator_dmg9.md3");
+ precache_model("models/onslaught/generator_dead.md3");
+
+ precache_model("models/onslaught/ons_ray.md3");
+ precache_sound("onslaught/shockwave.wav");
+ precache_sound("weapons/grenade_impact.wav");
+ precache_sound("weapons/rocket_impact.wav");
+ precache_sound("onslaught/electricity_explode.wav");
+
+ generator_precached = true;
+}
+
+void ons_generator_ray_draw()
+{
+ if(time < self.move_time)
+ return;
+
+ self.move_time = time + 0.05;
+
+ if(self.count > 10)
+ {
+ remove(self);
+ return;
+ }
+
+ if(self.count > 5)
+ self.alpha -= 0.1;
+ else
+ self.alpha += 0.1;
+
+ self.scale += 0.2;
+ self.count +=1;
+}
+
+void ons_generator_ray_spawn(vector org)
+{
+ entity e;
+ e = spawn();
+ e.classname = "ons_ray";
+ setmodel(e, "models/onslaught/ons_ray.md3");
+ setorigin(e, org);
+ e.angles = randomvec() * 360;
+ e.move_origin = org;
+ e.movetype = MOVETYPE_NONE;
+ e.alpha = 0;
+ e.scale = random() * 5 + 8;
+ e.move_time = time + 0.05;
+ e.drawmask = MASK_NORMAL;
+ e.draw = ons_generator_ray_draw;
+}
+
+void generator_draw()
+{
+ if(time < self.move_time)
+ return;
+
+ if(self.health > 0)
+ {
+ // damaged fx (less probable the more damaged is the generator)
+ if(random() < 0.9 - self.health / self.max_health)
+ if(random() < 0.01)
+ {
+ pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
+ sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
+ }
+ else
+ pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
+
+ self.move_time = time + 0.1;
+
+ return;
+ }
+
+ if(self.count <= 0)
+ return;
+
+ vector org;
+ int i;
+
+ // White shockwave
+ if(self.count==40||self.count==20)
+ {
+ sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("electro_combo"), self.origin, '0 0 0', 6);
+ }
+
+ // rays
+ if(random() > 0.25)
+ {
+ ons_generator_ray_spawn(self.origin);
+ }
+
+ // Spawn fire balls
+ for(i=0;i < 10;++i)
+ {
+ org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
+ pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
+ }
+
+ // Short explosion sound + small explosion
+ if(random() < 0.25)
+ {
+ te_explosion(self.origin);
+ sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
+ }
+
+ // Particles
+ org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
+ pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
+
+ // Final explosion
+ if(self.count==1)
+ {
+ org = self.origin;
+ te_explosion(org);
+ pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
+ sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ }
+
+ self.move_time = time + 0.05;
+
+ self.count -= 1;
+}
+
+void generator_damage(float hp)
+{
+ if(hp <= 0)
+ setmodel(self, "models/onslaught/generator_dead.md3");
+ else if(hp < self.max_health * 0.10)
+ setmodel(self, "models/onslaught/generator_dmg9.md3");
+ else if(hp < self.max_health * 0.20)
+ setmodel(self, "models/onslaught/generator_dmg8.md3");
+ else if(hp < self.max_health * 0.30)
+ setmodel(self, "models/onslaught/generator_dmg7.md3");
+ else if(hp < self.max_health * 0.40)
+ setmodel(self, "models/onslaught/generator_dmg6.md3");
+ else if(hp < self.max_health * 0.50)
+ setmodel(self, "models/onslaught/generator_dmg5.md3");
+ else if(hp < self.max_health * 0.60)
+ setmodel(self, "models/onslaught/generator_dmg4.md3");
+ else if(hp < self.max_health * 0.70)
+ setmodel(self, "models/onslaught/generator_dmg3.md3");
+ else if(hp < self.max_health * 0.80)
+ setmodel(self, "models/onslaught/generator_dmg2.md3");
+ else if(hp < self.max_health * 0.90)
+ setmodel(self, "models/onslaught/generator_dmg1.md3");
+ else if(hp <= self.max_health || hp >= self.max_health)
+ setmodel(self, "models/onslaught/generator.md3");
+
+ setsize(self, GENERATOR_MIN, GENERATOR_MAX);
+}
+
+void generator_construct()
+{
+ self.netname = "Generator";
+ self.classname = "onslaught_generator";
+
+ setorigin(self, self.origin);
+ setmodel(self, "models/onslaught/generator.md3");
+ setsize(self, GENERATOR_MIN, GENERATOR_MAX);
+
+ self.move_movetype = MOVETYPE_NOCLIP;
+ self.solid = SOLID_BBOX;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.drawmask = MASK_NORMAL;
+ self.alpha = 1;
+ self.draw = generator_draw;
+}
+
+.vector glowmod;
+void generator_changeteam()
+{
+ if(self.team)
+ {
+ self.glowmod = Team_ColorRGB(self.team - 1);
+ self.teamradar_color = Team_ColorRGB(self.team - 1);
+ self.colormap = 1024 + (self.team - 1) * 17;
+ }
+ else
+ {
+ self.colormap = 1024;
+ self.glowmod = '1 1 0';
+ self.teamradar_color = '1 1 0';
+ }
+}
+
+void ent_generator()
+{
+ int sf = ReadByte();
+
+ if(sf & GSF_SETUP)
+ {
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.health = ReadByte();
+ self.max_health = ReadByte();
+ self.count = ReadByte();
+ self.team = ReadByte();
+
+ if(!self.count)
+ self.count = 40;
+
+ generator_changeteam();
+ generator_precache();
+ generator_construct();
+ }
+
+ if(sf & GSF_STATUS)
+ {
+ int _tmp;
+ _tmp = ReadByte();
+ if(_tmp != self.team)
+ {
+ self.team = _tmp;
+ generator_changeteam();
+ }
+
+ _tmp = ReadByte();
+
+ if(_tmp != self.health)
+ generator_damage(_tmp);
+
+ self.health = _tmp;
+ }
+}
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+const vector GENERATOR_MIN = '-52 -52 -14';
+const vector GENERATOR_MAX = '52 52 75';
+
+const int GSF_STATUS = 4;
+const int GSF_SETUP = 8;
+
+void ent_generator();
+void generator_precache();
+#endif
#include "_all.qh"
#include "hud_config.qh"
+#include "mapvoting.qh"
#include "scoreboard.qh"
#include "sortlist.qh"
#include "teamradar.qh"
#include "t_items.qh"
+#include "../dpdefs/keycodes.qh"
+
#include "../common/buffs.qh"
#include "../common/constants.qh"
#include "../common/counting.qh"
// Radar (#6)
//
+
+float HUD_Radar_Clickable()
+{
+ return hud_panel_radar_mouse && !hud_panel_radar_temp_hidden;
+}
+
+void HUD_Radar_Show_Maximized(bool doshow,float clickable)
+{
+ hud_panel_radar_maximized = doshow;
+ hud_panel_radar_temp_hidden = 0;
+
+ if ( doshow )
+ {
+ if (clickable)
+ {
+ if(autocvar_hud_cursormode)
+ setcursormode(1);
+ hud_panel_radar_mouse = 1;
+ }
+ }
+ else if ( hud_panel_radar_mouse )
+ {
+ hud_panel_radar_mouse = 0;
+ mouseClicked = 0;
+ if(autocvar_hud_cursormode)
+ if(!mv_active)
+ setcursormode(0);
+ }
+}
+void HUD_Radar_Hide_Maximized()
+{
+ HUD_Radar_Show_Maximized(false,false);
+}
+
+
+float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
+{
+ if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
+ autocvar__hud_configure || mv_active)
+ return false;
+
+ if(bInputType == 3)
+ {
+ mousepos_x = nPrimary;
+ mousepos_y = nSecondary;
+ return true;
+ }
+
+ if(nPrimary == K_MOUSE1)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE1;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE1);
+ }
+ else if(nPrimary == K_MOUSE2)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE2;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE2);
+ }
+ else if ( nPrimary == K_ESCAPE && bInputType == 0 )
+ {
+ HUD_Radar_Hide_Maximized();
+ }
+ else
+ {
+ // allow console/use binds to work without hiding the map
+ string con_keys;
+ float keys;
+ float i;
+ con_keys = strcat(findkeysforcommand("toggleconsole", 0)," ",findkeysforcommand("+use", 0)) ;
+ keys = tokenize(con_keys); // findkeysforcommand returns data for this
+ for (i = 0; i < keys; ++i)
+ {
+ if(nPrimary == stof(argv(i)))
+ return false;
+ }
+
+ if ( getstati(STAT_HEALTH) <= 0 )
+ {
+ // Show scoreboard
+ if ( bInputType < 2 )
+ {
+ con_keys = findkeysforcommand("+showscores", 0);
+ keys = tokenize(con_keys);
+ for (i = 0; i < keys; ++i)
+ {
+ if ( nPrimary == stof(argv(i)) )
+ {
+ hud_panel_radar_temp_hidden = bInputType == 0;
+ return false;
+ }
+ }
+ }
+ }
+ else if ( bInputType == 0 )
+ HUD_Radar_Hide_Maximized();
+
+ return false;
+ }
+
+ return true;
+}
+
+void HUD_Radar_Mouse()
+{
+ if ( !hud_panel_radar_mouse ) return;
+ if(mv_active) return;
+
+ if ( intermission )
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+ if(mouseClicked & S_MOUSE2)
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+ if(!autocvar_hud_cursormode)
+ {
+ mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
+
+ mousepos_x = bound(0, mousepos_x, vid_conwidth);
+ mousepos_y = bound(0, mousepos_y, vid_conheight);
+ }
+
+ HUD_Panel_UpdateCvars();
+
+
+ panel_size = autocvar_hud_panel_radar_maximized_size;
+ panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth;
+ panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight;
+ panel_pos_x = (vid_conwidth - panel_size_x) / 2;
+ panel_pos_y = (vid_conheight - panel_size_y) / 2;
+
+ if(mouseClicked & S_MOUSE1)
+ {
+ // click outside
+ if ( mousepos_x < panel_pos_x || mousepos_x > panel_pos_x + panel_size_x ||
+ mousepos_y < panel_pos_y || mousepos_y > panel_pos_y + panel_size_y )
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+ vector pos = teamradar_texcoord_to_3dcoord(teamradar_2dcoord_to_texcoord(mousepos),view_origin_z);
+ localcmd(sprintf("cmd ons_spawn %f %f %f",pos_x,pos_y,pos_z));
+
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+
+ const vector cursor_size = '32 32 0';
+ drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursor_size, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+}
+
void HUD_Radar(void)
{
if(intermission == 2) return;
}
}
+ if ( hud_panel_radar_temp_hidden )
+ return;
+
HUD_Panel_UpdateCvars();
float f = 0;
for(tm = world; (tm = find(tm, classname, "radarlink")); )
draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+
+ vector coord;
+ vector brightcolor;
for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
+ {
+ if ( hud_panel_radar_mouse )
+ if ( tm.health > 0 )
+ if ( tm.team == myteam+1 )
+ {
+ coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
+ if ( vlen(mousepos-coord) < 8 )
+ {
+ brightcolor_x = min(1,tm.teamradar_color_x*1.5);
+ brightcolor_y = min(1,tm.teamradar_color_y*1.5);
+ brightcolor_z = min(1,tm.teamradar_color_z*1.5);
+ drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
+ }
+ }
+
draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+ }
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
color2 = GetPlayerColor(tm.sv_entnum);
draw_teamradar_player(view_origin, view_angles, '1 1 1');
drawresetcliparea();
+
+ if ( hud_panel_radar_mouse )
+ {
+ string message = "Click to select teleport destination";
+
+ if ( getstati(STAT_HEALTH) <= 0 )
+ {
+ message = "Click to select spawn location";
+ }
+
+ drawcolorcodedstring(pos + '0.5 0 0' * (mySize_x - stringwidth(message, true, hud_fontsize)) - '0 1 0' * hud_fontsize_y * 2,
+ message, hud_fontsize, hud_panel_radar_foreground_alpha, DRAWFLAG_NORMAL);
+
+ hud_panel_radar_bottom = pos_y + mySize_y + hud_fontsize_y;
+ }
}
// Score (#7)
}
HUD_Panel_UpdateCvars();
- if(scoreboard_fade_alpha)
+ if ( HUD_Radar_Clickable() )
+ {
+ if (hud_panel_radar_bottom >= 0.96 * vid_conheight)
+ return;
+
+ panel_pos = eY * hud_panel_radar_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
+ panel_size_y = min(panel_size_y, vid_conheight - hud_panel_radar_bottom);
+ }
+ else if(scoreboard_fade_alpha)
{
hud_fade_alpha = hud_fade_alpha_save;
int panel_order[HUD_PANEL_MAX];
string hud_panelorder_prev;
+bool hud_draw_maximized;
+bool hud_panel_radar_maximized;
+bool hud_panel_radar_mouse;
+float hud_panel_radar_bottom;
+bool hud_panel_radar_temp_hidden;
+bool chat_panel_modified;
+bool radar_panel_modified;
+
+void HUD_Radar_Hide_Maximized();
+
void HUD_Reset (void);
void HUD_Main (void);
float vote_alpha;
float vote_change; // "time" when vote_active changed
-float hud_draw_maximized;
-float hud_panel_radar_maximized;
-float chat_panel_modified;
-float radar_panel_modified;
-
vector mousepos;
vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
vector panel_click_resizeorigin; // coordinates for opposite point when resizing
}
}
-const int S_MOUSE1 = 1;
-const int S_MOUSE2 = 2;
-const int S_MOUSE3 = 4;
-int mouseClicked;
-int prevMouseClicked; // previous state
-float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks
-vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks
-
void HUD_Panel_EnableMenu();
entity tab_panels[HUD_PANEL_MAX];
entity tab_panel;
float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary);
+const int S_MOUSE1 = 1;
+const int S_MOUSE2 = 2;
+const int S_MOUSE3 = 4;
+int mouseClicked;
+int prevMouseClicked; // previous state
+float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks
+vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks
+
#endif
#include "_all.qh"
#include "casings.qh"
+#include "controlpoint.qh"
#include "csqcmodel_hooks.qh"
#include "damage.qh"
#include "effects.qh"
+#include "generator.qh"
#include "gibs.qh"
#include "hook.qh"
#include "hud.qh"
#include "scoreboard.qh"
#include "shownames.qh"
#include "sortlist.qh"
-#include "tturrets.qh"
#include "tuba.qh"
#include "t_items.qh"
#include "wall.qh"
#include "waypointsprites.qh"
-#include "../common/vehicles/unit/bumblebee.qh"
-#include "../common/vehicles/cl_vehicles.qh"
-#include "../common/vehicles/vehicles.qh"
+#include "../common/vehicles/all.qh"
+
+#include "mutators/events.qh"
#include "weapons/projectile.qh"
#include "../common/triggers/include.qh"
+#include "../common/turrets/cl_turrets.qh"
+#include "../common/turrets/turrets.qh"
+
#include "../warpzonelib/client.qh"
// --------------------------------------------------------------------------
// needs to be done so early because of the constants they create
static_init();
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
CALL_ACCUMULATED_FUNCTION(RegisterEffects);
- CALL_ACCUMULATED_FUNCTION(RegisterVehicles);
WaypointSprite_Load();
precache_sound("misc/hit.wav");
precache_sound("misc/typehit.wav");
+ generator_precache();
Projectile_Precache();
Hook_Precache();
GibSplash_Precache();
Casings_Precache();
- turrets_precache();
Tuba_Precache();
CSQCPlayer_Precache();
if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
return true;
+ if ( HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary) )
+ return true;
+
if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
return true;
button_zoom = false;
}
}
-
+ HUD_Radar_Hide_Maximized();
//printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
}
case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
case ENT_CLIENT_TURRET: ent_turret(); break;
+ case ENT_CLIENT_GENERATOR: ent_generator(); break;
+ case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
float CSQC_Parse_TempEntity()
{
- float bHandled;
- bHandled = true;
// Acquire TE ID
- float nTEID;
- nTEID = ReadByte();
+ int nTEID = ReadByte();
- if(autocvar_developer_csqcentities)
+ if (autocvar_developer_csqcentities)
printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
- // NOTE: Could just do return instead of break...
- switch(nTEID)
+ switch (nTEID)
{
+ case TE_CSQC_MUTATOR:
+ int mutID = ReadMutator();
+ if (MUTATOR_CALLHOOK(CSQC_Parse_TempEntity, mutID))
+ return true;
case TE_CSQC_TARGET_MUSIC:
Net_TargetMusic();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_PICTURE:
Net_MapVote_Picture();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_RACE:
Net_ReadRace();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_VORTEXBEAMPARTICLE:
Net_ReadVortexBeamParticle();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_TEAMNAGGER:
Net_TeamNagger();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_ARC:
Net_ReadArc();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_PINGPLREPORT:
Net_ReadPingPLReport();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_WEAPONCOMPLAIN:
Net_WeaponComplain();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_VEHICLESETUP:
Net_VehicleSetup();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_SVNOTICE:
cl_notice_read();
- bHandled = true;
- break;
+ return true;
case TE_CSQC_SHOCKWAVEPARTICLE:
Net_ReadShockwaveParticle();
- bHandled = true;
- break;
+ return true;
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
- bHandled = false;
- break;
+ return false;
}
-
- return bHandled;
}
string getcommandkey(string text, string command)
float hud;
float view_quality;
int framecount;
+.float health;
+
#endif
int mv_num_maps;
-float mv_active;
string mv_maps[MAPVOTE_COUNT];
string mv_pics[MAPVOTE_COUNT];
string mv_pk3[MAPVOTE_COUNT]; // map pk3 name or gametype human readable name
void Ent_MapVote();
void Net_MapVote_Picture();
+
+float mv_active;
#endif
/**/
MUTATOR_HOOKABLE(CSQC_ConsoleCommand, EV_CSQC_ConsoleCommand);
+/* Called when the crosshair is being updated */
+MUTATOR_HOOKABLE(UpdateCrosshair, EV_NO_ARGS);
+
+/**
+ * Called when a temp entity is parsed
+ * NOTE: hooks MUST start with `if (MUTATOR_RETURNVALUE) return false;`
+ * NOTE: hooks MUST start with `if (!ReadMutatorEquals(mutator_argv_int_0, name_of_mutator)) return false;`
+ * NOTE: return true if you handled the command, return false to continue handling
+ */
+#define EV_CSQC_Parse_TempEntity(i, o) \
+ /** entity id */ i(int, mutator_argv_int_0) \
+ /**/
+MUTATOR_HOOKABLE(CSQC_Parse_TempEntity, EV_CSQC_Parse_TempEntity);
+
#endif
announcer.qc
bgmscript.qc
casings.qc
+controlpoint.qc
csqcmodel_hooks.qc
damage.qc
effects.qc
+generator.qc
gibs.qc
hook.qc
hud.qc
shownames.qc
sortlist.qc
teamradar.qc
-tturrets.qc
tuba.qc
t_items.qc
view.qc
../common/viewloc.qc
../common/items/all.qc
-
../common/monsters/all.qc
+../common/mutators/all.qc
+../common/vehicles/all.qc
+../common/weapons/all.qc
-../common/weapons/all.qc // TODO
+../common/turrets/cl_turrets.qc
+../common/turrets/turrets.qc
../common/triggers/include.qc
../csqcmodellib/cl_player.qc
../csqcmodellib/interpolate.qc
-../common/vehicles/vehicles_include.qc
-
../server/mutators/mutator_multijump.qc
../warpzonelib/anglestransform.qc
#define HUD_DefaultColumnLayout() \
"ping pl name | " \
"-teams,race,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,race,ka/suicides +ft,tdm/suicides -race,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
-"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns " \
+"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
"+lms/lives +lms/rank " \
"+kh/caps +kh/pushes +kh/destroyed " \
"?+race/laps ?+race/time ?+race/fastest " \
float HUD_WouldDrawScoreboard() {
if (autocvar__hud_configure)
return 0;
+ else if (HUD_Radar_Clickable())
+ return 0;
else if (scoreboard_showscores)
return 1;
else if (intermission == 1)
return out;
}
+
+vector teamradar_2dcoord_to_texcoord(vector in)
+{
+ vector out;
+ out = in;
+
+ out -= teamradar_origin2d;
+ if(v_flipped)
+ out_x = -out_x;
+ out = out / teamradar_size;
+
+ out_y = - out_y; // screen space is reversed
+ out = rotate(out, -teamradar_angle * DEG2RAD);
+
+ out += teamradar_origin3d_in_texcoord;
+
+ return out;
+}
+
+vector teamradar_texcoord_to_3dcoord(vector in,float z)
+{
+ vector out;
+ out_x = in_x * (mi_picmax_x - mi_picmin_x) + mi_picmin_x;
+ out_y = in_y * (mi_picmax_y - mi_picmin_y) + mi_picmin_y;
+ out_z = z;
+ return out;
+}
+
vector yinvert(vector v)
{
v.y = 1 - v.y;
float vlen_minnorm2d(vector v);
+vector teamradar_2dcoord_to_texcoord(vector in);
+
vector teamradar_3dcoord_to_texcoord(vector in);
vector teamradar_texcoord_to_2dcoord(vector in);
+vector teamradar_texcoord_to_3dcoord(vector in,float z);
+
vector yinvert(vector v);
void draw_teamradar_background(float fg);
+++ /dev/null
-#include "tturrets.qh"
-#include "_all.qh"
-
-#include "hud.qh"
-#include "movelib.qh"
-#include "prandom.qh"
-#include "teamradar.qh"
-#include "waypointsprites.qh"
-
-#include "../common/teams.qh"
-
-#include "../common/movetypes/movetypes.qh"
-
-#include "../server/tturrets/include/turrets_early.qh"
-
-#include "../warpzonelib/anglestransform.qh"
-#include "../warpzonelib/mathlib.qh"
-
-.vector colormod;
-.float cnt;
-.float alpha;
-.float gravity;
-
-string tid2info_base;
-string tid2info_head;
-string tid2info_name;
-vector tid2info_min;
-vector tid2info_max;
-
-void turret_tid2info(float _tid);
-void turret_precache(float _tid);
-float turret_is_precache[TID_LAST];
-
-void turrets_precache()
-{
- turret_precache(TID_COMMON);
-}
-
-void turret_precache(int _tid)
-{
- if (!turret_is_precache[TID_COMMON])
- {
- precache_sound ("weapons/rocket_impact.wav");
- precache_model ("models/turrets/base-gib1.md3");
- precache_model ("models/turrets/base-gib2.md3");
- precache_model ("models/turrets/base-gib3.md3");
- precache_model ("models/turrets/base-gib4.md3");
- precache_model ("models/turrets/head-gib1.md3");
- precache_model ("models/turrets/head-gib2.md3");
- precache_model ("models/turrets/head-gib3.md3");
- precache_model ("models/turrets/head-gib4.md3");
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/rocket.md3");
- }
- turret_tid2info(_tid);
- if(turret_is_precache[_tid])
- return;
-
- switch(_tid)
- {
- case TID_EWHEEL:
- precache_model ("models/turrets/ewheel-base2.md3");
- precache_model ("models/turrets/ewheel-gun1.md3");
- break;
- case TID_FLAC:
- precache_model ("models/turrets/flac.md3");
- break;
- case TID_FUSION:
- precache_model ("models/turrets/reactor.md3");
- break;
- case TID_HELLION:
- precache_model ("models/turrets/hellion.md3");
- break;
- case TID_HK:
- precache_model ("models/turrets/hk.md3");
- break;
- case TID_MACHINEGUN:
- precache_model ("models/turrets/machinegun.md3");
- precache_sound ("weapons/uzi_fire.wav");
- break;
- case TID_MLRS:
- precache_model ("models/turrets/mlrs.md3");
- break;
- case TID_PHASER:
- precache_model ("models/turrets/phaser.md3");
- precache_model ("models/turrets/phaser_beam.md3");
- precache_sound ("turrets/phaser.wav");
- break;
- case TID_PLASMA:
- precache_model ("models/turrets/plasma.md3");
- break;
- case TID_PLASMA_DUAL:
- precache_model ("models/turrets/plasmad.md3");
- break;
- case TID_TESLA:
- precache_model ("models/turrets/tesla_head.md3");
- precache_model ("models/turrets/tesla_base.md3");
- break;
- case TID_WALKER:
- precache_model ("models/turrets/walker_head_minigun.md3");
- precache_model ("models/turrets/walker_body.md3");
- precache_sound ("weapons/uzi_fire.wav");
- break;
- }
- turret_is_precache[_tid] = true;
-}
-
-void turret_tid2info(float _tid)
-{
- tid2info_base = "models/turrets/base.md3";
- tid2info_min = '-32 -32 0';
- tid2info_max = '32 32 64';
-
- switch(_tid)
- {
- case TID_EWHEEL:
- tid2info_base = "models/turrets/ewheel-base2.md3";
- tid2info_head = "models/turrets/ewheel-gun1.md3";
- tid2info_name = "eWheel";
- break;
- case TID_FLAC:
- tid2info_head = "models/turrets/flac.md3";
- tid2info_name = "Flac Cannon";
- break;
- case TID_FUSION:
- tid2info_head = "models/turrets/reactor.md3";
- tid2info_name = "Fusion Reactor";
- tid2info_min = '-34 -34 0';
- tid2info_max = '34 34 90';
- break;
- case TID_HELLION:
- tid2info_head = "models/turrets/hellion.md3";
- tid2info_name = "Hellion";
- break;
- case TID_HK:
- tid2info_head = "models/turrets/hk.md3";
- tid2info_name = "Hunter-Killer";
- break;
- case TID_MACHINEGUN:
- tid2info_head = "models/turrets/machinegun.md3";
- tid2info_name = "Machinegun";
- break;
- case TID_MLRS:
- tid2info_head = "models/turrets/mlrs.md3";
- tid2info_name = "MLRS";
- break;
- case TID_PHASER:
- tid2info_head = "models/turrets/phaser.md3";
- tid2info_name = "Phaser";
- break;
- case TID_PLASMA:
- tid2info_head = "models/turrets/plasma.md3";
- tid2info_name = "Plasma";
- break;
- case TID_PLASMA_DUAL:
- tid2info_head = "models/turrets/plasmad.md3";
- tid2info_name = "Dual Plasma";
- break;
- case TID_TESLA:
- tid2info_base = "models/turrets/tesla_base.md3";
- tid2info_head = "models/turrets/tesla_head.md3";
- tid2info_name = "Tesla coil";
- tid2info_min = '-60 -60 0';
- tid2info_max ='60 60 128';
- break;
- case TID_WALKER:
- tid2info_base = "models/turrets/walker_body.md3";
- tid2info_head = "models/turrets/walker_head_minigun.md3";
- tid2info_name = "Walker";
- tid2info_min = '-70 -70 0';
- tid2info_max = '70 70 95';
- break;
- }
-}
-
-void turret_remove()
-{
- remove(self.tur_head);
- //remove(self.enemy);
- self.tur_head = world;
-}
-
-class(Turret) .vector glowmod;
-void turret_changeteam()
-{
- switch(self.team - 1)
- {
- case NUM_TEAM_1: // Red
- self.glowmod = '2 0 0';
- self.teamradar_color = '1 0 0';
- break;
-
- case NUM_TEAM_2: // Blue
- self.glowmod = '0 0 2';
- self.teamradar_color = '0 0 1';
- break;
-
- case NUM_TEAM_3: // Yellow
- self.glowmod = '1 1 0';
- self.teamradar_color = '1 1 0';
- break;
-
- case NUM_TEAM_4: // Pink
- self.glowmod = '1 0 1';
- self.teamradar_color = '1 0 1';
- break;
- }
-
- if(self.team)
- self.colormap = 1024 + (self.team - 1) * 17;
-
- self.tur_head.colormap = self.colormap;
- self.tur_head.glowmod = self.glowmod;
-
-}
-
-void turret_head_draw()
-{
- self.drawmask = MASK_NORMAL;
-}
-
-void turret_draw()
-{
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
-
- if (self.health < 127)
- {
- dt = random();
-
- if(dt < 0.03)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
- }
-
- if(self.health < 85)
- if(dt < 0.01)
- pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-
- if(self.health < 32)
- if(dt < 0.015)
- pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-
-}
-
-void turret_draw2d()
-{
- if(self.netname == "")
- return;
-
- if(!autocvar_g_waypointsprite_turrets)
- return;
-
- if(autocvar_cl_hidewaypoints)
- return;
-
- float dist = vlen(self.origin - view_origin);
- float t = (GetPlayerColor(player_localnum) + 1);
-
- vector o;
- string txt;
-
- if(autocvar_cl_vehicles_hud_tactical)
- if(dist < 10240 && t != self.team)
- {
- // TODO: Vehicle tactical hud
- o = project_3d_to_2d(self.origin + '0 0 32');
- if(o.z < 0
- || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
- || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
- || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
- || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
- return; // Dont draw wp's for turrets out of view
- o.z = 0;
- if(hud != HUD_NORMAL)
- {
- if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
- txt = "gfx/vehicles/turret_moving.tga";
- else
- txt = "gfx/vehicles/turret_stationary.tga";
-
- vector pz = drawgetimagesize(txt) * autocvar_cl_vehicles_crosshair_size;
- drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.7, DRAWFLAG_NORMAL);
- }
- }
-
- if(dist > self.maxdistance)
- return;
-
- string spriteimage = self.netname;
- float a = self.alpha * autocvar_hud_panel_fg_alpha;
- vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
-
-
- if(self.maxdistance > waypointsprite_normdistance)
- a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
- else if(self.maxdistance > 0)
- a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
-
- if(rgb == '0 0 0')
- {
- self.teamradar_color = '1 0 1';
- printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
- }
-
- txt = self.netname;
- if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
- txt = _("Spam");
- else
- txt = spritelookuptext(spriteimage);
-
- if(time - floor(time) > 0.5 && t == self.team)
- {
- if(self.helpme && time < self.helpme)
- {
- a *= SPRITE_HELPME_BLINK;
- txt = sprintf(_("%s under attack!"), txt);
- }
- else
- a *= spritelookupblinkvalue(spriteimage);
- }
-
- if(autocvar_g_waypointsprite_uppercase)
- txt = strtoupper(txt);
-
- if(a > 1)
- {
- rgb *= a;
- a = 1;
- }
-
- if(a <= 0)
- return;
-
- rgb = fixrgbexcess(rgb);
-
- o = project_3d_to_2d(self.origin + '0 0 64');
- if(o.z < 0
- || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
- || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
- || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
- || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
- return; // Dont draw wp's for turrets out of view
-
- o.z = 0;
-
- float edgedistance_min, crosshairdistance;
- edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
- (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)),
- (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x,
- (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y);
-
- float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
-
- crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
-
- t = waypointsprite_scale * vidscale;
- a *= waypointsprite_alpha;
-
- {
- a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
- t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
- }
- if (edgedistance_min < waypointsprite_edgefadedistance) {
- a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
- t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
- }
- if(crosshairdistance < waypointsprite_crosshairfadedistance) {
- a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
- t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
- }
-
- o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
- o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
- drawhealthbar(
- o,
- 0,
- self.health / 255,
- '0 0 0',
- '0 0 0',
- 0.5 * SPRITE_HEALTHBAR_WIDTH * t,
- 0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
- SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
- SPRITE_HEALTHBAR_BORDER * t,
- 0,
- rgb,
- a * SPRITE_HEALTHBAR_BORDERALPHA,
- rgb,
- a * SPRITE_HEALTHBAR_HEALTHALPHA,
- DRAWFLAG_NORMAL
- );
-}
-
-void turret_walker_draw()
-{
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- movelib_groundalign4point(300, 100, 0.25, 45);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles.y;
-
- if (self.health < 127)
- if(random() < 0.15)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-void turret_ewheel_draw()
-{
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles.y;
-
- if (self.health < 127)
- if(random() < 0.05)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-void turret_construct()
-{
- if(self.tur_head == world)
- self.tur_head = spawn();
-
- turret_tid2info(self.turret_type);
- self.netname = tid2info_name;
-
- setorigin(self, self.origin);
- setmodel(self, tid2info_base);
- setmodel(self.tur_head, tid2info_head);
- setsize(self, tid2info_min, tid2info_max);
- setsize(self.tur_head, '0 0 0', '0 0 0');
-
- if(self.turret_type == TID_EWHEEL)
- setattachment(self.tur_head, self, "");
- else
- setattachment(self.tur_head, self, "tag_head");
-
- self.tur_head.classname = "turret_head";
- self.tur_head.owner = self;
- self.tur_head.move_movetype = MOVETYPE_NOCLIP;
- self.move_movetype = MOVETYPE_NOCLIP;
- self.tur_head.angles = self.angles;
- self.health = 255;
- self.solid = SOLID_BBOX;
- self.tur_head.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NOCLIP;
- self.tur_head.movetype = MOVETYPE_NOCLIP;
- self.draw = turret_draw;
- self.entremove = turret_remove;
- self.drawmask = MASK_NORMAL;
- self.tur_head.drawmask = MASK_NORMAL;
- self.anim_start_time = 0;
- self.draw2d = turret_draw2d;
- self.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
- self.teamradar_color = '1 0 0';
- self.alpha = 1;
-
- if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
- {
- self.gravity = 1;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- self.move_time = time;
- switch(self.turret_type)
- {
- case TID_EWHEEL:
- self.draw = turret_ewheel_draw;
- break;
- case TID_WALKER:
- self.draw = turret_walker_draw;
- break;
-
- }
- }
-}
-
-entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
-void turret_gibboom();
-void turret_gib_draw()
-{
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
-
- self.drawmask = MASK_NORMAL;
-
- if(self.cnt)
- {
- if(time >= self.nextthink)
- {
- turret_gibboom();
- remove(self);
- }
- }
- else
- {
- self.alpha = bound(0, self.nextthink - time, 1);
- if(self.alpha < ALPHA_MIN_VISIBLE)
- remove(self);
- }
-}
-
-void turret_gibboom()
-{
- float i;
-
- sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
-
- for (i = 1; i < 5; i = i + 1)
- turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', false);
-}
-
-entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
-{
- entity gib;
-
- traceline(_from, _to, MOVE_NOMONSTERS, world);
- if(trace_startsolid)
- return world;
-
- gib = spawn();
- setorigin(gib, _from);
- setmodel(gib, _model);
- gib.colormod = _cmod;
- gib.solid = SOLID_CORPSE;
- gib.draw = turret_gib_draw;
- gib.cnt = _explode;
- setsize(gib, '-1 -1 -1', '1 1 1');
- if(_explode)
- {
- gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
- gib.effects = EF_FLAME;
- }
- else
- gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
-
- gib.gravity = 1;
- gib.move_movetype = MOVETYPE_BOUNCE;
- gib.move_origin = _from;
- setorigin(gib, _from);
- gib.move_velocity = _to;
- gib.move_avelocity = prandomvec() * 32;
- gib.move_time = time;
- gib.damageforcescale = 1;
- gib.classname = "turret_gib";
-
- return gib;
-}
-
-void turret_die()
-{
-
- sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
- turret_tid2info(self.turret_type);
- if (!autocvar_cl_nogibs)
- {
- // Base
- if(self.turret_type == TID_EWHEEL)
- turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
- else if (self.turret_type == TID_WALKER)
- turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
- else if (self.turret_type == TID_TESLA)
- turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
- else
- {
- if (random() > 0.5)
- {
- turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
- turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
- turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
- }
- else
- turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', true);
-
- entity headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
- if(headgib)
- {
- headgib.angles = headgib.move_angles = self.tur_head.angles;
- headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
- headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity.y * 5;
- headgib.gravity = 0.5;
- }
- }
- }
-
- setmodel(self, "null");
- setmodel(self.tur_head, "null");
-}
-
-void ent_turret()
-{
- int sf = ReadByte();
-
- if(sf & TNSF_SETUP)
- {
- self.turret_type = ReadByte();
-
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.angles_x = ReadAngle();
- self.angles_y = ReadAngle();
-
- turret_precache(self.turret_type);
- turret_construct();
- self.colormap = 1024;
- self.glowmod = '0 1 1';
- self.tur_head.colormap = self.colormap;
- self.tur_head.glowmod = self.glowmod;
- }
-
- if(sf & TNSF_ANG)
- {
- if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
- self.tur_head = spawn();
-
- self.tur_head.move_angles_x = ReadShort();
- self.tur_head.move_angles_y = ReadShort();
- //self.tur_head.angles = self.angles + self.tur_head.move_angles;
- self.tur_head.angles = self.tur_head.move_angles;
- }
-
- if(sf & TNSF_AVEL)
- {
- if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
- self.tur_head = spawn();
-
- self.tur_head.move_avelocity_x = ReadShort();
- self.tur_head.move_avelocity_y = ReadShort();
- }
-
- if(sf & TNSF_MOVE)
- {
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
- setorigin(self, self.origin);
-
- self.velocity_x = ReadShort();
- self.velocity_y = ReadShort();
- self.velocity_z = ReadShort();
-
- self.move_angles_y = ReadShort();
-
- self.move_time = time;
- self.move_velocity = self.velocity;
- self.move_origin = self.origin;
- }
-
- if(sf & TNSF_ANIM)
- {
- self.frame1time = ReadCoord();
- self.frame = ReadByte();
- }
-
- if(sf & TNSF_STATUS)
- {
- int _tmp = ReadByte();
- if(_tmp != self.team)
- {
- self.team = _tmp;
- turret_changeteam();
- }
-
- _tmp = ReadByte();
- if(_tmp == 0 && self.health != 0)
- turret_die();
- else if(self.health && self.health != _tmp)
- self.helpme = servertime + 10;
-
- self.health = _tmp;
- }
- //self.enemy.health = self.health / 255;
-}
+++ /dev/null
-#ifndef TTURRETS_H
-#define TTURRETS_H
-
-void ent_turret();
-void turrets_precache();
-entityclass(Turret);
-class(Turret) .entity tur_head;
-#endif
#include "shownames.qh"
#include "waypointsprites.qh"
+#include "mutators/events.qh"
+
#include "../common/constants.qh"
#include "../common/mapinfo.qh"
#include "../common/nades.qh"
wcross_alpha_prev = wcross_alpha;
wcross_color_prev = wcross_color;
+ MUTATOR_CALLHOOK(UpdateCrosshair);
+
wcross_scale *= 1 - autocvar__menu_alpha;
wcross_alpha *= 1 - autocvar__menu_alpha;
wcross_size = draw_getimagesize(wcross_name) * wcross_scale;
if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
{
float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
- if(WantEventchase())
+ float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+ entity gen = world;
+
+ if(ons_roundlost)
+ {
+ entity e;
+ for(e = world; (e = find(e, classname, "onslaught_generator")); )
+ {
+ if(e.health <= 0)
+ {
+ gen = e;
+ break;
+ }
+ }
+ if(!gen)
+ ons_roundlost = FALSE; // don't enforce the 3rd person camera if there is no dead generator to show
+ }
+ if(WantEventchase() || (!autocvar_cl_orthoview && ons_roundlost))
{
eventchase_running = true;
// make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
+ if(ons_roundlost) { current_view_origin = gen.origin; }
// detect maximum viewoffset and use it
vector view_offset = autocvar_cl_eventchase_viewoffset;
if(vehicle_chase && autocvar_cl_eventchase_vehicle_viewoffset) { view_offset = autocvar_cl_eventchase_vehicle_viewoffset; }
+ if(ons_roundlost) { view_offset = autocvar_cl_eventchase_generator_viewoffset; }
if(view_offset)
{
// make the camera smooth back
float chase_distance = autocvar_cl_eventchase_distance;
if(vehicle_chase && autocvar_cl_eventchase_vehicle_distance) { chase_distance = autocvar_cl_eventchase_vehicle_distance; }
+ if(ons_roundlost) { chase_distance = autocvar_cl_eventchase_generator_distance; }
if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
if(autocvar__hud_configure)
HUD_Panel_Mouse();
+ else
+ HUD_Radar_Mouse();
if(hud && !intermission)
if(hud == HUD_BUMBLEBEE_GUN)
switch(s)
{
- case "ons-cp-atck-neut": return 2;
- case "ons-cp-atck-red": return 2;
- case "ons-cp-atck-blue": return 2;
- case "ons-cp-dfnd-red": return 0.5;
- case "ons-cp-dfnd-blue": return 0.5;
+ case "ons-cp-atck": return 2;
+ case "ons-cp-dfnd": return 0.5;
case "item_health_mega": return 2;
case "item_armor_large": return 2;
case "item-invis": return 2;
case "neutralbase": return _("White base");
case "pinkbase": return _("Pink base");
case "waypoint": return _("Waypoint");
- case "ons-gen-red": return _("Generator");
- case "ons-gen-blue": return _("Generator");
+ case "ons-gen": return _("Generator");
case "ons-gen-shielded": return _("Generator");
- case "ons-cp-neut": return _("Control point");
- case "ons-cp-red": return _("Control point");
- case "ons-cp-blue": return _("Control point");
- case "ons-cp-atck-neut": return _("Control point");
- case "ons-cp-atck-red": return _("Control point");
- case "ons-cp-atck-blue": return _("Control point");
- case "ons-cp-dfnd-red": return _("Control point");
- case "ons-cp-dfnd-blue": return _("Control point");
+ case "ons-cp": return _("Control point");
+ case "ons-cp-atck": return _("Control point");
+ case "ons-cp-dfnd": return _("Control point");
case "race-checkpoint": return _("Checkpoint");
case "race-finish": return _("Finish");
case "race-start": return _("Start");
// they are drawn using a .draw function
void Ent_RemoveWaypointSprite();
+
void Ent_WaypointSprite();
void WaypointSprite_Load_Frames(string ext);
ATTRIB(Buff, m_skin, int, 0)
ATTRIB(Buff, m_sprite, string, "")
#ifdef SVQC
- METHOD(Buff, m_time, float(entity))
+ METHOD(Buff, m_time, float(entity));
float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
#endif
ENDCLASS(Buff)
#include "../../server/command/cmd.qh"
#include "../../server/command/common.qh"
#include "../../server/command/sv_cmd.qh"
-
+ #include "../../common/turrets/config.qh"
#include "../../common/weapons/config.qh"
#endif
}
}
+void GenericCommand_dumpturrets(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ #ifdef SVQC
+ tur_config_file = -1;
+ tur_config_alsoprint = -1;
+ string filename = argv(1);
+
+ if(filename == "")
+ {
+ filename = "turrets_dump.cfg";
+ tur_config_alsoprint = FALSE;
+ }
+ else if(filename == "-")
+ {
+ filename = "turrets_dump.cfg";
+ tur_config_alsoprint = TRUE;
+ }
+ tur_config_file = fopen(filename, FILE_WRITE);
+
+ if(tur_config_file >= 0)
+ {
+ Dump_Turret_Settings();
+ print(sprintf("Dumping turrets... File located in ^2data/data/%s^7.\n", filename));
+ fclose(tur_config_file);
+ tur_config_file = -1;
+ tur_config_alsoprint = -1;
+ }
+ else
+ {
+ print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+ }
+ #else
+ print(_("Turrets dump command only works with sv_cmd.\n"));
+ #endif
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpturrets [filename]"));
+ print(" Where 'filename' is the file to write (default is turrets_dump.cfg),\n");
+ print(" if supplied with '-' output to console as well as default,\n");
+ print(" if left blank, it will only write to default.\n");
+ return;
+ }
+ }
+}
+
void GenericCommand_maplist(float request, float argc)
{
switch(request)
GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
GENERIC_COMMAND("dumpitems", GenericCommand_dumpitems(request), "Dump all items to the console") \
GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
+ GENERIC_COMMAND("dumpturrets", GenericCommand_dumpturrets(request), "Dump all turrets into turrets_dump.txt") \
GENERIC_COMMAND("dumpweapons", GenericCommand_dumpweapons(request), "Dump all weapons into weapons_dump.txt") \
GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \
const int AS_FLOAT_TRUNCATED = 2;
const int AS_FLOAT = 8;
+const int TE_CSQC_MUTATOR = 99;
+#define MUTATOR_HASH(s) crc16(true, s)
+#define WriteMutator(to, s) do { \
+ WriteByte(to, TE_CSQC_MUTATOR); \
+ WriteLong(to, MUTATOR_HASH(#s)); \
+} while (0)
+#define ReadMutator() ReadLong()
+#define ReadMutatorEquals(read, s) (read == MUTATOR_HASH(#s))
const int TE_CSQC_PICTURE = 100;
const int TE_CSQC_RACE = 101;
const int TE_CSQC_VORTEXBEAMPARTICLE = 103;
const int ENT_CLIENT_SWAMP = 69;
const int ENT_CLIENT_CORNER = 70;
const int ENT_CLIENT_KEYLOCK = 71;
-const int ENT_CLIENT_EFFECT = 72;
+const int ENT_CLIENT_GENERATOR = 72;
+const int ENT_CLIENT_CONTROLPOINT_ICON = 73;
+const int ENT_CLIENT_EFFECT = 74;
const int ENT_CLIENT_VIEWLOC = 78;
const int ENT_CLIENT_VIEWLOC_TRIGGER = 79;
CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
CSQCMODEL_PROPERTY_SCALED(4096, float, ReadByte, WriteByte, scale, 16, 0, 255) \
CSQCMODEL_PROPERTY(8192, int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
- CSQCMODEL_PROPERTY(16384, TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
+ CSQCMODEL_PROPERTY(16384, TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
// TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
// add hook function calls here
DEATHTYPE(DEATH_TURRET_PLASMA, DEATH_SELF_TURRET_PLASMA, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_TESLA, DEATH_SELF_TURRET_TESLA, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_WALK_GUN, DEATH_SELF_TURRET_WALK_GUN, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_TURRET_WALK_MEELE, DEATH_SELF_TURRET_WALK_MEELE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_WALK_MELEE, DEATH_SELF_TURRET_WALK_MELEE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_WALK_ROCKET, DEATH_SELF_TURRET_WALK_ROCKET, NO_MSG, DEATH_TURRET_LAST) \
DEATHTYPE(DEATH_VH_BUMB_DEATH, DEATH_SELF_VH_BUMB_DEATH, DEATH_MURDER_VH_BUMB_DEATH, DEATH_VHFIRST) \
DEATHTYPE(DEATH_VH_BUMB_GUN, NO_MSG, DEATH_MURDER_VH_BUMB_GUN, NORMAL_POS) \
vel_y = ReadCoord();
vel_z = ReadCoord();
}
-
+
if(!eff_trail)
eff_cnt = ReadByte();
Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
}
-#endif
\ No newline at end of file
+#endif
EFFECT(0, EFFECT_ITEM_PICKUP, "item_pickup") \
EFFECT(0, EFFECT_ITEM_RESPAWN, "item_respawn") \
EFFECT(0, EFFECT_JUMPPAD, "jumppad_activate") \
- EFFECT(1, EFFECT_BULLET, "tr_bullet")
+ EFFECT(1, EFFECT_BULLET, "tr_bullet")
/** If you register a new item, make sure to add it to all.inc */
CLASS(GameItem, Object)
ATTRIB(GameItem, m_id, int, 0)
- METHOD(GameItem, show, void(entity this))
+ METHOD(GameItem, show, void(entity this));
void GameItem_show(entity this) { print("A game item\n"); }
void ITEM_HANDLE(Show, entity this) { this.show(this); }
ENDCLASS(GameItem)
ATTRIB(Pickup, m_model, string, string_null)
ATTRIB(Pickup, m_sound, string, "misc/itempickup.wav")
ATTRIB(Pickup, m_name, string, string_null)
- METHOD(Pickup, show, void(entity this))
+ METHOD(Pickup, show, void(entity this));
void Pickup_show(entity this) { printf("%s: %s\n", etos(this), this.m_name); }
#ifdef SVQC
ATTRIB(Pickup, m_botvalue, int, 0)
ATTRIB(Pickup, m_pickupevalfunc, float(entity player, entity item), generic_pickupevalfunc)
ATTRIB(Pickup, m_respawntime, float(), func_null)
ATTRIB(Pickup, m_respawntimejitter, float(), func_null)
- METHOD(Pickup, giveTo, bool(entity this, entity item, entity player))
+ METHOD(Pickup, giveTo, bool(entity this, entity item, entity player));
bool Pickup_giveTo(entity this, entity item, entity player) { return Item_GiveTo(item, player); }
bool ITEM_HANDLE(Pickup, entity this, entity item, entity player);
#endif
#define IS_GAMETYPE(NAME) \
(MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
-REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,false,"timelimit=20 pointlimit=30 leadlimit=0",_("Kill all enemies"));
+REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,false,"timelimit=20 pointlimit=30 leadlimit=0",_("Score as many frags as you can."));
#define g_dm IS_GAMETYPE(DEATHMATCH)
-REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,false,"timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
+REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,false,"timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left."));
#define g_lms IS_GAMETYPE(LMS)
-REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
+REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line."));
#define g_race IS_GAMETYPE(RACE)
-REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,false,"timelimit=20 skill=-1",_("Race for fastest time"));
+REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,false,"timelimit=20 skill=-1",_("Race for fastest time."));
#define g_cts IS_GAMETYPE(CTS)
-REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Kill all enemy teammates"));
+REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team."));
#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
-REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,true,"timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it"));
+REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,true,"timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team."));
#define g_ctf IS_GAMETYPE(CTF)
-REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"));
+REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round."));
#define g_ca IS_GAMETYPE(CA)
-REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture all the control points to win"));
+REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win."));
#define g_domination IS_GAMETYPE(DOMINATION)
-REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
+REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round."));
#define g_keyhunt IS_GAMETYPE(KEYHUNT)
-REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
+REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out."));
#define g_assault IS_GAMETYPE(ASSAULT)
-REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
+REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator."));
#define g_onslaught IS_GAMETYPE(ONSLAUGHT)
-REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"timelimit=20 pointlimit=5 leadlimit=0",_("XonSports"));
+REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean."));
#define g_nexball IS_GAMETYPE(NEXBALL)
-REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them"));
+REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them, freeze the most enemies to win."));
#define g_freezetag IS_GAMETYPE(FREEZETAG)
-REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,true,"timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
+REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,true,"timelimit=20 pointlimit=30",_("Hold the ball to get points for kills."));
#define g_keepaway IS_GAMETYPE(KEEPAWAY)
-REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,false,"pointlimit=50 teams=0",_("Survive against waves of monsters"));
+REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,false,"pointlimit=50 teams=0",_("Survive against waves of monsters."));
#define g_invasion IS_GAMETYPE(INVASION)
const int MAPINFO_FEATURE_WEAPONS = 1; // not defined for instagib-only maps
#include "../../server/defs.qh"
#include "../deathtypes.qh"
#include "../../server/mutators/mutators_include.qh"
- #include "../../server/tturrets/include/turrets_early.qh"
- #include "../vehicles/sv_vehicles.qh"
+ #include "../../server/steerlib.qh"
+ #include "../turrets/sv_turrets.qh"
+ #include "../turrets/util.qh"
+ #include "../vehicles/all.qh"
#include "../../server/campaign.qh"
#include "../../server/command/common.qh"
#include "../../server/command/cmd.qh"
#include "../triggers/triggers.qh"
#include "../../csqcmodellib/sv_model.qh"
#include "../../server/round_handler.qh"
- #include "../../server/tturrets/include/turrets.qh"
#endif
// =========================
for(i = 0; i <= MAX_CLIP_PLANES; ++i)
planes[i] = '0 0 0';
-
+
grav = 0;
restore_velocity = self.move_velocity;
void _Movetype_Physics_Pusher(float dt);
-#endif
\ No newline at end of file
+#endif
void _Movetype_Physics_Toss(float dt);
-#endif
\ No newline at end of file
+#endif
--- /dev/null
+#include "mutator/damagetext.qc"
--- /dev/null
+#include "all.inc"
#define EV_NO_ARGS(i, o)
+#pragma noref 1
string ret_string;
+#define MUTATOR_TYPES(_, x) \
+ _(x, bool) \
+ _(x, int) \
+ _(x, entity) \
+ _(x, float) \
+ _(x, vector) \
+ _(x, string) \
+ /**/
+
+#define MUTATOR_NEWGLOBAL(x, type) type mutator_argv_##type##_##x;
+
+MUTATOR_TYPES(MUTATOR_NEWGLOBAL, 0)
+MUTATOR_TYPES(MUTATOR_NEWGLOBAL, 1)
+
+#undef MUTATOR_TYPES
+#undef MUTATOR_NEWGLOBAL
+
+#pragma noref 0
+
/** appends ":mutatorname" to ret_string for logging */
#define EV_BuildMutatorsString(i, o) \
/**/ i(string, ret_string) \
--- /dev/null
+REGISTER_MUTATOR(damagetext, true);
+
+#ifdef CSQC
+bool autocvar_cl_damagetext = false;
+string autocvar_cl_damagetext_format = "-%3$d";
+vector autocvar_cl_damagetext_color = '1 1 0';
+float autocvar_cl_damagetext_size = 8;
+float autocvar_cl_damagetext_alpha_start = 1;
+float autocvar_cl_damagetext_alpha_lifetime = 3;
+vector autocvar_cl_damagetext_velocity = '0 0 20';
+vector autocvar_cl_damagetext_offset = '0 -40 0';
+float autocvar_cl_damagetext_accumulate_range = 30;
+STATIC_INIT(cl_damagetext) {
+ CVAR_DESCRIBE(cl_damagetext, _("Draw damage dealt. 0: disabled, 1: enabled"));
+ CVAR_DESCRIBESTR(cl_damagetext_format, _("How to format the damage text. 1$ is health, 2$ is armor, 3$ is both"));
+ CVAR_DESCRIBEVEC(cl_damagetext_color, _("Default damage text color"));
+ CVAR_DESCRIBE(cl_damagetext_size, _("Damage text font size"));
+ CVAR_DESCRIBE(cl_damagetext_alpha_start, _("Damage text initial alpha"));
+ CVAR_DESCRIBE(cl_damagetext_alpha_lifetime, _("Damage text lifetime in seconds"));
+ CVAR_DESCRIBEVEC(cl_damagetext_velocity, _("Damage text move direction"));
+ CVAR_DESCRIBEVEC(cl_damagetext_offset, _("Damage text offset"));
+ CVAR_DESCRIBE(cl_damagetext_accumulate_range, _("Damage text spawned within this range is accumulated"));
+}
+
+CLASS(DamageText, Object)
+ ATTRIB(DamageText, m_color, vector, autocvar_cl_damagetext_color)
+ ATTRIB(DamageText, m_size, float, autocvar_cl_damagetext_size)
+ ATTRIB(DamageText, alpha, float, autocvar_cl_damagetext_alpha_start)
+ ATTRIB(DamageText, fade_rate, float, 1 / autocvar_cl_damagetext_alpha_lifetime)
+ ATTRIB(DamageText, velocity, vector, autocvar_cl_damagetext_velocity)
+ ATTRIB(DamageText, m_group, int, 0)
+ ATTRIB(DamageText, m_damage, int, 0)
+ ATTRIB(DamageText, m_armordamage, int, 0)
+ ATTRIB(DamageText, time_prev, float, time)
+
+ void DamageText_draw() {
+ entity this = self;
+ float dt = time - this.time_prev;
+ this.time_prev = time;
+ setorigin(this, this.origin + dt * this.velocity);
+ this.alpha -= dt * this.fade_rate;
+ if (this.alpha < 0) remove(this);
+ vector pos = project_3d_to_2d(this.origin) + autocvar_cl_damagetext_offset;
+ if (pos.z >= 0 && this.m_size > 0) {
+ pos.z = 0;
+ string s = sprintf(autocvar_cl_damagetext_format, this.m_damage, this.m_armordamage, this.m_damage + this.m_armordamage);
+ drawcolorcodedstring2(pos, s, this.m_size * '1 1 0', this.m_color, this.alpha, DRAWFLAG_NORMAL);
+ }
+ }
+ ATTRIB(DamageText, draw2d, void(), DamageText_draw)
+
+ void DamageText_update(DamageText this, vector _origin, int _health, int _armor) {
+ this.m_damage = _health;
+ this.m_armordamage = _armor;
+ setorigin(this, _origin);
+ this.alpha = 1;
+ }
+
+ CONSTRUCTOR(DamageText, int _group, vector _origin, int _health, int _armor) {
+ CONSTRUCT(DamageText);
+ this.m_group = _group;
+ DamageText_update(this, _origin, _health, _armor);
+ return this;
+ }
+ENDCLASS(DamageText)
+#endif
+
+#ifdef SVQC
+int autocvar_sv_damagetext = 2;
+STATIC_INIT(sv_damagetext) {
+ CVAR_DESCRIBE(sv_damagetext, _("<= 0: disabled, >= 1: spectators, >= 2: players, >= 3: all players"));
+}
+#define SV_DAMAGETEXT_DISABLED() (autocvar_sv_damagetext <= 0 /* disabled */)
+#define SV_DAMAGETEXT_SPECTATORS_ONLY() (autocvar_sv_damagetext >= 1 /* spectators only */)
+#define SV_DAMAGETEXT_PLAYERS() (autocvar_sv_damagetext >= 2 /* players */)
+#define SV_DAMAGETEXT_ALL() (autocvar_sv_damagetext >= 3 /* all players */)
+MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
+ if (SV_DAMAGETEXT_DISABLED()) return;
+ const entity attacker = mutator_argv_entity_0;
+ const entity hit = mutator_argv_entity_1; if (hit == attacker) return;
+ const int health = mutator_argv_int_0;
+ const int armor = mutator_argv_int_1;
+ const vector location = hit.origin;
+ entity e;
+ FOR_EACH_REALCLIENT(e) if (
+ (SV_DAMAGETEXT_ALL()) ||
+ (SV_DAMAGETEXT_PLAYERS() && e == attacker) ||
+ (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(e) && e.enemy == attacker) ||
+ (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(e))
+ ) {
+ msg_entity = e;
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteMutator(MSG_ONE, damagetext);
+ WriteShort(MSG_ONE, health);
+ WriteShort(MSG_ONE, armor);
+ WriteEntity(MSG_ONE, hit);
+ WriteCoord(MSG_ONE, location.x);
+ WriteCoord(MSG_ONE, location.y);
+ WriteCoord(MSG_ONE, location.z);
+ }
+}
+#endif
+
+#ifdef CSQC
+MUTATOR_HOOKFUNCTION(damagetext, CSQC_Parse_TempEntity) {
+ if (MUTATOR_RETURNVALUE) return false;
+ if (!ReadMutatorEquals(mutator_argv_int_0, damagetext)) return false;
+ int health = ReadShort();
+ int armor = ReadShort();
+ int group = ReadShort();
+ vector location = vec3(ReadCoord(), ReadCoord(), ReadCoord());
+ if (autocvar_cl_damagetext) {
+ if (autocvar_cl_damagetext_accumulate_range) {
+ for (entity e = findradius(location, autocvar_cl_damagetext_accumulate_range); e; e = e.chain) {
+ if (e.instanceOfDamageText && e.m_group == group) {
+ DamageText_update(e, location, e.m_damage + health, e.m_armordamage + armor);
+ return true;
+ }
+ }
+ }
+ NEW(DamageText, group, location, health, armor);
+ }
+ return true;
+}
+#endif
#include "nades.qh"
#include "buffs.qh"
#include "../common/movetypes/movetypes.qh"
- #include "../server/tturrets/include/turrets_early.qh"
#include "../client/main.qh"
#include "../csqcmodellib/cl_model.qh"
#elif defined(MENUQC)
#include "../dpdefs/progsdefs.qh"
#include "constants.qh"
#include "../server/constants.qh"
+ #include "../common/turrets/sv_turrets.qh"
#endif
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PLASMA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served some superheated plasma from a turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_TESLA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was electrocuted by a Tesla turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_GUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MEELE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Walker turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_BUMB_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a vehicle%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left"), "") \
MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED, 0, 0, "", "", "", _("^BGMonsters are currently disabled"), "") \
+ MSG_INFO_NOTIF(1, INFO_ONSLAUGHT_CAPTURE, 2, 0, "s1 s2", "", "", _("^BG%s^BG captured %s^BG control point"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_CPDESTROYED_, 4, 2, 0, "s1 s2", "", "", _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator has been destroyed"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVE_SELF, 0, 0, "", NO_CPID, "0 0", _("^K3You revived yourself"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVED, 1, 0, "s1", NO_CPID, "0 0", _("^K3You were revived by ^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_AUTO_REVIVED, 0, 1, "f1", NO_CPID, "0 0", _("^K3You were automatically revived after %s second(s)"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_GENERATOR_UNDERATTACK, 0, 0, "", NO_CPID, "0 0", _("^BGThe generator is under attack!"), "") \
MULTITEAM_CENTER(1, CENTER_ROUND_TEAM_WIN_, 4, 0, 0, "", CPID_ROUND, "0 0", _("^TC^TT^BG team wins the round"), "") \
MSG_CENTER_NOTIF(1, CENTER_ROUND_PLAYER_WIN, 1, 0, "s1", CPID_ROUND, "0 0", _("^BG%s^BG wins the round"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SELF, 0, 0, "", NO_CPID, "0 0", _("^K1You froze yourself"), "") \
MSG_CENTER_NOTIF(1, CENTER_NIX_COUNTDOWN, 0, 2, "item_wepname", CPID_NIX, "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_NIX_NEWWEAPON, 0, 1, "item_wepname", CPID_NIX, "0 0", _("^F2Active weapon: ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_NADE, 0, 0, "", NO_CPID, "0 0", _("^BGPress ^F2DROPWEAPON^BG again to toss the grenade!"), "") \
- MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture controlpoints to shield it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_CAPTURE, 1, 0, "s1", CPID_ONSLAUGHT, "0 0", _("^BGYou captured %s^BG control point"), "") \
+ MULTITEAM_CENTER(1, CENTER_ONS_CAPTURE_, 4, 1, 0, "s1", CPID_ONSLAUGHT, "0 0", _("^TC^TT^BG team captured %s^BG control point"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_CONTROLPOINT_SHIELDED, 0, 0, "", CPID_ONS_CAPSHIELD, "0 0", _("^BGThis control point currently cannot be captured"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_GENERATOR_SHIELDED, 0, 0, "", CPID_ONS_CAPSHIELD, "0 0", _("^BGThe enemy generator cannot be destroyed yet\n^F2Capture some control points to unshield it"), "") \
+ MULTITEAM_CENTER(1, CENTER_ONS_NOTSHIELDED_, 4, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED_TEAM, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture control points to shield it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT, 0, 0, "pass_key", CPID_ONSLAUGHT, "0 0", _("^BGPress ^F2DROPFLAG%s^BG to teleport"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT_ANTISPAM, 0, 1, "f1secs", CPID_ONSLAUGHT, "0 0", _("^BGTeleporting disabled for %s"), "") \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_FRAG, 0, 0, "", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\nKeep fragging until we have a winner!"), _("^F2Now playing ^F4OVERTIME^F2!\nKeep scoring until we have a winner!")) \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_CONTROLPOINT, 0, 0, "", CPID_OVERTIME, "5 0", _("^F2Now playing ^F4OVERTIME^F2!\n\nGenerators are now decaying.\nThe more control points your team holds,\nthe faster the enemy generator decays"), "") \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_TIME, 0, 1, "f1time", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\n^BGAdded ^F4%s^BG to the game!"), "") \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_PLASMA, NO_MSG, INFO_DEATH_SELF_TURRET_PLASMA, CENTER_DEATH_SELF_TURRET) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_TESLA, NO_MSG, INFO_DEATH_SELF_TURRET_TESLA, CENTER_DEATH_SELF_TURRET) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_GUN, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_GUN, CENTER_DEATH_SELF_TURRET_WALK) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_MEELE, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_MEELE, CENTER_DEATH_SELF_TURRET_WALK) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_MELEE, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_MELEE, CENTER_DEATH_SELF_TURRET_WALK) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_ROCKET, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_ROCKET, CENTER_DEATH_SELF_TURRET_WALK) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_BUMB_DEATH, NO_MSG, INFO_DEATH_SELF_VH_BUMB_DEATH, CENTER_DEATH_SELF_VH_BUMB_DEATH) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_CRUSH, NO_MSG, INFO_DEATH_SELF_VH_CRUSH, CENTER_DEATH_SELF_VH_CRUSH) \
, CPID_MOTD
, CPID_NIX
, CPID_ONSLAUGHT
+, CPID_ONS_CAPSHIELD
, CPID_OVERTIME
, CPID_POWERUP
, CPID_RACE_FINISHLAP
// notification limits -- INCREASE AS NECESSARY
const float NOTIF_ANNCE_MAX = 100;
-const float NOTIF_INFO_MAX = 300;
+const float NOTIF_INFO_MAX = 350;
const float NOTIF_CENTER_MAX = 250;
const float NOTIF_MULTI_MAX = 200;
const float NOTIF_CHOICE_MAX = 30;
#define METHOD(cname, name, prototype) \
class(cname) .prototype name; \
prototype cname##_##name; \
- INIT_STATIC(cname) { this.name = cname##_##name; }
+ INIT_STATIC(cname) { this.name = cname##_##name; } \
+ prototype cname##_##name
#define ATTRIB(cname, name, type, val) \
class(cname) .type name; \
/*
Copyright (C) 2015 Micah Talkiewicz.
-
+
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
+
See the GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
+
vector vec_bias(vector v, float f){
vector c;
c_x = v_x + f;
c_z = min (a_z, b_z);
return c;
}
-
+
vector vec_to_max (vector a, vector b) {
vector c;
c_x = max (a_x, b_x);
c_z = max (a_z, b_z);
return c;
}
-
+
// there may already be a function for bounding a vector in this manner, however my very quick search did not reveal one -- Player_2
vector vec_bounds_in (vector point, vector a, vector b) {
vector c, d, e;
-
+
d = vec_to_min(a,b);
e = vec_to_max(a,b);
-
+
c = vec_to_max(point, d);
c = vec_to_min(c, e);
-
+
return c;
-
+
}
-
+
vector vec_bounds_out (vector point, vector a, vector b) {
vector c, d, e;
-
+
d = vec_to_max(a,b);
e = vec_to_min(a,b);
-
+
c = vec_to_max(point, d);
c = vec_to_min(c, e);
-
+
return c;
-
+
}
-
+
float angle_snap_f (float f, float increment){
-
+
float i;
for (i = 0; i <= 360; ){
if (f <= i - increment)
return i - increment;
i = i + increment;
}
-
+
return 0;
}
-
+
vector angle_snap_vec (vector v, float increment) {
vector c;
c_x = angle_snap_f (v_x, increment);
/*
Copyright (C) 2015 Micah Talkiewicz.
-
+
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
+
See the GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
vector trace1_plane_normal = '0 0 0';
vector trace2_plane_normal = '0 0 0';
vector trace3_plane_normal = '0 0 0';
-
+
PM_ClientMovement_UpdateStatus(false);
primalvelocity = self.velocity;
PM_ClientMovement_UpdateStatus(true);
#endif
-
+
#ifdef SVQC
WarpZone_PlayerPhysics_FixVAngle();
PM_Main();
#ifdef CSQC
- self.pmove_flags =
+ self.pmove_flags =
((self.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
(!(self.flags & FL_JUMPRELEASED) ? 0 : PMF_JUMP_HELD) |
((self.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
const int STAT_FUELREGEN_TIME = 96;
const int STAT_JETPACK_TIME = 97;
const int STAT_SUPERWEAPONS_TIME = 98;
-// 99 empty?
+const int STAT_ROUNDLOST = 99;
/* The following stats change depending on the gamemode, so can share the same ID */
// IDs 100 to 104 reserved for gamemodes
// 137 empty?
// 138 empty?
// 139 empty?
-// 140 empty?
-// 141 empty?
-// 142 empty?
-// 143 empty?
-// 144 empty?
-// 145 empty?
-// 146 empty?
-// 147 empty?
-// 148 empty?
-// 149 empty?
-// 150 empty?
-// 151 empty?
-// 152 empty?
-// 153 empty?
-// 154 empty?
-// 155 empty?
+// 140 reserved
+// 141 reserved
+// 142 reserved
+// 143 reserved
+// 144 reserved
+// 145 reserved
+// 146 reserved
+// 147 reserved
+// 148 reserved
+// 149 reserved
+// 150 reserved
+// 151 reserved
+// 152 reserved
+// 153 reserved
+// 154 reserved
+// 155 reserved
// 156 empty?
// 157 empty?
// 158 empty?
void door_blocked()
{
- if((self.spawnflags & 8)
+ if((self.spawnflags & 8)
#ifdef SVQC
&& (other.takedamage != DAMAGE_NO)
#elif defined(CSQC)
void Ent_PointParticles();
-#endif
\ No newline at end of file
+#endif
if (!InitMovingBrushTrigger())
return;
self.effects |= EF_LOWPRECISION;
-
+
if (self.spawnflags & 2)
{
self.platmovetype_turn = true;
#include "../../server/constants.qh"
#include "../../server/defs.qh"
#include "../deathtypes.qh"
- #include "../../server/tturrets/include/turrets_early.qh"
- #include "../vehicles/sv_vehicles.qh"
+ #include "../turrets/sv_turrets.qh"
+ #include "../vehicles/all.qh"
#include "../mapinfo.qh"
#include "../../server/anticheat.qh"
#endif
void ent_viewloc_trigger();
#endif
-#endif
\ No newline at end of file
+#endif
.vector dest;
+void FixSize(entity e);
+
#ifdef CSQC
void trigger_common_read(bool withtarget);
void trigger_remove_generic();
--- /dev/null
+#include "unit/ewheel.qc"
+#include "unit/flac.qc"
+#include "unit/fusionreactor.qc"
+#include "unit/hellion.qc"
+#include "unit/hk.qc"
+#include "unit/machinegun.qc"
+#include "unit/mlrs.qc"
+#include "unit/phaser.qc"
+#include "unit/plasma.qc"
+#include "unit/plasma_dual.qc"
+#include "unit/tesla.qc"
+#include "unit/walker.qc"
--- /dev/null
+/**
+ turret_checkpoint
+**/
+
+
+//.entity checkpoint_target;
+
+/*
+#define checkpoint_cache_who flagcarried
+#define checkpoint_cache_from lastrocket
+#define checkpoint_cache_to selected_player
+*/
+
+.entity pathgoal;
+
+/*
+entity path_makeorcache(entity forwho,entity start, entity end)
+{
+ entity oldself;
+ entity pth;
+ oldself = self;
+ self = forwho;
+
+ //pth = pathlib_makepath(start.origin,end.origin,PFL_GROUNDSNAP,500,1.5,PT_QUICKSTAR);
+
+ self = oldself;
+ return pth;
+}
+*/
+
+void turret_checkpoint_use()
+{
+}
+
+#if 0
+void turret_checkpoint_think()
+{
+ if(self.enemy)
+ te_lightning1(self,self.origin, self.enemy.origin);
+
+ self.nextthink = time + 0.25;
+}
+#endif
+/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
+-----------KEYS------------
+target: .targetname of next waypoint in chain.
+wait: Pause at this point # seconds.
+-----------SPAWNFLAGS-----------
+---------NOTES----------
+If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
+If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+*/
+//float tc_acum;
+void turret_checkpoint_init()
+{
+ traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self);
+ setorigin(self, trace_endpos + '0 0 32');
+
+ if(self.target != "")
+ {
+ self.enemy = find(world, targetname, self.target);
+ if(self.enemy == world)
+ dprint("A turret_checkpoint faild to find its target!\n");
+ }
+ //self.think = turret_checkpoint_think;
+ //self.nextthink = time + tc_acum + 0.25;
+ //tc_acum += 0.25;
+}
+
+void spawnfunc_turret_checkpoint()
+{
+ setorigin(self,self.origin);
+ self.think = turret_checkpoint_init;
+ self.nextthink = time + 0.2;
+}
+
+// Compat.
+void spawnfunc_walker_checkpoint()
+{
+ self.classname = "turret_checkpoint";
+ spawnfunc_turret_checkpoint();
+}
--- /dev/null
+void turret_remove()
+{
+ remove(self.tur_head);
+ //remove(self.enemy);
+ self.tur_head = world;
+}
+
+.vector glowmod;
+void turret_changeteam()
+{
+ self.glowmod = Team_ColorRGB(self.team - 1) * 2;
+ self.teamradar_color = Team_ColorRGB(self.team - 1);
+
+ if(self.team)
+ self.colormap = 1024 + (self.team - 1) * 17;
+
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
+
+}
+
+void turret_head_draw()
+{
+ self.drawmask = MASK_NORMAL;
+}
+
+void turret_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+
+ if (self.health < 127)
+ {
+ dt = random();
+
+ if(dt < 0.03)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+ }
+
+ if(self.health < 85)
+ if(dt < 0.01)
+ pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+
+ if(self.health < 32)
+ if(dt < 0.015)
+ pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+
+}
+
+void turret_draw2d()
+{
+ if(self.netname == "")
+ return;
+
+ if(!autocvar_g_waypointsprite_turrets)
+ return;
+
+ if(autocvar_cl_hidewaypoints)
+ return;
+
+ float dist = vlen(self.origin - view_origin);
+ float t = (GetPlayerColor(player_localnum) + 1);
+
+ vector o;
+ string txt;
+
+ if(autocvar_cl_vehicles_hud_tactical)
+ if(dist < 10240 && t != self.team)
+ {
+ // TODO: Vehicle tactical hud
+ o = project_3d_to_2d(self.origin + '0 0 32');
+ if(o_z < 0
+ || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
+ || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
+ || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
+ || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+ return; // Dont draw wp's for turrets out of view
+ o_z = 0;
+ if(hud != HUD_NORMAL)
+ {
+ if((get_turretinfo(self.turretid)).spawnflags & TUR_FLAG_MOVE)
+ txt = "gfx/vehicles/turret_moving.tga";
+ else
+ txt = "gfx/vehicles/turret_stationary.tga";
+
+ vector pz = drawgetimagesize(txt) * autocvar_cl_vehicles_crosshair_size;
+ drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.7, DRAWFLAG_NORMAL);
+ }
+ }
+
+ if(dist > self.maxdistance)
+ return;
+
+ string spriteimage = self.netname;
+ float a = self.alpha * autocvar_hud_panel_fg_alpha;
+ vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+
+
+ if(self.maxdistance > waypointsprite_normdistance)
+ a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
+ else if(self.maxdistance > 0)
+ a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
+
+ if(rgb == '0 0 0')
+ {
+ self.teamradar_color = '1 0 1';
+ printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
+ }
+
+ txt = self.netname;
+ if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
+ txt = _("Spam");
+ else
+ txt = spritelookuptext(spriteimage);
+
+ if(time - floor(time) > 0.5 && t == self.team)
+ {
+ if(self.helpme && time < self.helpme)
+ {
+ a *= SPRITE_HELPME_BLINK;
+ txt = sprintf(_("%s under attack!"), txt);
+ }
+ else
+ a *= spritelookupblinkvalue(spriteimage);
+ }
+
+ if(autocvar_g_waypointsprite_uppercase)
+ txt = strtoupper(txt);
+
+ if(a > 1)
+ {
+ rgb *= a;
+ a = 1;
+ }
+
+ if(a <= 0)
+ return;
+
+ rgb = fixrgbexcess(rgb);
+
+ o = project_3d_to_2d(self.origin + '0 0 64');
+ if(o_z < 0
+ || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
+ || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
+ || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
+ || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+ return; // Dont draw wp's for turrets out of view
+
+ o_z = 0;
+
+ float edgedistance_min, crosshairdistance;
+ edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)),
+ (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)),
+ (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x,
+ (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y);
+
+ float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
+
+ crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
+
+ t = waypointsprite_scale * vidscale;
+ a *= waypointsprite_alpha;
+
+ {
+ a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+ }
+ if (edgedistance_min < waypointsprite_edgefadedistance) {
+ a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+ }
+ if(crosshairdistance < waypointsprite_crosshairfadedistance) {
+ a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+ }
+
+ o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
+ o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+ drawhealthbar(
+ o,
+ 0,
+ self.health / 255,
+ '0 0 0',
+ '0 0 0',
+ 0.5 * SPRITE_HEALTHBAR_WIDTH * t,
+ 0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
+ SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
+ SPRITE_HEALTHBAR_BORDER * t,
+ 0,
+ rgb,
+ a * SPRITE_HEALTHBAR_BORDERALPHA,
+ rgb,
+ a * SPRITE_HEALTHBAR_HEALTHALPHA,
+ DRAWFLAG_NORMAL
+ );
+}
+
+void turret_construct()
+{
+ entity tur = get_turretinfo(self.turretid);
+
+ if(self.tur_head == world)
+ self.tur_head = spawn();
+
+ self.netname = TUR_NAME(self.turretid);
+
+ setorigin(self, self.origin);
+ setmodel(self, tur.model);
+ setmodel(self.tur_head, tur.head_model);
+ setsize(self, tur.mins, tur.maxs);
+ setsize(self.tur_head, '0 0 0', '0 0 0');
+
+ if(self.turretid == TUR_EWHEEL)
+ setattachment(self.tur_head, self, "");
+ else
+ setattachment(self.tur_head, self, "tag_head");
+
+ self.tur_head.classname = "turret_head";
+ self.tur_head.owner = self;
+ self.tur_head.move_movetype = MOVETYPE_NOCLIP;
+ self.move_movetype = MOVETYPE_NOCLIP;
+ self.tur_head.angles = self.angles;
+ self.health = 255;
+ self.solid = SOLID_BBOX;
+ self.tur_head.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.tur_head.movetype = MOVETYPE_NOCLIP;
+ self.draw = turret_draw;
+ self.entremove = turret_remove;
+ self.drawmask = MASK_NORMAL;
+ self.tur_head.drawmask = MASK_NORMAL;
+ self.anim_start_time = 0;
+ self.draw2d = turret_draw2d;
+ self.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
+ self.teamradar_color = '1 0 0';
+ self.alpha = 1;
+
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
+void turret_gibboom();
+void turret_gib_draw()
+{
+ Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+
+ self.drawmask = MASK_NORMAL;
+
+ if(self.cnt)
+ {
+ if(time >= self.nextthink)
+ {
+ turret_gibboom();
+ remove(self);
+ }
+ }
+ else
+ {
+ self.alpha = bound(0, self.nextthink - time, 1);
+ if(self.alpha < ALPHA_MIN_VISIBLE)
+ remove(self);
+ }
+}
+
+void turret_gibboom()
+{
+ float i;
+
+ sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+ for (i = 1; i < 5; i = i + 1)
+ turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', false);
+}
+
+entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
+{
+ entity gib;
+
+ traceline(_from, _to, MOVE_NOMONSTERS, world);
+ if(trace_startsolid)
+ return world;
+
+ gib = spawn();
+ setorigin(gib, _from);
+ setmodel(gib, _model);
+ gib.colormod = _cmod;
+ gib.solid = SOLID_CORPSE;
+ gib.draw = turret_gib_draw;
+ gib.cnt = _explode;
+ setsize(gib, '-1 -1 -1', '1 1 1');
+ if(_explode)
+ {
+ gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
+ gib.effects = EF_FLAME;
+ }
+ else
+ gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
+
+ gib.gravity = 1;
+ gib.move_movetype = MOVETYPE_BOUNCE;
+ gib.move_origin = _from;
+ setorigin(gib, _from);
+ gib.move_velocity = _to;
+ gib.move_avelocity = prandomvec() * 32;
+ gib.move_time = time;
+ gib.damageforcescale = 1;
+ gib.classname = "turret_gib";
+
+ return gib;
+}
+
+void turret_die()
+{
+ sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ if (!autocvar_cl_nogibs)
+ {
+ // Base
+ if(self.turretid == TUR_EWHEEL)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
+ else if (self.turretid == TUR_WALKER)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
+ else if (self.turretid == TUR_TESLA)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
+ else
+ {
+ if (random() > 0.5)
+ {
+ turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
+ turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
+ turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
+ }
+ else
+ turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', true);
+
+ entity headgib = turret_gibtoss((get_turretinfo(self.turretid)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
+ if(headgib)
+ {
+ headgib.angles = headgib.move_angles = self.tur_head.angles;
+ headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
+ headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
+ headgib.gravity = 0.5;
+ }
+ }
+ }
+
+ setmodel(self, "null");
+ setmodel(self.tur_head, "null");
+}
+
+void ent_turret()
+{
+ float sf;
+ sf = ReadByte();
+
+ if(sf & TNSF_SETUP)
+ {
+ self.turretid = ReadByte();
+
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.angles_x = ReadAngle();
+ self.angles_y = ReadAngle();
+
+ turret_construct();
+ self.colormap = 1024;
+ self.glowmod = '0 1 1';
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
+ }
+
+ if(sf & TNSF_ANG)
+ {
+ if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
+ self.tur_head = spawn();
+
+ self.tur_head.move_angles_x = ReadShort();
+ self.tur_head.move_angles_y = ReadShort();
+ //self.tur_head.angles = self.angles + self.tur_head.move_angles;
+ self.tur_head.angles = self.tur_head.move_angles;
+ }
+
+ if(sf & TNSF_AVEL)
+ {
+ if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
+ self.tur_head = spawn();
+
+ self.tur_head.move_avelocity_x = ReadShort();
+ self.tur_head.move_avelocity_y = ReadShort();
+ }
+
+ if(sf & TNSF_MOVE)
+ {
+ self.origin_x = ReadShort();
+ self.origin_y = ReadShort();
+ self.origin_z = ReadShort();
+ setorigin(self, self.origin);
+
+ self.velocity_x = ReadShort();
+ self.velocity_y = ReadShort();
+ self.velocity_z = ReadShort();
+
+ self.move_angles_y = ReadShort();
+
+ self.move_time = time;
+ self.move_velocity = self.velocity;
+ self.move_origin = self.origin;
+ }
+
+ if(sf & TNSF_ANIM)
+ {
+ self.frame1time = ReadCoord();
+ self.frame = ReadByte();
+ }
+
+ if(sf & TNSF_STATUS)
+ {
+ float _tmp;
+ _tmp = ReadByte();
+ if(_tmp != self.team)
+ {
+ self.team = _tmp;
+ turret_changeteam();
+ }
+
+ _tmp = ReadByte();
+ if(_tmp == 0 && self.health != 0)
+ turret_die();
+ else if(self.health && self.health != _tmp)
+ self.helpme = servertime + 10;
+
+ self.health = _tmp;
+ }
+ //self.enemy.health = self.health / 255;
+}
--- /dev/null
+#ifndef CL_TURRETS_H
+#define CL_TURRETS_H
+
+void ent_turret();
+
+#endif
--- /dev/null
+// ==========================
+// Turret Config Generator
+// ==========================
+
+void T_Config_Queue_Swap(float root, float child, entity pass)
+{
+ string oldroot = tur_config_queue[root];
+ tur_config_queue[root] = tur_config_queue[child];
+ tur_config_queue[child] = oldroot;
+}
+
+float T_Config_Queue_Compare(float root, float child, entity pass)
+{
+ float i, r, c;
+
+ for(i = 1; i <= 100; ++i)
+ {
+ r = str2chr(tur_config_queue[root], i);
+ c = str2chr(tur_config_queue[child], i);
+ if(r == c) { continue; }
+ else if(c > r) { return -1; }
+ else { return 1; }
+ }
+
+ return 0;
+}
+
+void Dump_Turret_Settings(void)
+{
+ float i, x, totalsettings = 0;
+ for(i = TUR_FIRST; i <= TUR_LAST; ++i)
+ {
+ // step 1: clear the queue
+ TUR_CONFIG_COUNT = 0;
+ for(x = 0; x <= MAX_TUR_CONFIG; ++x)
+ { tur_config_queue[x] = string_null; }
+
+ // step 2: build new queue
+ TUR_ACTION(i, TR_CONFIG);
+
+ // step 3: sort queue
+ heapsort(TUR_CONFIG_COUNT, T_Config_Queue_Swap, T_Config_Queue_Compare, world);
+
+ // step 4: write queue
+ TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, TUR_NAME(i)))
+ for(x = 0; x <= TUR_CONFIG_COUNT; ++x)
+ { TUR_CONFIG_WRITETOFILE(tur_config_queue[x]) }
+ TUR_CONFIG_WRITETOFILE("// }}}\n")
+
+ // step 5: debug info
+ print(sprintf("#%d: %s: %d settings...\n", i, TUR_NAME(i), TUR_CONFIG_COUNT));
+ totalsettings += TUR_CONFIG_COUNT;
+ }
+
+ // clear queue now that we're finished
+ TUR_CONFIG_COUNT = 0;
+ for(x = 0; x <= MAX_TUR_CONFIG; ++x)
+ { tur_config_queue[x] = string_null; }
+
+ // extra information
+ print(sprintf("Totals: %d turrets, %d settings\n", (i - 1), totalsettings));
+}
--- /dev/null
+#ifndef TURRETS_CONFIG_H
+#define TURRETS_CONFIG_H
+
+#ifdef SVQC
+
+void Dump_Turret_Settings(void);
+float tur_config_file;
+float tur_config_alsoprint;
+
+#define MAX_TUR_CONFIG 256
+float TUR_CONFIG_COUNT;
+string tur_config_queue[MAX_TUR_CONFIG];
+
+#define TUR_CONFIG_QUEUE(a) { \
+ tur_config_queue[TUR_CONFIG_COUNT] = a; \
+ ++TUR_CONFIG_COUNT; }
+
+#define TUR_CONFIG_WRITETOFILE(a) { \
+ fputs(tur_config_file, a); \
+ if(tur_config_alsoprint) { print(a); } }
+
+#define TUR_CONFIG_WRITE_CVARS(turret,name) \
+ { TUR_CONFIG_QUEUE( \
+ sprintf("set g_turrets_unit_%s_%s %g\n", #turret, #name, \
+ cvar(sprintf("g_turrets_unit_%s_%s", #turret, #name)))) } \
+
+#define TUR_CONFIG_SETTINGS(tursettings) \
+ #define TUR_ADD_CVAR(turret,name) TUR_CONFIG_WRITE_CVARS(turret,name) \
+ tursettings \
+ #undef TUR_ADD_CVAR
+
+#endif
+
+#endif
--- /dev/null
+#ifdef SVQC
+#include "../../server/autocvars.qh"
+
+// Generic aiming
+vector turret_aim_generic()
+{
+
+ vector pre_pos, prep;
+ float distance, impact_time = 0, i, mintime;
+
+ turret_tag_fire_update();
+
+ if(self.aim_flags & TFL_AIM_SIMPLE)
+ return real_origin(self.enemy);
+
+ mintime = max(self.attack_finished_single - time,0) + sys_frametime;
+
+ // Baseline
+ pre_pos = real_origin(self.enemy);
+
+ // Lead?
+ if (self.aim_flags & TFL_AIM_LEAD)
+ {
+ if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
+ {
+ prep = pre_pos;
+
+ distance = vlen(prep - self.tur_shotorg);
+ impact_time = distance / self.shot_speed;
+
+ prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
+
+ if(self.aim_flags & TFL_AIM_ZPREDICT)
+ if(!(self.enemy.flags & FL_ONGROUND))
+ if(self.enemy.movetype == MOVETYPE_WALK || self.enemy.movetype == MOVETYPE_TOSS || self.enemy.movetype == MOVETYPE_BOUNCE)
+ {
+ float vz;
+ prep_z = pre_pos_z;
+ vz = self.enemy.velocity_z;
+ for(i = 0; i < impact_time; i += sys_frametime)
+ {
+ vz = vz - (autocvar_sv_gravity * sys_frametime);
+ prep_z = prep_z + vz * sys_frametime;
+ }
+ }
+ pre_pos = prep;
+ }
+ else
+ pre_pos = pre_pos + self.enemy.velocity * mintime;
+ }
+
+ if(self.aim_flags & TFL_AIM_SPLASH)
+ {
+ //tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
+ traceline(pre_pos + '0 0 32',pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
+ if(trace_fraction != 1.0)
+ pre_pos = trace_endpos;
+ }
+
+ return pre_pos;
+}
+
+float turret_targetscore_support(entity _turret,entity _target)
+{
+ float score; // Total score
+ float s_score = 0, d_score;
+
+ if (_turret.enemy == _target) s_score = 1;
+
+ d_score = min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist);
+
+ score = (d_score * _turret.target_select_rangebias) +
+ (s_score * _turret.target_select_samebias);
+
+ return score;
+}
+
+/*
+* Generic bias aware score system.
+*/
+float turret_targetscore_generic(entity _turret, entity _target)
+{
+ float d_dist; // Defendmode Distance
+ float score; // Total score
+ float d_score; // Distance score
+ float a_score; // Angular score
+ float m_score = 0; // missile score
+ float p_score = 0; // player score
+ float ikr; // ideal kill range
+
+ if (_turret.tur_defend)
+ {
+ d_dist = vlen(real_origin(_target) - _turret.tur_defend.origin);
+ ikr = vlen(_turret.origin - _turret.tur_defend.origin);
+ d_score = 1 - d_dist / _turret.target_range;
+ }
+ else
+ {
+ // Make a normlized value base on the targets distance from our optimal killzone
+ ikr = _turret.target_range_optimal;
+ d_score = min(ikr, tvt_dist) / max(ikr, tvt_dist);
+ }
+
+ a_score = 1 - tvt_thadf / _turret.aim_maxrotate;
+
+ if ((_turret.target_select_missilebias > 0) && (_target.flags & FL_PROJECTILE))
+ m_score = 1;
+
+ if ((_turret.target_select_playerbias > 0) && IS_CLIENT(_target))
+ p_score = 1;
+
+ d_score = max(d_score, 0);
+ a_score = max(a_score, 0);
+ m_score = max(m_score, 0);
+ p_score = max(p_score, 0);
+
+ score = (d_score * _turret.target_select_rangebias) +
+ (a_score * _turret.target_select_anglebias) +
+ (m_score * _turret.target_select_missilebias) +
+ (p_score * _turret.target_select_playerbias);
+
+ if(_turret.target_range < vlen(_turret.tur_shotorg - real_origin(_target)))
+ {
+ //dprint("Wtf?\n");
+ score *= 0.001;
+ }
+
+#ifdef TURRET_DEBUG
+ string sd,sa,sm,sp,ss;
+ string sdt,sat,smt,spt;
+
+ sd = ftos(d_score);
+ d_score *= _turret.target_select_rangebias;
+ sdt = ftos(d_score);
+
+ //sv = ftos(v_score);
+ //v_score *= _turret.target_select_samebias;
+ //svt = ftos(v_score);
+
+ sa = ftos(a_score);
+ a_score *= _turret.target_select_anglebias;
+ sat = ftos(a_score);
+
+ sm = ftos(m_score);
+ m_score *= _turret.target_select_missilebias;
+ smt = ftos(m_score);
+
+ sp = ftos(p_score);
+ p_score *= _turret.target_select_playerbias;
+ spt = ftos(p_score);
+
+
+ ss = ftos(score);
+ bprint("^3Target scores^7 \[ ",_turret.netname, " \] ^3for^7 \[ ", _target.netname," \]\n");
+ bprint("^5Range:\[ ",sd, " \]^2+bias:\[ ",sdt," \]\n");
+ bprint("^5Angle:\[ ",sa, " \]^2+bias:\[ ",sat," \]\n");
+ bprint("^5Missile:\[ ",sm," \]^2+bias:\[ ",smt," \]\n");
+ bprint("^5Player:\[ ",sp, " \]^2+bias:\[ ",spt," \]\n");
+ bprint("^3Total (w/bias):\[^1",ss,"\]\n");
+
+#endif
+
+ return score;
+}
+
+// Generic damage handling
+void turret_hide()
+{
+ self.effects |= EF_NODRAW;
+ self.nextthink = time + self.respawntime - 0.2;
+ self.think = turret_respawn;
+}
+
+void turret_die()
+{
+ self.deadflag = DEAD_DEAD;
+ self.tur_head.deadflag = self.deadflag;
+
+// Unsolidify and hide real parts
+ self.solid = SOLID_NOT;
+ self.tur_head.solid = self.solid;
+
+ self.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+
+ self.health = 0;
+
+// Go boom
+ //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
+
+ if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
+ {
+ TUR_ACTION(self.turretid, TR_DEATH);
+
+ remove(self.tur_head);
+ remove(self);
+ }
+ else
+ {
+ // Setup respawn
+ self.SendFlags |= TNSF_STATUS;
+ self.nextthink = time + 0.2;
+ self.think = turret_hide;
+
+ TUR_ACTION(self.turretid, TR_DEATH);
+ }
+}
+
+void turret_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
+{
+ // Enough already!
+ if(self.deadflag == DEAD_DEAD)
+ return;
+
+ // Inactive turrets take no damage. (hm..)
+ if(!self.active)
+ return;
+
+ if(SAME_TEAM(self, attacker))
+ {
+ if(autocvar_g_friendlyfire)
+ damage = damage * autocvar_g_friendlyfire;
+ else
+ return;
+ }
+
+ self.health -= damage;
+
+ // thorw head slightly off aim when hit?
+ if (self.damage_flags & TFL_DMG_HEADSHAKE)
+ {
+ self.tur_head.angles_x = self.tur_head.angles_x + (-0.5 + random()) * damage;
+ self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if (self.turret_flags & TUR_FLAG_MOVE)
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ {
+ self.event_damage = func_null;
+ self.tur_head.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+ self.nextthink = time;
+ self.think = turret_die;
+ }
+
+ self.SendFlags |= TNSF_STATUS;
+}
+
+void() turret_think;
+void turret_respawn()
+{
+ // Make sure all parts belong to the same team since
+ // this function doubles as "teamchange" function.
+ self.tur_head.team = self.team;
+ self.effects &= ~EF_NODRAW;
+ self.deadflag = DEAD_NO;
+ self.effects = EF_LOWPRECISION;
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.event_damage = turret_damage;
+ self.avelocity = '0 0 0';
+ self.tur_head.avelocity = self.avelocity;
+ self.tur_head.angles = self.idle_aim;
+ self.health = self.max_health;
+ self.enemy = world;
+ self.volly_counter = self.shot_volly;
+ self.ammo = self.ammo_max;
+
+ self.nextthink = time + self.ticrate;
+ self.think = turret_think;
+
+ self.SendFlags = TNSF_FULL_UPDATE;
+
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+
+// Main functions
+#define cvar_base "g_turrets_unit_"
+.float clientframe;
+void turrets_setframe(float _frame, float client_only)
+{
+ if((client_only ? self.clientframe : self.frame ) != _frame)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ if(client_only)
+ self.clientframe = _frame;
+ else
+ self.frame = _frame;
+
+}
+
+float turret_send(entity to, float sf)
+{
+
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & TNSF_SETUP)
+ {
+ WriteByte(MSG_ENTITY, self.turretid);
+
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteAngle(MSG_ENTITY, self.angles_x);
+ WriteAngle(MSG_ENTITY, self.angles_y);
+ }
+
+ if(sf & TNSF_ANG)
+ {
+ WriteShort(MSG_ENTITY, rint(self.tur_head.angles_x));
+ WriteShort(MSG_ENTITY, rint(self.tur_head.angles_y));
+ }
+
+ if(sf & TNSF_AVEL)
+ {
+ WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_x));
+ WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_y));
+ }
+
+ if(sf & TNSF_MOVE)
+ {
+ WriteShort(MSG_ENTITY, rint(self.origin_x));
+ WriteShort(MSG_ENTITY, rint(self.origin_y));
+ WriteShort(MSG_ENTITY, rint(self.origin_z));
+
+ WriteShort(MSG_ENTITY, rint(self.velocity_x));
+ WriteShort(MSG_ENTITY, rint(self.velocity_y));
+ WriteShort(MSG_ENTITY, rint(self.velocity_z));
+
+ WriteShort(MSG_ENTITY, rint(self.angles_y));
+ }
+
+ if(sf & TNSF_ANIM)
+ {
+ WriteCoord(MSG_ENTITY, self.anim_start_time);
+ WriteByte(MSG_ENTITY, self.frame);
+ }
+
+ if(sf & TNSF_STATUS)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+
+ if(self.health <= 0)
+ WriteByte(MSG_ENTITY, 0);
+ else
+ WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255));
+ }
+
+ return true;
+}
+
+void load_unit_settings(entity ent, string unitname, float is_reload)
+{
+ string sbase;
+
+ if (ent == world)
+ return;
+
+ if(!ent.turret_scale_damage) ent.turret_scale_damage = 1;
+ if(!ent.turret_scale_range) ent.turret_scale_range = 1;
+ if(!ent.turret_scale_refire) ent.turret_scale_refire = 1;
+ if(!ent.turret_scale_ammo) ent.turret_scale_ammo = 1;
+ if(!ent.turret_scale_aim) ent.turret_scale_aim = 1;
+ if(!ent.turret_scale_health) ent.turret_scale_health = 1;
+ if(!ent.turret_scale_respawn) ent.turret_scale_respawn = 1;
+
+ sbase = strcat(cvar_base,unitname);
+ if (is_reload)
+ {
+ ent.enemy = world;
+ ent.tur_head.avelocity = '0 0 0';
+
+ ent.tur_head.angles = '0 0 0';
+ }
+
+ ent.health = cvar(strcat(sbase,"_health")) * ent.turret_scale_health;
+ ent.respawntime = cvar(strcat(sbase,"_respawntime")) * ent.turret_scale_respawn;
+
+ ent.shot_dmg = cvar(strcat(sbase,"_shot_dmg")) * ent.turret_scale_damage;
+ ent.shot_refire = cvar(strcat(sbase,"_shot_refire")) * ent.turret_scale_refire;
+ ent.shot_radius = cvar(strcat(sbase,"_shot_radius")) * ent.turret_scale_damage;
+ ent.shot_speed = cvar(strcat(sbase,"_shot_speed"));
+ ent.shot_spread = cvar(strcat(sbase,"_shot_spread"));
+ ent.shot_force = cvar(strcat(sbase,"_shot_force")) * ent.turret_scale_damage;
+ ent.shot_volly = cvar(strcat(sbase,"_shot_volly"));
+ ent.shot_volly_refire = cvar(strcat(sbase,"_shot_volly_refire")) * ent.turret_scale_refire;
+
+ ent.target_range = cvar(strcat(sbase,"_target_range")) * ent.turret_scale_range;
+ ent.target_range_min = cvar(strcat(sbase,"_target_range_min")) * ent.turret_scale_range;
+ ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * ent.turret_scale_range;
+ //ent.target_range_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
+
+ ent.target_select_rangebias = cvar(strcat(sbase,"_target_select_rangebias"));
+ ent.target_select_samebias = cvar(strcat(sbase,"_target_select_samebias"));
+ ent.target_select_anglebias = cvar(strcat(sbase,"_target_select_anglebias"));
+ ent.target_select_playerbias = cvar(strcat(sbase,"_target_select_playerbias"));
+ //ent.target_select_fov = cvar(cvar_gets(sbase,"_target_select_fov"));
+
+ ent.ammo_max = cvar(strcat(sbase,"_ammo_max")) * ent.turret_scale_ammo;
+ ent.ammo_recharge = cvar(strcat(sbase,"_ammo_recharge")) * ent.turret_scale_ammo;
+
+ ent.aim_firetolerance_dist = cvar(strcat(sbase,"_aim_firetolerance_dist"));
+ ent.aim_speed = cvar(strcat(sbase,"_aim_speed")) * ent.turret_scale_aim;
+ ent.aim_maxrotate = cvar(strcat(sbase,"_aim_maxrot"));
+ ent.aim_maxpitch = cvar(strcat(sbase,"_aim_maxpitch"));
+
+ ent.track_type = cvar(strcat(sbase,"_track_type"));
+ ent.track_accel_pitch = cvar(strcat(sbase,"_track_accel_pitch"));
+ ent.track_accel_rotate = cvar(strcat(sbase,"_track_accel_rot"));
+ ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
+
+ if(is_reload)
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+void turret_projectile_explode()
+{
+
+ self.takedamage = DAMAGE_NO;
+ self.event_damage = func_null;
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_debug_dmg_t_h = self.owner.tur_debug_dmg_t_h + d;
+ self.owner.tur_debug_dmg_t_f = self.owner.tur_debug_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+void turret_projectile_touch()
+{
+ PROJECTILE_TOUCH;
+ turret_projectile_explode();
+}
+
+void turret_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
+{
+ self.velocity += vforce;
+ self.health -= damage;
+ //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
+ if(self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, turret_projectile_explode);
+}
+
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
+{
+ entity proj;
+
+ sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
+ proj.owner = self;
+ proj.realowner = self;
+ proj.bot_dodge = true;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_projectile_explode;
+ proj.touch = turret_projectile_touch;
+ proj.nextthink = time + 9;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ proj.flags = FL_PROJECTILE;
+ proj.enemy = self.enemy;
+ proj.totalfrags = _death;
+ PROJECTILE_MAKETRIGGER(proj);
+ if(_health)
+ {
+ proj.health = _health;
+ proj.takedamage = DAMAGE_YES;
+ proj.event_damage = turret_projectile_damage;
+ }
+ else
+ proj.flags |= FL_NOTARGET;
+
+ CSQCProjectile(proj, _cli_anim, _proj_type, _cull);
+
+ return proj;
+}
+
+/**
+** updates enemy distances, predicted impact point/time
+** and updated aim<->predict impact distance.
+**/
+void turret_do_updates(entity t_turret)
+{
+ vector enemy_pos;
+ entity oldself;
+
+ oldself = self;
+ self = t_turret;
+
+ enemy_pos = real_origin(self.enemy);
+
+ turret_tag_fire_update();
+
+ self.tur_shotdir_updated = v_forward;
+ self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos);
+ self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos);
+
+ /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy))
+ {
+ oldpos = self.enemy.origin;
+ setorigin(self.enemy, self.tur_aimpos);
+ tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
+ setorigin(self.enemy, oldpos);
+
+ if(trace_ent == self.enemy)
+ self.tur_dist_impact_to_aimpos = 0;
+ else
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
+ }
+ else*/
+ tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
+
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5);
+ self.tur_impactent = trace_ent;
+ self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
+
+ self = oldself;
+}
+
+/**
+** Handles head rotation according to
+** the units .track_type and .track_flags
+**/
+.float turret_framecounter;
+void turret_track()
+{
+ vector target_angle; // This is where we want to aim
+ vector move_angle; // This is where we can aim
+ float f_tmp;
+ vector v1, v2;
+ v1 = self.tur_head.angles;
+ v2 = self.tur_head.avelocity;
+
+ if (self.track_flags == TFL_TRACK_NO)
+ return;
+
+ if(!self.active)
+ target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
+ else if (self.enemy == world)
+ {
+ if(time > self.lip)
+ target_angle = self.idle_aim + self.angles;
+ else
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
+ }
+ else
+ {
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
+ }
+
+ self.tur_head.angles_x = anglemods(self.tur_head.angles_x);
+ self.tur_head.angles_y = anglemods(self.tur_head.angles_y);
+
+ // Find the diffrence between where we currently aim and where we want to aim
+ //move_angle = target_angle - (self.angles + self.tur_head.angles);
+ //move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
+
+ move_angle = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(self.angles), AnglesTransform_FromAngles(target_angle))) - self.tur_head.angles;
+ move_angle = shortangle_vxy(move_angle, self.tur_head.angles);
+
+ switch(self.track_type)
+ {
+ case TFL_TRACKTYPE_STEPMOTOR:
+ f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
+ if (self.track_flags & TFL_TRACK_PITCH)
+ {
+ self.tur_head.angles_x += bound(-f_tmp,move_angle_x, f_tmp);
+ if(self.tur_head.angles_x > self.aim_maxpitch)
+ self.tur_head.angles_x = self.aim_maxpitch;
+
+ if(self.tur_head.angles_x < -self.aim_maxpitch)
+ self.tur_head.angles_x = self.aim_maxpitch;
+ }
+
+ if (self.track_flags & TFL_TRACK_ROTATE)
+ {
+ self.tur_head.angles_y += bound(-f_tmp, move_angle_y, f_tmp);
+ if(self.tur_head.angles_y > self.aim_maxrotate)
+ self.tur_head.angles_y = self.aim_maxrotate;
+
+ if(self.tur_head.angles_y < -self.aim_maxrotate)
+ self.tur_head.angles_y = self.aim_maxrotate;
+ }
+
+ // CSQC
+ self.SendFlags |= TNSF_ANG;
+
+ return;
+
+ case TFL_TRACKTYPE_FLUIDINERTIA:
+ f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
+ move_angle_x = bound(-self.aim_speed, move_angle_x * self.track_accel_pitch * f_tmp, self.aim_speed);
+ move_angle_y = bound(-self.aim_speed, move_angle_y * self.track_accel_rotate * f_tmp, self.aim_speed);
+ move_angle = (self.tur_head.avelocity * self.track_blendrate) + (move_angle * (1 - self.track_blendrate));
+ break;
+
+ case TFL_TRACKTYPE_FLUIDPRECISE:
+
+ move_angle_y = bound(-self.aim_speed, move_angle_y, self.aim_speed);
+ move_angle_x = bound(-self.aim_speed, move_angle_x, self.aim_speed);
+
+ break;
+ }
+
+ // pitch
+ if (self.track_flags & TFL_TRACK_PITCH)
+ {
+ self.tur_head.avelocity_x = move_angle_x;
+ if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) > self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = self.aim_maxpitch;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) < -self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = -self.aim_maxpitch;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+ }
+
+ // rot
+ if (self.track_flags & TFL_TRACK_ROTATE)
+ {
+ self.tur_head.avelocity_y = move_angle_y;
+
+ if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) > self.aim_maxrotate)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = self.aim_maxrotate;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) < -self.aim_maxrotate)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = -self.aim_maxrotate;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+ }
+
+ self.SendFlags |= TNSF_AVEL;
+
+ // Force a angle update every 10'th frame
+ self.turret_framecounter += 1;
+ if(self.turret_framecounter >= 10)
+ {
+ self.SendFlags |= TNSF_ANG;
+ self.turret_framecounter = 0;
+ }
+}
+
+/*
+ + TFL_TARGETSELECT_NO
+ + TFL_TARGETSELECT_LOS
+ + TFL_TARGETSELECT_PLAYERS
+ + TFL_TARGETSELECT_MISSILES
+ - TFL_TARGETSELECT_TRIGGERTARGET
+ + TFL_TARGETSELECT_ANGLELIMITS
+ + TFL_TARGETSELECT_RANGELIMITS
+ + TFL_TARGETSELECT_TEAMCHECK
+ - TFL_TARGETSELECT_NOBUILTIN
+ + TFL_TARGETSELECT_OWNTEAM
+*/
+
+/**
+** Evaluate a entity for target valitity based on validate_flags
+** NOTE: the caller must check takedamage before calling this, to inline this check.
+**/
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
+{
+ vector v_tmp;
+
+ //if(!validate_flags & TFL_TARGETSELECT_NOBUILTIN)
+ // return -0.5;
+
+ if(!e_target)
+ return -2;
+
+ if(e_target.owner == e_turret)
+ return -0.5;
+
+ if(!checkpvs(e_target.origin, e_turret))
+ return -1;
+
+ if(e_target.alpha <= 0.3)
+ return -1;
+
+ if(g_onslaught)
+ if (substring(e_target.classname, 0, 10) == "onslaught_") // don't attack onslaught targets, that's the player's job!
+ return - 3;
+
+ if (validate_flags & TFL_TARGETSELECT_NO)
+ return -4;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return -5;
+
+ // Cant touch this
+ if(IS_VEHICLE(e_target))
+ {
+ if (e_target.vehicle_health <= 0)
+ return -6;
+ }
+ else if (e_target.health <= 0)
+ return -6;
+ else if(e_target.frozen > 0)
+ return -6;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
+ if(!(validate_flags & TFL_TARGETSELECT_PLAYERS))
+ return -7;
+
+ if (e_target.deadflag != DEAD_NO)
+ return -8;
+ }
+
+ // enemy turrets
+ if(validate_flags & TFL_TARGETSELECT_NOTURRETS)
+ if(e_target.owner.tur_head == e_target)
+ if(e_target.team != e_turret.team) // Dont break support units.
+ return -9;
+
+ // Missile
+ if (e_target.flags & FL_PROJECTILE)
+ if(!(validate_flags & TFL_TARGETSELECT_MISSILES))
+ return -10;
+
+ if (validate_flags & TFL_TARGETSELECT_MISSILESONLY)
+ if(!(e_target.flags & FL_PROJECTILE))
+ return -10.5;
+
+ // Team check
+ if (validate_flags & TFL_TARGETSELECT_TEAMCHECK)
+ {
+ if (validate_flags & TFL_TARGETSELECT_OWNTEAM)
+ {
+ if (e_target.team != e_turret.team)
+ return -11;
+
+ if (e_turret.team != e_target.owner.team)
+ return -12;
+ }
+ else
+ {
+ if (e_target.team == e_turret.team)
+ return -13;
+
+ if (e_turret.team == e_target.owner.team)
+ return -14;
+ }
+ }
+
+ // Range limits?
+ tvt_dist = vlen(e_turret.origin - real_origin(e_target));
+ if (validate_flags & TFL_TARGETSELECT_RANGELIMITS)
+ {
+ if (tvt_dist < e_turret.target_range_min)
+ return -15;
+
+ if (tvt_dist > e_turret.target_range)
+ return -16;
+ }
+
+ // Can we even aim this thing?
+ tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target);
+ tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
+ tvt_thadf = vlen(tvt_thadv);
+ tvt_tadf = vlen(tvt_tadv);
+
+ /*
+ if(validate_flags & TFL_TARGETSELECT_FOV)
+ {
+ if(e_turret.target_select_fov < tvt_thadf)
+ return -21;
+ }
+ */
+
+ if (validate_flags & TFL_TARGETSELECT_ANGLELIMITS)
+ {
+ if (fabs(tvt_tadv_x) > e_turret.aim_maxpitch)
+ return -17;
+
+ if (fabs(tvt_tadv_y) > e_turret.aim_maxrotate)
+ return -18;
+ }
+
+ // Line of sight?
+ if (validate_flags & TFL_TARGETSELECT_LOS)
+ {
+ v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5);
+
+ traceline(e_turret.origin + '0 0 16', v_tmp, 0, e_turret);
+
+ if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos))
+ return -19;
+ }
+
+ if (e_target.classname == "grapplinghook")
+ return -20;
+
+ /*
+ if (e_target.classname == "func_button")
+ return -21;
+ */
+
+#ifdef TURRET_DEBUG_TARGETSELECT
+ dprint("Target:",e_target.netname," is a valid target for ",e_turret.netname,"\n");
+#endif
+
+ return 1;
+}
+
+entity turret_select_target()
+{
+ entity e; // target looper entity
+ float score; // target looper entity score
+ entity e_enemy; // currently best scoreing target
+ float m_score; // currently best scoreing target's score
+
+ m_score = 0;
+ if(self.enemy && self.enemy.takedamage && turret_validate_target(self,self.enemy,self.target_validate_flags) > 0)
+ {
+ e_enemy = self.enemy;
+ m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias;
+ }
+ else
+ e_enemy = self.enemy = world;
+
+ e = findradius(self.origin, self.target_range);
+
+ // Nothing to aim at?
+ if (!e)
+ return world;
+
+ while (e)
+ {
+ if(e.takedamage)
+ {
+ float f = turret_validate_target(self, e, self.target_select_flags);
+ //dprint("F is: ", ftos(f), "\n");
+ if ( f > 0)
+ {
+ score = self.turret_score_target(self,e);
+ if ((score > m_score) && (score > 0))
+ {
+ e_enemy = e;
+ m_score = score;
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ return e_enemy;
+}
+
+
+/*
+ + = implemented
+ - = not implemented
+
+ + TFL_FIRECHECK_NO
+ + TFL_FIRECHECK_WORLD
+ + TFL_FIRECHECK_DEAD
+ + TFL_FIRECHECK_DISTANCES
+ - TFL_FIRECHECK_LOS
+ + TFL_FIRECHECK_AIMDIST
+ + TFL_FIRECHECK_REALDIST
+ - TFL_FIRECHECK_ANGLEDIST
+ - TFL_FIRECHECK_TEAMCECK
+ + TFL_FIRECHECK_AFF
+ + TFL_FIRECHECK_AMMO_OWN
+ + TFL_FIRECHECK_AMMO_OTHER
+ + TFL_FIRECHECK_REFIRE
+*/
+
+/**
+** Preforms pre-fire checks based on the uints firecheck_flags
+**/
+float turret_firecheck()
+{
+ // This one just dont care =)
+ if (self.firecheck_flags & TFL_FIRECHECK_NO)
+ return 1;
+
+ if (self.enemy == world)
+ return 0;
+
+ // Ready?
+ if (self.firecheck_flags & TFL_FIRECHECK_REFIRE)
+ if (self.attack_finished_single > time) return 0;
+
+ // Special case: volly fire turret that has to fire a full volly if a shot was fired.
+ if (self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
+ if (self.volly_counter != self.shot_volly)
+ if(self.ammo >= self.shot_dmg)
+ return 1;
+
+ // Lack of zombies makes shooting dead things unnecessary :P
+ if (self.firecheck_flags & TFL_FIRECHECK_DEAD)
+ if (self.enemy.deadflag != DEAD_NO)
+ return 0;
+
+ // Own ammo?
+ if (self.firecheck_flags & TFL_FIRECHECK_AMMO_OWN)
+ if (self.ammo < self.shot_dmg)
+ return 0;
+
+ // Other's ammo? (support-supply units)
+ if (self.firecheck_flags & TFL_FIRECHECK_AMMO_OTHER)
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return 0;
+
+ // Target of opertunity?
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ {
+ self.enemy = self.tur_impactent;
+ return 1;
+ }
+
+ if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
+ {
+ // To close?
+ if (self.tur_dist_aimpos < self.target_range_min)
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ return 1; // Target of opertunity?
+ else
+ return 0;
+ }
+
+ // Try to avoid FF?
+ if (self.firecheck_flags & TFL_FIRECHECK_AFF)
+ if (self.tur_impactent.team == self.team)
+ return 0;
+
+ // aim<->predicted impact
+ if (self.firecheck_flags & TFL_FIRECHECK_AIMDIST)
+ if (self.tur_dist_impact_to_aimpos > self.aim_firetolerance_dist)
+ return 0;
+
+ // Volly status
+ if (self.shot_volly > 1)
+ if (self.volly_counter == self.shot_volly)
+ if (self.ammo < (self.shot_dmg * self.shot_volly))
+ return 0;
+
+ /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
+ if(self.tur_impactent != self.enemy)
+ return 0;*/
+
+ return 1;
+}
+
+void turret_fire()
+{
+ if (autocvar_g_turrets_nofire != 0)
+ return;
+
+ TUR_ACTION(self.turretid, TR_ATTACK);
+
+ self.attack_finished_single = time + self.shot_refire;
+ self.ammo -= self.shot_dmg;
+ self.volly_counter = self.volly_counter - 1;
+
+ if (self.volly_counter <= 0)
+ {
+ self.volly_counter = self.shot_volly;
+
+ if (self.shoot_flags & TFL_SHOOT_CLEARTARGET)
+ self.enemy = world;
+
+ if (self.shot_volly > 1)
+ self.attack_finished_single = time + self.shot_volly_refire;
+ }
+
+#ifdef TURRET_DEBUG
+ if (self.enemy) paint_target3(self.tur_aimpos, 64, self.tur_debug_rvec, self.tur_impacttime + 0.25);
+#endif
+}
+
+void turret_think()
+{
+ entity e;
+
+ self.nextthink = time + self.ticrate;
+
+ // ONS uses somewhat backwards linking.
+ if (teamplay)
+ {
+ if (g_onslaught)
+ if (self.target)
+ {
+ e = find(world, targetname,self.target);
+ if (e != world)
+ self.team = e.team;
+ }
+
+ if (self.team != self.tur_head.team)
+ turret_respawn();
+ }
+
+#ifdef TURRET_DEBUG
+ if (self.tur_debug_tmr1 < time)
+ {
+ if (self.enemy) paint_target (self.enemy,128,self.tur_debug_rvec,0.9);
+ paint_target(self,256,self.tur_debug_rvec,0.9);
+ self.tur_debug_tmr1 = time + 1;
+ }
+#endif
+
+ // Handle ammo
+ if (!(self.spawnflags & TSF_NO_AMMO_REGEN))
+ if (self.ammo < self.ammo_max)
+ self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max);
+
+ // Inactive turrets needs to run the think loop,
+ // So they can handle animation and wake up if need be.
+ if(!self.active)
+ {
+ turret_track();
+ return;
+ }
+
+ // This is typicaly used for zaping every target in range
+ // turret_fusionreactor uses this to recharge friendlys.
+ if (self.shoot_flags & TFL_SHOOT_HITALLVALID)
+ {
+ // Do a self.turret_fire for every valid target.
+ e = findradius(self.origin,self.target_range);
+ while (e)
+ {
+ if(e.takedamage)
+ {
+ if (turret_validate_target(self,e,self.target_validate_flags))
+ {
+ self.enemy = e;
+
+ turret_do_updates(self);
+
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+ }
+
+ e = e.chain;
+ }
+ self.enemy = world;
+ }
+ else if(self.shoot_flags & TFL_SHOOT_CUSTOM)
+ {
+ // This one is doing something.. oddball. assume its handles what needs to be handled.
+
+ // Predict?
+ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch?
+ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire?
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+ else
+ {
+ // Special case for volly always. if it fired once it must compleate the volly.
+ if(self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
+ if(self.volly_counter != self.shot_volly)
+ {
+ // Predict or whatnot
+ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch
+ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire!
+ if (self.turret_firecheckfunc() != 0)
+ turret_fire();
+
+ TUR_ACTION(self.turretid, TR_THINK);
+
+ return;
+ }
+
+ // Check if we have a vailid enemy, and try to find one if we dont.
+
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ // No target, just go to idle, do any custom stuff and bail.
+ if (self.enemy == world)
+ {
+ // Turn & pitch
+ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ TUR_ACTION(self.turretid, TR_THINK);
+
+ // And bail.
+ return;
+ }
+ else
+ self.lip = time + autocvar_g_turrets_aimidle_delay; // Keep track of the last time we had a target.
+
+ // Predict?
+ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch?
+ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire?
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+
+ TUR_ACTION(self.turretid, TR_THINK);
+}
+
+/*
+ When .used a turret switch team to activator.team.
+ If activator is world, the turret go inactive.
+*/
+void turret_use()
+{
+ dprint("Turret ",self.netname, " used by ", activator.classname, "\n");
+
+ self.team = activator.team;
+
+ if(self.team == 0)
+ self.active = ACTIVE_NOT;
+ else
+ self.active = ACTIVE_ACTIVE;
+
+}
+
+void turret_link()
+{
+ Net_LinkEntity(self, true, 0, turret_send);
+ self.think = turret_think;
+ self.nextthink = time;
+ self.tur_head.effects = EF_NODRAW;
+}
+
+void turrets_manager_think()
+{
+ self.nextthink = time + 1;
+
+ entity e;
+ if (autocvar_g_turrets_reloadcvars == 1)
+ {
+ e = nextent(world);
+ while (e)
+ {
+ if (IS_TURRET(e))
+ {
+ load_unit_settings(e,e.cvar_basename,1);
+ TUR_ACTION(self.turretid, TR_THINK);
+ }
+
+ e = nextent(e);
+ }
+ cvar_set("g_turrets_reloadcvars","0");
+ }
+}
+
+float turret_initialize(float tur_id)
+{
+ if(!autocvar_g_turrets)
+ return false;
+
+ entity e;
+ entity tur = get_turretinfo(tur_id);
+ if(tur.turretid == 0)
+ return false; // invalid turret
+
+ if(!self.tur_head) { TUR_ACTION(tur_id, TR_PRECACHE); } // if tur_head exists, we can assume this turret re-spawned
+
+ e = find(world, classname, "turret_manager");
+ if(!e)
+ {
+ e = spawn();
+ e.classname = "turret_manager";
+ e.think = turrets_manager_think;
+ e.nextthink = time + 2;
+ }
+
+ if(!(self.spawnflags & TSF_SUSPENDED))
+ builtin_droptofloor();
+
+ self.cvar_basename = tur.cvar_basename;
+ load_unit_settings(self, self.cvar_basename, 0);
+
+ if(!self.team || !teamplay) { self.team = MAX_SHOT_DISTANCE; }
+ if(!self.ticrate) { self.ticrate = ((self.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); }
+ if(!self.health) { self.health = 1000; }
+ if(!self.shot_refire) { self.shot_refire = 1; }
+ if(!self.tur_shotorg) { self.tur_shotorg = '50 0 50'; }
+ if(!self.turret_flags) { self.turret_flags = TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER; }
+ if(!self.damage_flags) { self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE; }
+ if(!self.aim_flags) { self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; }
+ if(!self.track_type) { self.track_type = TFL_TRACKTYPE_STEPMOTOR; }
+ if(!self.track_flags) { self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROTATE; }
+ if(!self.ammo_flags) { self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE; }
+ if(!self.target_select_flags) { self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_ANGLELIMITS; }
+ if(!self.firecheck_flags) { self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_LOS
+ | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_REFIRE; }
+
+ if(self.track_type != TFL_TRACKTYPE_STEPMOTOR)
+ {
+ // Fluid / Ineria mode. Looks mutch nicer.
+ // Can reduce aim preformance alot, needs a bit diffrent aimspeed
+
+ self.aim_speed = bound(0.1, ((!self.aim_speed) ? 180 : self.aim_speed), 1000);
+
+ if(!self.track_accel_pitch) { self.track_accel_pitch = 0.5; }
+ if(!self.track_accel_rotate) { self.track_accel_rotate = 0.5; }
+ if(!self.track_blendrate) { self.track_blendrate = 0.35; }
+ }
+
+ self.respawntime = max(-1, ((!self.respawntime) ? 60 : self.respawntime));
+ self.shot_refire = bound(0.01, ((!self.shot_refire) ? 1 : self.shot_refire), 9999);
+ self.shot_dmg = max(1, ((!self.shot_dmg) ? self.shot_refire * 50 : self.shot_dmg));
+ self.shot_radius = max(1, ((!self.shot_radius) ? self.shot_dmg * 0.5 : self.shot_radius));
+ self.shot_speed = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
+ self.shot_spread = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
+ self.shot_force = bound(0.001, ((!self.shot_force) ? self.shot_dmg * 0.5 + self.shot_radius * 0.5 : self.shot_force), 5000);
+ self.shot_volly = bound(1, ((!self.shot_volly) ? 1 : self.shot_volly), floor(self.ammo_max / self.shot_dmg));
+ self.shot_volly_refire = bound(self.shot_refire, ((!self.shot_volly_refire) ? self.shot_refire * self.shot_volly : self.shot_volly_refire), 60);
+ self.target_range = bound(0, ((!self.target_range) ? self.shot_speed * 0.5 : self.target_range), MAX_SHOT_DISTANCE);
+ self.target_range_min = bound(0, ((!self.target_range_min) ? self.shot_radius * 2 : self.target_range_min), MAX_SHOT_DISTANCE);
+ self.target_range_optimal = bound(0, ((!self.target_range_optimal) ? self.target_range * 0.5 : self.target_range_optimal), MAX_SHOT_DISTANCE);
+ self.aim_maxrotate = bound(0, ((!self.aim_maxrotate) ? 90 : self.aim_maxrotate), 360);
+ self.aim_maxpitch = bound(0, ((!self.aim_maxpitch) ? 20 : self.aim_maxpitch), 90);
+ self.aim_speed = bound(0.1, ((!self.aim_speed) ? 36 : self.aim_speed), 1000);
+ self.aim_firetolerance_dist = bound(0.1, ((!self.aim_firetolerance_dist) ? 5 + (self.shot_radius * 2) : self.aim_firetolerance_dist), MAX_SHOT_DISTANCE);
+ self.target_select_rangebias = bound(-10, ((!self.target_select_rangebias) ? 1 : self.target_select_rangebias), 10);
+ self.target_select_samebias = bound(-10, ((!self.target_select_samebias) ? 1 : self.target_select_samebias), 10);
+ self.target_select_anglebias = bound(-10, ((!self.target_select_anglebias) ? 1 : self.target_select_anglebias), 10);
+ self.target_select_missilebias = bound(-10, ((!self.target_select_missilebias) ? 1 : self.target_select_missilebias), 10);
+ self.target_select_playerbias = bound(-10, ((!self.target_select_playerbias) ? 1 : self.target_select_playerbias), 10);
+ self.ammo_max = max(self.shot_dmg, ((!self.ammo_max) ? self.shot_dmg * 10 : self.ammo_max));
+ self.ammo_recharge = max(0, ((!self.ammo_recharge) ? self.shot_dmg * 0.5 : self.ammo_recharge));
+
+ self.turret_flags = TUR_FLAG_ISTURRET | (tur.spawnflags);
+
+ if(self.turret_flags & TUR_FLAG_SPLASH)
+ self.aim_flags |= TFL_AIM_SPLASH;
+
+ if(self.turret_flags & TUR_FLAG_MISSILE)
+ self.target_select_flags |= TFL_TARGETSELECT_MISSILES;
+
+ if(self.turret_flags & TUR_FLAG_PLAYER)
+ self.target_select_flags |= TFL_TARGETSELECT_PLAYERS;
+
+ if(self.spawnflags & TSL_NO_RESPAWN)
+ self.damage_flags |= TFL_DMG_DEATH_NORESPAWN;
+
+ if (self.turret_flags & TUR_FLAG_SUPPORT)
+ self.turret_score_target = turret_targetscore_support;
+ else
+ self.turret_score_target = turret_targetscore_generic;
+
+ ++turret_count;
+
+ setmodel(self, tur.model);
+ setsize(self, tur.mins, tur.maxs);
+
+ self.turretid = tur_id;
+ self.classname = "turret_main";
+ self.active = ACTIVE_ACTIVE;
+ self.effects = EF_NODRAW;
+ self.netname = TUR_NAME(tur_id);
+ self.ticrate = bound(sys_frametime, self.ticrate, 60);
+ self.max_health = self.health;
+ self.target_validate_flags = self.target_select_flags;
+ self.ammo = self.ammo_max;
+ self.ammo_recharge *= self.ticrate;
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.view_ofs = '0 0 0';
+ self.turret_firecheckfunc = turret_firecheck;
+ self.event_damage = turret_damage;
+ self.use = turret_use;
+ self.bot_attack = true;
+ self.nextthink = time + 1;
+ self.nextthink += turret_count * sys_frametime;
+
+ self.tur_head = spawn();
+ setmodel(self.tur_head, tur.head_model);
+ setsize(self.tur_head, '0 0 0', '0 0 0');
+ setorigin(self.tur_head, '0 0 0');
+ setattachment(self.tur_head, self, "tag_head");
+
+ self.tur_head.netname = self.tur_head.classname = "turret_head";
+ self.tur_head.team = self.team;
+ self.tur_head.owner = self;
+ self.tur_head.takedamage = DAMAGE_NO;
+ self.tur_head.solid = SOLID_NOT;
+ self.tur_head.movetype = self.movetype;
+
+ if(!self.tur_defend)
+ if(self.target != "")
+ {
+ self.tur_defend = find(world, targetname, self.target);
+ if (self.tur_defend == world)
+ {
+ self.target = "";
+ dprint("Turret has invalid defendpoint!\n");
+ }
+ }
+
+ if (self.tur_defend)
+ self.idle_aim = self.tur_head.angles + angleofs(self.tur_head, self.tur_defend);
+ else
+ self.idle_aim = '0 0 0';
+
+#ifdef TURRET_DEBUG
+ self.tur_debug_start = self.nextthink;
+ while (vlen(self.tur_debug_rvec) < 2)
+ self.tur_debug_rvec = randomvec() * 4;
+
+ self.tur_debug_rvec_x = fabs(self.tur_debug_rvec_x);
+ self.tur_debug_rvec_y = fabs(self.tur_debug_rvec_y);
+ self.tur_debug_rvec_z = fabs(self.tur_debug_rvec_z);
+#endif
+
+ turret_link();
+ turret_respawn();
+ turret_tag_fire_update();
+
+ TUR_ACTION(tur_id, TR_SETUP);
+
+ if(MUTATOR_CALLHOOK(TurretSpawn, self))
+ return false;
+
+ return true;
+}
+#endif
--- /dev/null
+#ifndef SV_TURRETS_H
+#define SV_TURRETS_H
+
+// turret fields
+.float ticrate; // interal ai think rate
+.vector aim_idle; // where to aim while idle
+.entity tur_head; // top part of the turret
+.entity tur_defend; // defend this entity
+.vector tur_shotorg; // shot origin
+.vector tur_aimpos; // aiming location
+.float tur_impacttime; // predicted projectile impact time
+.entity tur_impactent; // entity the projectile hit
+.float tur_dist_enemy; // distance to enemy
+.float tur_dist_aimpos; // distance to aim location
+.float tur_dist_impact_to_aimpos; // distance impact<->aim
+.float volly_counter; // decrement counter from .shot_volly to 0
+
+.float shot_refire; // attack refire
+.float shot_speed; // projectile speed
+.float shot_spread; // inaccuracy
+.float shot_dmg; // core damage of projectile
+.float shot_radius; // projectile damage radius
+.float shot_force; // projectile damage force
+.float shot_volly; // smaller than 1 = shoot # times at target
+.float shot_volly_refire; // refire after completed volly
+
+.float target_range;
+.float target_range_min;
+.float target_range_optimal;
+
+.float target_select_rangebias;
+.float target_select_samebias;
+.float target_select_anglebias;
+.float target_select_missilebias;
+.float target_select_playerbias;
+.float target_select_time; // last time turret had a valid target
+.float target_validate_time; // throttle re-validation of current target
+
+.float aim_firetolerance_dist;
+.float aim_speed;
+.float aim_maxpitch;
+.float aim_maxrotate;
+
+.float ammo; // current ammo
+.float ammo_recharge; // recharge rate
+.float ammo_max; // maximum ammo
+
+.vector idle_aim;
+
+/// Map time control over pain inflicted
+.float turret_scale_damage;
+/// Map time control targetting range
+.float turret_scale_range;
+/// Map time control refire
+.float turret_scale_refire;
+/// Map time control ammo held and recharged
+.float turret_scale_ammo;
+/// Map time control aim speed
+.float turret_scale_aim;
+/// Map time control health
+.float turret_scale_health;
+/// Map time control respawn time
+.float turret_scale_respawn;
+
+// tracking type
+.float track_type;
+const float TFL_TRACKTYPE_STEPMOTOR = 1; // hard angle increments, ugly for fast turning with best accuracy
+const float TFL_TRACKTYPE_FLUIDPRECISE = 2; // smooth absolute movement, looks OK with fair accuracy
+const float TFL_TRACKTYPE_FLUIDINERTIA = 3; // simulated inertia ("wobbly" mode), worst accuracy, depends on below flags
+.float track_accel_pitch;
+.float track_accel_rotate;
+.float track_blendrate;
+
+void() turret_respawn;
+
+/// updates aim org, shot org, shot dir and enemy org for selected turret
+void turret_do_updates(entity e_turret);
+.vector tur_shotdir_updated;
+
+.float() turret_firecheckfunc; // TODO: deprecate!
+
+void turrets_setframe(float _frame, float client_only);
+
+float turret_initialize(float tur_id);
+
+/// Function to use for target evaluation. usualy turret_targetscore_generic
+.float(entity _turret, entity _target) turret_score_target;
+
+.float(entity e_target,entity e_sender) turret_addtarget;
+
+.entity pathcurrent;
+
+float turret_count;
+
+// debugging
+// Uncomment below to enable various debug output.
+//#define TURRET_DEBUG
+//#define TURRET_DEBUG_TARGETVALIDATE
+//#define TURRET_DEBUG_TARGETSELECT
+#ifdef TURRET_DEBUG
+.float tur_debug_dmg_t_h; // total damage that hit something (can be more than tur_debug_dmg_t_f since it should count radius damage)
+.float tur_debug_dmg_t_f; // total damage
+.float tur_debug_start; // turret initialization time
+.float tur_debug_tmr1; // random timer
+.float tur_debug_tmr2; // random timer
+.float tur_debug_tmr3; // random timer
+.vector tur_debug_rvec; // random vector
+#endif
+
+// aiming
+vector tvt_thadv; // turret head angle diff vector, updated by a successful call to turret_validate_target
+vector tvt_tadv; // turret angle diff vector, updated by a successful call to turret_validate_target
+float tvt_thadf; // turret head angle diff float, updated by a successful call to turret_validate_target
+float tvt_tadf; // turret angle diff float, updated by a successful call to turret_validate_target
+float tvt_dist; // turret distance, updated by a successful call to turret_validate_target
+
+#endif
--- /dev/null
+void spawnfunc_turret_targettrigger();
+void turret_targettrigger_touch();
+
+void turret_targettrigger_touch()
+{
+ entity e;
+ if (self.cnt > time) return;
+ entity oldself;
+ oldself = self;
+
+ e = find(world, targetname, self.target);
+ while (e)
+ {
+ if (e.turret_flags & TUR_FLAG_RECIEVETARGETS)
+ {
+ self = e;
+ if(e.turret_addtarget)
+ e.turret_addtarget(other,oldself);
+ }
+
+ e = find(e, targetname, oldself.target);
+ }
+
+ oldself.cnt = time + 0.5;
+
+ self = oldself;
+}
+
+/*QUAKED turret_targettrigger (.5 .5 .5) ?
+*/
+void spawnfunc_turret_targettrigger()
+{
+ if(!autocvar_g_turrets) { remove(self); return; }
+
+ InitTrigger ();
+
+ self.touch = turret_targettrigger_touch;
+}
--- /dev/null
+#include "all.qh"
+
+// TURRET PLUGIN SYSTEM
+entity turret_info[TUR_MAXCOUNT];
+entity dummy_turret_info;
+
+void turrets_common_precache()
+{
+ precache_sound ("weapons/rocket_impact.wav");
+ precache_model ("models/turrets/base-gib1.md3");
+ precache_model ("models/turrets/base-gib2.md3");
+ precache_model ("models/turrets/base-gib3.md3");
+ precache_model ("models/turrets/base-gib4.md3");
+ precache_model ("models/turrets/head-gib1.md3");
+ precache_model ("models/turrets/head-gib2.md3");
+ precache_model ("models/turrets/head-gib3.md3");
+ precache_model ("models/turrets/head-gib4.md3");
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/rocket.md3");
+
+ precache_model ("models/turrets/c512.md3");
+ precache_model ("models/marker.md3");
+
+#ifdef TURRET_DEBUG
+ precache_model ("models/turrets/c512.md3");
+ precache_model ("models/pathlib/goodsquare.md3");
+ precache_model ("models/pathlib/badsquare.md3");
+ precache_model ("models/pathlib/square.md3");
+ precache_model ("models/pathlib/edge.md3");
+#endif
+}
+
+void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname)
+{
+ entity e;
+ turret_info[id - 1] = e = spawn();
+ e.classname = "turret_info";
+ e.turretid = id;
+ e.netname = shortname;
+ e.turret_name = mname;
+ e.turret_func = func;
+ e.mdl = modelname;
+ e.cvar_basename = shortname;
+ e.spawnflags = turretflags;
+ e.mins = min_s;
+ e.maxs = max_s;
+ e.model = strzone(strcat("models/turrets/", modelname));
+ e.head_model = strzone(strcat("models/turrets/", headmodelname));
+
+ #ifndef MENUQC
+ turrets_common_precache();
+ #endif
+}
+float t_null(float dummy) { return 0; }
+void register_turrets_done()
+{
+ dummy_turret_info = spawn();
+ dummy_turret_info.classname = "turret_info";
+ dummy_turret_info.turretid = 0; // you can recognize dummies by this
+ dummy_turret_info.netname = "";
+ dummy_turret_info.turret_name = "Turret";
+ dummy_turret_info.turret_func = t_null;
+ dummy_turret_info.mdl = "";
+ dummy_turret_info.mins = '-0 -0 -0';
+ dummy_turret_info.maxs = '0 0 0';
+ dummy_turret_info.model = "";
+}
+entity get_turretinfo(float id)
+{
+ entity m;
+ if(id < TUR_FIRST || id > TUR_LAST)
+ return dummy_turret_info;
+ m = turret_info[id - 1];
+ if(m)
+ return m;
+ return dummy_turret_info;
+}
--- /dev/null
+#ifndef TURRETS_H
+#define TURRETS_H
+
+// turret requests
+#define TR_SETUP 1 // (BOTH) setup turret data
+#define TR_THINK 2 // (SERVER) logic to run every frame
+#define TR_DEATH 3 // (SERVER) called when turret dies
+#define TR_PRECACHE 4 // (BOTH) precaches models/sounds used by this turret
+#define TR_ATTACK 5 // (SERVER) called when turret attacks
+#define TR_CONFIG 6 // (ALL)
+
+// functions:
+entity get_turretinfo(int id);
+
+// fields:
+.entity tur_head;
+
+// target selection flags
+.int target_select_flags;
+.int target_validate_flags;
+const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
+const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
+const int TFL_TARGETSELECT_PLAYERS = 8; // target players
+const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
+const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
+const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
+const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
+const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
+const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
+const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
+const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
+const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
+const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
+
+// aim flags
+.int aim_flags;
+const int TFL_AIM_NO = 1; // no aiming
+const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
+const int TFL_AIM_LEAD = 4; // try to predict target movement
+const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
+const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
+const int TFL_AIM_SIMPLE = 32; // aim at player's current location
+
+// tracking flags
+.int track_flags;
+const int TFL_TRACK_NO = 2; // don't move head
+const int TFL_TRACK_PITCH = 4; // pitch head
+const int TFL_TRACK_ROTATE = 8; // rotate head
+
+// prefire checks
+.int firecheck_flags;
+const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
+const int TFL_FIRECHECK_DISTANCES = 8; // another range check
+const int TFL_FIRECHECK_LOS = 16; // line of sight
+const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
+const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
+const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
+const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
+const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
+const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
+const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
+const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
+const int TFL_FIRECHECK_NO = 16384; // no prefire checks
+
+// attack flags
+.int shoot_flags;
+const int TFL_SHOOT_NO = 64; // no attacking
+const int TFL_SHOOT_VOLLY = 2; // fire in vollies
+const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
+const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
+const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
+const int TFL_SHOOT_CUSTOM = 32; // custom attacking
+
+// turret capabilities
+.int turret_flags;
+const int TUR_FLAG_NONE = 0; // no abilities
+const int TUR_FLAG_SNIPER = 2; // sniping turret
+const int TUR_FLAG_SPLASH = 4; // can deal splash damage
+const int TUR_FLAG_HITSCAN = 8; // hit scan
+const int TUR_FLAG_MULTIGUN = 16; // multiple guns
+const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
+const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
+const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
+const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
+const int TUR_FLAG_PLAYER = 512; // can damage players
+const int TUR_FLAG_MISSILE = 1024; // can damage missiles
+const int TUR_FLAG_SUPPORT = 2048; // supports other units
+const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
+const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
+const int TUR_FLAG_MOVE = 16384; // can move
+const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
+const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
+
+// ammo types
+#define ammo_flags currentammo
+const int TFL_AMMO_NONE = 64; // doesn't use ammo
+const int TFL_AMMO_ENERGY = 2; // uses power
+const int TFL_AMMO_BULLETS = 4; // uses bullets
+const int TFL_AMMO_ROCKETS = 8; // uses explosives
+const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
+const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
+
+// damage flags
+.int damage_flags;
+const int TFL_DMG_NO = 256; // doesn't take damage
+const int TFL_DMG_YES = 2; // can be damaged
+const int TFL_DMG_TEAM = 4; // can be damaged by teammates
+const int TFL_DMG_RETALIATE = 8; // target attackers
+const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
+const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
+const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
+const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
+const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
+
+// spawn flags
+const int TSF_SUSPENDED = 1;
+const int TSF_TERRAINBASE = 2; // currently unused
+const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
+const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
+const int TSL_NO_RESPAWN = 16; // don't re-spawn
+const int TSL_ROAM = 32; // roam while idle
+
+// send flags
+const int TNSF_UPDATE = 2;
+const int TNSF_STATUS = 4;
+const int TNSF_SETUP = 8;
+const int TNSF_ANG = 16;
+const int TNSF_AVEL = 32;
+const int TNSF_MOVE = 64;
+.float anim_start_time;
+const int TNSF_ANIM = 128;
+
+const int TNSF_FULL_UPDATE = 16777215;
+
+
+// entity properties of turretinfo:
+.int turretid; // TUR_...
+.string netname; // short name
+.string turret_name; // human readable name
+.float(float) turret_func; // m_...
+.string mdl; // currently a copy of the model
+.string model; // full name of model
+.string head_model; // full name of tur_head model
+.string cvar_basename; // TODO: deprecate!
+.float spawnflags;
+.vector mins, maxs; // turret hitbox size
+
+// other useful macros
+#define TUR_ACTION(turrettype,mrequest) (get_turretinfo(turrettype)).turret_func(mrequest)
+#define TUR_NAME(turrettype) (get_turretinfo(turrettype)).turret_name
+
+// =====================
+// Turret Registration
+// =====================
+
+float t_null(float dummy);
+void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname);
+void register_turrets_done();
+
+const float TUR_MAXCOUNT = 24;
+#define TUR_FIRST 1
+float TUR_COUNT;
+float TUR_LAST;
+
+#define REGISTER_TURRET_2(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
+ float id; \
+ float func(float); \
+ void RegisterTurrets_##id() \
+ { \
+ TUR_LAST = (id = TUR_FIRST + TUR_COUNT); \
+ ++TUR_COUNT; \
+ register_turret(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname); \
+ } \
+ ACCUMULATE_FUNCTION(RegisterTurrets, RegisterTurrets_##id)
+#ifdef MENUQC
+#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
+ REGISTER_TURRET_2(TUR_##id,t_null,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
+#else
+#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
+ REGISTER_TURRET_2(TUR_##id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
+#endif
+
+#define TUR_DUPECHECK(dupecheck,cvar) \
+ #ifndef dupecheck \
+ #define dupecheck \
+ float cvar; \
+ #else \
+ #error DUPLICATE TURRET CVAR: cvar \
+ #endif
+
+#define TUR_ADD_CVAR(turret,name) \
+ TUR_DUPECHECK(TUR_CVAR_##turret##_##name, autocvar_g_turrets_unit_##turret##_##name)
+
+#define TUR_CVAR(turret,name) autocvar_g_turrets_unit_##turret##_##name
+
+#include "all.qh"
+
+#undef TUR_ADD_CVAR
+#undef REGISTER_TURRET
+ACCUMULATE_FUNCTION(RegisterTurrets, register_turrets_done);
+
+#endif
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ EWHEEL,
+/* function */ t_ewheel,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
+/* mins,maxs */ '-32 -32 0', '32 32 48',
+/* model */ "ewheel-base2.md3",
+/* head_model */ "ewheel-gun1.md3",
+/* netname */ "ewheel",
+/* fullname */ _("eWheel Turret")
+);
+#else
+#ifdef SVQC
+float autocvar_g_turrets_unit_ewheel_speed_fast;
+float autocvar_g_turrets_unit_ewheel_speed_slow;
+float autocvar_g_turrets_unit_ewheel_speed_slower;
+float autocvar_g_turrets_unit_ewheel_speed_stop;
+float autocvar_g_turrets_unit_ewheel_turnrate;
+
+const float ewheel_anim_stop = 0;
+const float ewheel_anim_fwd_slow = 1;
+const float ewheel_anim_fwd_fast = 2;
+const float ewheel_anim_bck_slow = 3;
+const float ewheel_anim_bck_fast = 4;
+
+//#define EWHEEL_FANCYPATH
+void ewheel_move_path()
+{
+#ifdef EWHEEL_FANCYPATH
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+#endif
+
+ if (self.pathcurrent)
+ {
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+}
+
+void ewheel_move_enemy()
+{
+ float newframe;
+
+ self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+
+ self.moveto = self.origin + self.steerto * 128;
+
+ if (self.tur_dist_enemy > self.target_range_optimal)
+ {
+ if ( self.tur_head.spawnshieldtime < 1 )
+ {
+ newframe = ewheel_anim_fwd_fast;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+ else if (self.tur_head.spawnshieldtime < 2)
+ {
+
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
+ }
+ }
+ else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
+ {
+ newframe = ewheel_anim_bck_slow;
+ movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_stop;
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+ }
+
+ turrets_setframe(newframe, false);
+}
+
+void ewheel_move_idle()
+{
+ if(self.frame != 0)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ self.frame = 0;
+ if (vlen(self.velocity))
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+}
+
+void spawnfunc_turret_ewheel() { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
+
+float t_ewheel(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ float i;
+ entity _mis;
+
+ for (i = 0; i < 1; ++i)
+ {
+ turret_do_updates(self);
+
+ _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
+ _mis.missile_flags = MIF_SPLASH;
+
+ Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ self.tur_head.frame += 2;
+
+ if (self.tur_head.frame > 3)
+ self.tur_head.frame = 0;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ float vz;
+ vector wish_angle, real_angle;
+
+ vz = self.velocity_z;
+
+ self.angles_x = anglemods(self.angles_x);
+ self.angles_y = anglemods(self.angles_y);
+
+ fixedmakevectors(self.angles);
+
+ wish_angle = normalize(self.steerto);
+ wish_angle = vectoangles(wish_angle);
+ real_angle = wish_angle - self.angles;
+ real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
+
+ self.tur_head.spawnshieldtime = fabs(real_angle_y);
+ real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
+ self.angles_y = (self.angles_y + real_angle_y);
+
+ if(self.enemy)
+ ewheel_move_enemy();
+ else if(self.pathcurrent)
+ ewheel_move_path();
+ else
+ ewheel_move_idle();
+
+ self.velocity_z = vz;
+
+ if(vlen(self.velocity))
+ self.SendFlags |= TNSF_MOVE;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ self.velocity = '0 0 0';
+
+#ifdef EWHEEL_FANCYPATH
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return true;
+ }
+ case TR_SETUP:
+ {
+ entity e;
+
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ self.velocity = '0 0 0';
+ self.enemy = world;
+
+ setorigin(self, self.pos1);
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ {
+
+#ifdef EWHEEL_FANCYPATH
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+ }
+
+ self.iscreature = true;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = true;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.idle_aim = '0 0 0';
+ self.pos1 = self.origin;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.frame = self.tur_head.frame = 1;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+
+ // Convert from dgr / sec to dgr / tic
+ self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
+ self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/ewheel-base2.md3");
+ precache_model ("models/turrets/ewheel-gun1.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+void ewheel_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.05)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_ewheel(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = ewheel_draw;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ FLAC,
+/* function */ t_flac,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "flac.md3",
+/* netname */ "flac",
+/* fullname */ _("FLAC Cannon")
+);
+#else
+#ifdef SVQC
+void turret_flac_projectile_think_explode()
+{
+ if(self.enemy != world)
+ if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
+ setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+void spawnfunc_turret_flac() { if(!turret_initialize(TUR_FLAC)) remove(self); }
+
+float t_flac(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity proj;
+
+ turret_tag_fire_update();
+
+ proj = turret_projectile("weapons/hagar_fire.wav", 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
+ Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ proj.think = turret_flac_projectile_think_explode;
+ proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
+ proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+
+ self.tur_head.frame = self.tur_head.frame + 1;
+ if (self.tur_head.frame >= 4)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/flac.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_flac(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ FUSIONREACTOR,
+/* function */ t_fusionreactor,
+/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
+/* mins,maxs */ '-34 -34 0', '34 34 90',
+/* model */ "base.md3",
+/* head_model */ "reactor.md3",
+/* netname */ "fusionreactor",
+/* fullname */ _("Fusion Reactor")
+);
+#else
+#ifdef SVQC
+float turret_fusionreactor_firecheck()
+{
+ if (self.attack_finished_single > time)
+ return 0;
+
+ if (self.enemy.deadflag != DEAD_NO)
+ return 0;
+
+ if (self.enemy == world)
+ return 0;
+
+ if (self.ammo < self.shot_dmg)
+ return 0;
+
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return 0;
+
+ if (vlen(self.enemy.origin - self.origin) > self.target_range)
+ return 0;
+
+ if(self.team != self.enemy.team)
+ return 0;
+
+ if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
+ return 0;
+
+ return 1;
+}
+
+void spawnfunc_turret_fusionreactor() { if(!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
+
+float t_fusionreactor(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ vector fl_org;
+
+ self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
+ te_smallflash(fl_org);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+ self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
+ self.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
+ self.shoot_flags = TFL_SHOOT_HITALLVALID;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ self.tur_head.scale = 0.75;
+ self.tur_head.avelocity = '0 50 0';
+
+ self.turret_firecheckfunc = turret_fusionreactor_firecheck;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/reactor.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_fusionreactor(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ HELLION,
+/* function */ t_hellion,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hellion.md3",
+/* netname */ "hellion",
+/* fullname */ _("Hellion Missile Turret")
+);
+#else
+#ifdef SVQC
+float autocvar_g_turrets_unit_hellion_shot_speed_gain;
+float autocvar_g_turrets_unit_hellion_shot_speed_max;
+
+void turret_hellion_missile_think()
+{
+ vector olddir,newdir;
+ vector pre_pos;
+ float itime;
+
+ self.nextthink = time + 0.05;
+
+ olddir = normalize(self.velocity);
+
+ if(self.max_health < time)
+ turret_projectile_explode();
+
+ // Enemy dead? just keep on the current heading then.
+ if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
+ {
+
+ // Make sure we dont return to tracking a respawned player
+ self.enemy = world;
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
+ turret_projectile_explode();
+
+ // Accelerate
+ self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ UpdateCSQCProjectile(self);
+
+ return;
+ }
+
+ // Enemy in range?
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+ turret_projectile_explode();
+
+ // Predict enemy position
+ itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
+ pre_pos = self.enemy.origin + self.enemy.velocity * itime;
+
+ pre_pos = (pre_pos + self.enemy.origin) * 0.5;
+
+ // Find out the direction to that place
+ newdir = normalize(pre_pos - self.origin);
+
+ // Turn
+ newdir = normalize(olddir + newdir * 0.35);
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ // Accelerate
+ self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ if (itime < 0.05)
+ self.think = turret_projectile_explode;
+
+ UpdateCSQCProjectile(self);
+}
+
+void spawnfunc_turret_hellion() { if(!turret_initialize(TUR_HELLION)) remove(self); }
+
+float t_hellion(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ if(self.tur_head.frame != 0)
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
+ else
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
+
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;
+ missile.flags = FL_PROJECTILE;
+ missile.max_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+ self.tur_head.frame += 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame += 1;
+
+ if (self.tur_head.frame >= 7)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hellion.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hellion(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ HK,
+/* function */ t_hk,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hk.md3",
+/* netname */ "hk",
+/* fullname */ _("Hunter-Killer Turret")
+);
+#else
+#ifdef SVQC
+float autocvar_g_turrets_unit_hk_shot_speed;
+float autocvar_g_turrets_unit_hk_shot_speed_accel;
+float autocvar_g_turrets_unit_hk_shot_speed_accel2;
+float autocvar_g_turrets_unit_hk_shot_speed_decel;
+float autocvar_g_turrets_unit_hk_shot_speed_max;
+float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
+
+//#define TURRET_DEBUG_HK
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+float hk_is_valid_target(entity e_target)
+{
+ if (e_target == world)
+ return 0;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return 0;
+
+ // Cant touch this
+ if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
+ return 0;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
+ if (self.owner.target_select_playerbias < 0)
+ return 0;
+
+ if (e_target.deadflag != DEAD_NO)
+ return 0;
+ }
+
+ // Missile
+ if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
+ return 0;
+
+ // Team check
+ if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
+ return 0;
+
+ return 1;
+}
+
+void turret_hk_missile_think()
+{
+ vector vu, vd, vf, vl, vr, ve; // Vector (direction)
+ float fu, fd, ff, fl, fr, fe; // Fraction to solid
+ vector olddir,wishdir,newdir; // Final direction
+ float lt_for; // Length of Trace FORwrad
+ float lt_seek; // Length of Trace SEEK (left, right, up down)
+ float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+ vector pre_pos;
+ float myspeed;
+ entity e;
+ float ad,edist;
+
+ self.nextthink = time + self.ticrate;
+
+ //if (self.cnt < time)
+ // turret_hk_missile_explode();
+
+ if (self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ // Pick the closest valid target.
+ if (!self.enemy)
+ {
+ e = findradius(self.origin, 5000);
+ while (e)
+ {
+ if (hk_is_valid_target(e))
+ {
+ if (!self.enemy)
+ self.enemy = e;
+ else
+ if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
+ self.enemy = e;
+ }
+ e = e.chain;
+ }
+ }
+
+ self.angles = vectoangles(self.velocity);
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ if (self.enemy)
+ {
+ edist = vlen(self.origin - self.enemy.origin);
+ // Close enougth to do decent damage?
+ if ( edist <= (self.owner.shot_radius * 0.25) )
+ {
+ turret_projectile_explode();
+ return;
+ }
+
+ // Get data on enemy position
+ pre_pos = self.enemy.origin +
+ self.enemy.velocity *
+ min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
+
+ traceline(self.origin, pre_pos,true,self.enemy);
+ ve = normalize(pre_pos - self.origin);
+ fe = trace_fraction;
+
+ }
+ else
+ {
+ edist = 0;
+ ve = '0 0 0';
+ fe = 0;
+ }
+
+ if ((fe != 1) || (self.enemy == world) || (edist > 1000))
+ {
+ myspeed = vlen(self.velocity);
+
+ lt_for = myspeed * 3;
+ lt_seek = myspeed * 2.95;
+
+ // Trace forward
+ traceline(self.origin, self.origin + v_forward * lt_for,false,self);
+ vf = trace_endpos;
+ ff = trace_fraction;
+
+ // Find angular offset
+ ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
+
+ // To close to something, Slow down!
+ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
+ myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
+
+ // Failry clear, accelerate.
+ if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Setup trace pitch
+ pt_seek = 1 - ff;
+ pt_seek = bound(0.15,pt_seek,0.8);
+ if (ff < 0.5) pt_seek = 1;
+
+ // Trace left
+ traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
+ vl = trace_endpos;
+ fl = trace_fraction;
+
+ // Trace right
+ traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vr = trace_endpos;
+ fr = trace_fraction;
+
+ // Trace up
+ traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vu = trace_endpos;
+ fu = trace_fraction;
+
+ // Trace down
+ traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vd = trace_endpos;
+ fd = trace_fraction;
+
+ vl = normalize(vl - self.origin);
+ vr = normalize(vr - self.origin);
+ vu = normalize(vu - self.origin);
+ vd = normalize(vd - self.origin);
+
+ // Panic tresh passed, find a single direction and turn as hard as we can
+ if (pt_seek == 1)
+ {
+ wishdir = v_right;
+ if (fl > fr) wishdir = -1 * v_right;
+ if (fu > fl) wishdir = v_up;
+ if (fd > fu) wishdir = -1 * v_up;
+ }
+ else
+ {
+ // Normalize our trace vectors to make a smooth path
+ wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
+ }
+
+ if (self.enemy)
+ {
+ if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+ wishdir = (wishdir * (1 - fe)) + (ve * fe);
+ }
+ }
+ else
+ {
+ // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+ myspeed = vlen(self.velocity);
+ if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ wishdir = ve;
+ }
+
+ if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Ranoutagazfish?
+ if (self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCE;
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(self.velocity);
+ newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
+
+ // Set heading & speed
+ self.velocity = newdir * myspeed;
+
+ // Align model with new heading
+ self.angles = vectoangles(self.velocity);
+
+
+#ifdef TURRET_DEBUG_HK
+ //if(self.atime < time) {
+ if ((fe <= 0.99)||(edist > 1000))
+ {
+ te_lightning2(world,self.origin, self.origin + vr * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vl * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vu * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vd * lt_seek);
+ te_lightning2(world,self.origin, vf);
+ }
+ else
+ {
+ te_lightning2(world,self.origin, self.enemy.origin);
+ }
+ bprint("Speed: ", ftos(rint(myspeed)), "\n");
+ bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
+ bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
+ self.atime = time + 0.2;
+ //}
+#endif
+
+ UpdateCSQCProjectile(self);
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{
+ if (e_target)
+ {
+ if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+ {
+ self.enemy = e_target;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void spawnfunc_turret_hk() { if(!turret_initialize(TUR_HK)) remove(self); }
+
+float t_hk(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+
+ missile.think = turret_hk_missile_think;
+ missile.nextthink = time + 0.25;
+ missile.movetype = MOVETYPE_BOUNCEMISSILE;
+ missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
+ missile.angles = vectoangles(missile.velocity);
+ missile.cnt = time + 30;
+ missile.ticrate = max(autocvar_sys_ticrate, 0.05);
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+ self.shoot_flags = TFL_SHOOT_CLEARTARGET;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_addtarget = turret_hk_addtarget;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hk.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hk(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ MACHINEGUN,
+/* function */ t_machinegun,
+/* spawnflags */ TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "machinegun.md3",
+/* netname */ "machinegun",
+/* fullname */ _("Machinegun Turret")
+);
+#else
+#ifdef SVQC
+void spawnfunc_turret_machinegun() { if(!turret_initialize(TUR_MACHINEGUN)) remove(self); }
+
+void W_MachineGun_MuzzleFlash(void);
+
+float t_machinegun(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
+
+ W_MachineGun_MuzzleFlash();
+ setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/machinegun.md3");
+ precache_sound ("weapons/uzi_fire.wav");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_machinegun(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ MLRS,
+/* function */ t_mlrs,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "mlrs.md3",
+/* netname */ "mlrs",
+/* fullname */ _("MLRS Turret")
+);
+#else
+#ifdef SVQC
+void spawnfunc_turret_mlrs() { if(!turret_initialize(TUR_MLRS)) remove(self); }
+
+float t_mlrs(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ turret_tag_fire_update();
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
+ missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
+ missile.missile_flags = MIF_SPLASH;
+ te_explosion (missile.origin);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ // 0 = full, 6 = empty
+ self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
+ if(self.tur_head.frame < 0)
+ {
+ dprint("ammo:",ftos(self.ammo),"\n");
+ dprint("shot_dmg:",ftos(self.shot_dmg),"\n");
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
+ self.volly_counter = self.shot_volly;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/mlrs.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_mlrs(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PHASER,
+/* function */ t_phaser,
+/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "phaser.md3",
+/* netname */ "phaser",
+/* fullname */ _("Phaser Cannon")
+);
+#else
+#ifdef SVQC
+.float fireflag;
+
+float turret_phaser_firecheck()
+{
+ if (self.fireflag != 0) return 0;
+ return turret_firecheck();
+}
+
+void beam_think()
+{
+ if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
+ {
+ self.owner.attack_finished_single = time + self.owner.shot_refire;
+ self.owner.fireflag = 2;
+ self.owner.tur_head.frame = 10;
+ sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+ remove(self);
+ return;
+ }
+
+ turret_do_updates(self.owner);
+
+ if (time - self.shot_spread > 0)
+ {
+ self.shot_spread = time + 2;
+ sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
+ }
+
+
+ self.nextthink = time + self.ticrate;
+
+ self.owner.attack_finished_single = time + frametime;
+ entity oldself;
+ oldself = self;
+ self = self.owner;
+ FireImoBeam ( self.tur_shotorg,
+ self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
+ '-1 -1 -1' * self.shot_radius,
+ '1 1 1' * self.shot_radius,
+ self.shot_force,
+ oldself.shot_dmg,
+ 0.75,
+ DEATH_TURRET_PHASER);
+ self = oldself;
+ self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
+void spawnfunc_turret_phaser() { if(!turret_initialize(TUR_PHASER)) remove(self); }
+
+float t_phaser(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity beam;
+
+ beam = spawn();
+ beam.ticrate = 0.1; //autocvar_sys_ticrate;
+ setmodel(beam,"models/turrets/phaser_beam.md3");
+ beam.effects = EF_LOWPRECISION;
+ beam.solid = SOLID_NOT;
+ beam.think = beam_think;
+ beam.cnt = time + self.shot_speed;
+ beam.shot_spread = time + 2;
+ beam.nextthink = time;
+ beam.owner = self;
+ beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
+ beam.scale = self.target_range / 256;
+ beam.movetype = MOVETYPE_NONE;
+ beam.enemy = self.enemy;
+ beam.bot_dodge = true;
+ beam.bot_dodgerating = beam.shot_dmg;
+ sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
+ self.fireflag = 1;
+
+ beam.attack_finished_single = self.attack_finished_single;
+ self.attack_finished_single = time; // + autocvar_sys_ticrate;
+
+ setattachment(beam,self.tur_head,"tag_fire");
+
+ soundat (self, trace_endpos, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ {
+ if (self.fireflag == 1)
+ {
+ if (self.tur_head.frame == 10)
+ self.tur_head.frame = 1;
+ else
+ self.tur_head.frame = self.tur_head.frame +1;
+ }
+ else if (self.fireflag == 2 )
+ {
+ self.tur_head.frame = self.tur_head.frame +1;
+ if (self.tur_head.frame == 15)
+ {
+ self.tur_head.frame = 0;
+ self.fireflag = 0;
+ }
+ }
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
+
+ self.turret_firecheckfunc = turret_phaser_firecheck;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/phaser.md3");
+ precache_model ("models/turrets/phaser_beam.md3");
+ precache_sound ("turrets/phaser.wav");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_phaser(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA,
+/* function */ t_plasma,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasma.md3",
+/* netname */ "plasma",
+/* fullname */ _("Plasma Cannon")
+);
+#else
+#ifdef SVQC
+void spawnfunc_turret_plasma() { if(!turret_initialize(TUR_PLASMA)) remove(self); }
+
+float t_plasma(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_instagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+ Send_Effect("nex_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v;
+ string s;
+ v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ s = strcat("TE_TEI_G3", ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
+
+ WarpZone_TrailParticles(world, particleeffectnum(s), self.tur_shotorg, v);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+ else
+ {
+ entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+
+ Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasma.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA_DUAL,
+/* function */ t_plasma_dual,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasmad.md3",
+/* netname */ "plasma_dual",
+/* fullname */ _("Dual Plasma Cannon")
+);
+#else
+#ifdef SVQC
+void spawnfunc_turret_plasma_dual() { if(!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
+
+float t_plasma_dual(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_instagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+
+ Send_Effect("nex_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v;
+ string s;
+ v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ s = strcat("TE_TEI_G3", ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
+
+ WarpZone_TrailParticles(world, particleeffectnum(s), self.tur_shotorg, v);
+
+ self.tur_head.frame += 1;
+ }
+ else
+ {
+ entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+ Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ self.tur_head.frame += 1;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 6)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasmad.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma_dual(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ TESLA,
+/* function */ t_tesla,
+/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-60 -60 0', '60 60 128',
+/* model */ "tesla_base.md3",
+/* head_model */ "tesla_head.md3",
+/* netname */ "tesla",
+/* fullname */ _("Tesla Coil")
+);
+#else
+#ifdef SVQC
+entity toast(entity from, float range, float damage)
+{
+ entity e;
+ entity etarget = world;
+ float d,dd;
+ float r;
+
+ dd = range + 1;
+
+ e = findradius(from.origin,range);
+ while (e)
+ {
+ if ((e.railgunhit != 1) && (e != from))
+ {
+ r = turret_validate_target(self,e,self.target_validate_flags);
+ if (r > 0)
+ {
+ traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
+ if (trace_fraction == 1.0)
+ {
+ d = vlen(e.origin - from.origin);
+ if (d < dd)
+ {
+ dd = d;
+ etarget = e;
+ }
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ if (etarget)
+ {
+ te_csqc_lightningarc(from.origin,etarget.origin);
+ Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
+ etarget.railgunhit = 1;
+ }
+
+ return etarget;
+}
+
+float turret_tesla_firecheck()
+{
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ if(!turret_firecheck())
+ return 0;
+
+ if(self.enemy)
+ return 1;
+
+ return 0;
+}
+
+void spawnfunc_turret_tesla() { if(!turret_initialize(TUR_TESLA)) remove(self); }
+
+float t_tesla(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity e, t;
+ float d, r, i;
+
+ d = self.shot_dmg;
+ r = self.target_range;
+ e = spawn();
+ setorigin(e,self.tur_shotorg);
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ t = toast(e,r,d);
+ remove(e);
+
+ if (t == world) return true;
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.attack_finished_single = time + self.shot_refire;
+ for (i = 0; i < 10; ++i)
+ {
+ d *= 0.75;
+ r *= 0.85;
+ t = toast(t, r, d);
+ if (t == world) break;
+
+ }
+
+ e = findchainfloat(railgunhit, 1);
+ while (e)
+ {
+ e.railgunhit = 0;
+ e = e.chain;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if(!self.active)
+ {
+ self.tur_head.avelocity = '0 0 0';
+ return true;
+ }
+
+ if(self.ammo < self.shot_dmg)
+ {
+ self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
+ }
+ else
+ {
+ self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
+
+ if(self.attack_finished_single > time)
+ return true;
+
+ float f;
+ f = (self.ammo / self.ammo_max);
+ f = f * f;
+ if(f > random())
+ if(random() < 0.1)
+ te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_firecheckfunc = turret_tesla_firecheck;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
+ self.shoot_flags = TFL_SHOOT_CUSTOM;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/tesla_base.md3");
+ precache_model ("models/turrets/tesla_head.md3");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_tesla(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ WALKER,
+/* function */ t_walker,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
+/* mins,maxs */ '-70 -70 0', '70 70 95',
+/* model */ "walker_body.md3",
+/* head_model */ "walker_head_minigun.md3",
+/* netname */ "walker",
+/* fullname */ _("Walker Turret")
+);
+#else
+#ifdef SVQC
+float autocvar_g_turrets_unit_walker_melee_damage;
+float autocvar_g_turrets_unit_walker_melee_force;
+float autocvar_g_turrets_unit_walker_melee_range;
+float autocvar_g_turrets_unit_walker_rocket_damage;
+float autocvar_g_turrets_unit_walker_rocket_radius;
+float autocvar_g_turrets_unit_walker_rocket_force;
+float autocvar_g_turrets_unit_walker_rocket_speed;
+float autocvar_g_turrets_unit_walker_rocket_range;
+float autocvar_g_turrets_unit_walker_rocket_range_min;
+float autocvar_g_turrets_unit_walker_rocket_refire;
+float autocvar_g_turrets_unit_walker_rocket_turnrate;
+float autocvar_g_turrets_unit_walker_speed_stop;
+float autocvar_g_turrets_unit_walker_speed_walk;
+float autocvar_g_turrets_unit_walker_speed_run;
+float autocvar_g_turrets_unit_walker_speed_jump;
+float autocvar_g_turrets_unit_walker_speed_swim;
+float autocvar_g_turrets_unit_walker_speed_roam;
+float autocvar_g_turrets_unit_walker_turn;
+float autocvar_g_turrets_unit_walker_turn_walk;
+float autocvar_g_turrets_unit_walker_turn_strafe;
+float autocvar_g_turrets_unit_walker_turn_swim;
+float autocvar_g_turrets_unit_walker_turn_run;
+
+#define ANIM_NO 0
+#define ANIM_TURN 1
+#define ANIM_WALK 2
+#define ANIM_RUN 3
+#define ANIM_STRAFE_L 4
+#define ANIM_STRAFE_R 5
+#define ANIM_JUMP 6
+#define ANIM_LAND 7
+#define ANIM_PAIN 8
+#define ANIM_MELEE 9
+#define ANIM_SWIM 10
+#define ANIM_ROAM 11
+
+.float animflag;
+.float idletime;
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{
+ if (self.animflag == ANIM_MELEE)
+ return 0;
+
+ return turret_firecheck();
+}
+
+void walker_melee_do_dmg()
+{
+ vector where;
+ entity e;
+
+ makevectors(self.angles);
+ where = self.origin + v_forward * 128;
+
+ e = findradius(where,32);
+ while (e)
+ {
+ if (turret_validate_target(self, e, self.target_validate_flags))
+ if (e != self && e.owner != self)
+ Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
+
+ e = e.chain;
+ }
+}
+
+void walker_setnoanim()
+{
+ turrets_setframe(ANIM_NO, false);
+ self.animflag = self.frame;
+}
+void walker_rocket_explode()
+{
+ RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
+ remove (self);
+}
+
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+ self.health = self.health - damage;
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
+}
+
+#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
+void walker_rocket_loop();
+void walker_rocket_think()
+{
+ vector newdir;
+ float edist;
+ float itime;
+ float m_speed;
+
+ self.nextthink = time;
+
+ edist = vlen(self.enemy.origin - self.origin);
+
+ // Simulate crude guidance
+ if (self.cnt < time)
+ {
+ if (edist < 1000)
+ self.tur_shotorg = randomvec() * min(edist, 64);
+ else
+ self.tur_shotorg = randomvec() * min(edist, 256);
+
+ self.cnt = time + 0.5;
+ }
+
+ if (edist < 128)
+ self.tur_shotorg = '0 0 0';
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if (self.shot_dmg != 1337 && random() < 0.01)
+ {
+ walker_rocket_loop();
+ return;
+ }
+
+ m_speed = vlen(self.velocity);
+
+ // Enemy dead? just keep on the current heading then.
+ if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if (self.enemy)
+ {
+ itime = max(edist / m_speed, 1);
+ newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
+ }
+ else
+ newdir = normalize(self.velocity);
+
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop3()
+{
+ vector newdir;
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.think = walker_rocket_think;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+
+ self.angles = vectoangles(self.velocity);
+}
+
+void walker_rocket_loop2()
+{
+ vector newdir;
+
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.tur_shotorg = self.origin - '0 0 200';
+ self.think = walker_rocket_loop3;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop()
+{
+ self.nextthink = time;
+ self.tur_shotorg = self.origin + '0 0 300';
+ self.think = walker_rocket_loop2;
+ self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{
+ entity rocket;
+
+ fixedmakevectors(self.angles);
+
+ te_explosion (org);
+
+ rocket = spawn ();
+ setorigin(rocket, org);
+
+ sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTEN_NORM);
+ setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+ rocket.classname = "walker_rocket";
+ rocket.owner = self;
+ rocket.bot_dodge = true;
+ rocket.bot_dodgerating = 50;
+ rocket.takedamage = DAMAGE_YES;
+ rocket.damageforcescale = 2;
+ rocket.health = 25;
+ rocket.tur_shotorg = randomvec() * 512;
+ rocket.cnt = time + 1;
+ rocket.enemy = self.enemy;
+
+ if (random() < 0.01)
+ rocket.think = walker_rocket_loop;
+ else
+ rocket.think = walker_rocket_think;
+
+ rocket.event_damage = walker_rocket_damage;
+
+ rocket.nextthink = time;
+ rocket.movetype = MOVETYPE_FLY;
+ rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
+ rocket.angles = vectoangles(rocket.velocity);
+ rocket.touch = walker_rocket_explode;
+ rocket.flags = FL_PROJECTILE;
+ rocket.solid = SOLID_BBOX;
+ rocket.max_health = time + 9;
+ rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+
+ CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
+}
+
+.vector enemy_last_loc;
+.float enemy_last_time;
+void walker_move_to(vector _target, float _dist)
+{
+ switch (self.waterlevel)
+ {
+ case WATERLEVEL_NONE:
+ if (_dist > 500)
+ self.animflag = ANIM_RUN;
+ else
+ self.animflag = ANIM_WALK;
+ case WATERLEVEL_WETFEET:
+ case WATERLEVEL_SWIMMING:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case WATERLEVEL_SUBMERGED:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = _target;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ if(self.enemy)
+ {
+ self.enemy_last_loc = _target;
+ self.enemy_last_time = time;
+ }
+}
+
+//#define WALKER_FANCYPATHING
+
+void walker_move_path()
+{
+#ifdef WALKER_FANCYPATHING
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+ walker_move_to(self.moveto, 0);
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+
+ if(!self.pathcurrent)
+ return;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ walker_move_to(self.moveto, 0);
+#endif
+}
+
+void spawnfunc_turret_walker() { if(!turret_initialize(TUR_WALKER)) remove(self); }
+
+float t_walker(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTEN_NORM);
+ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
+ Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ fixedmakevectors(self.angles);
+
+ if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
+ walker_move_path();
+ else if (self.enemy == world)
+ {
+ if(self.pathcurrent)
+ walker_move_path();
+ else
+ {
+ if(self.enemy_last_time != 0)
+ {
+ if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
+ self.enemy_last_time = 0;
+ else
+ walker_move_to(self.enemy_last_loc, 0);
+ }
+ else
+ {
+ if(self.animflag != ANIM_NO)
+ {
+ traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
+
+ if(trace_fraction != 1.0)
+ self.tur_head.idletime = -1337;
+ else
+ {
+ traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
+ if(trace_fraction == 1.0)
+ self.tur_head.idletime = -1337;
+ }
+
+ if(self.tur_head.idletime == -1337)
+ {
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.idletime = 0;
+ }
+
+ self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
+ self.moveto_z = self.origin_z + 64;
+ walker_move_to(self.moveto, 0);
+ }
+
+ if(self.idletime < time)
+ {
+ if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
+ {
+ self.idletime = time + 1 + random() * 5;
+ self.moveto = self.origin;
+ self.animflag = ANIM_NO;
+ }
+ else
+ {
+ self.animflag = ANIM_WALK;
+ self.idletime = time + 4 + random() * 2;
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.moveto = self.moveto;
+ self.tur_head.idletime = 0;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
+ {
+ vector wish_angle;
+
+ wish_angle = angleofs(self, self.enemy);
+ if (self.animflag != ANIM_SWIM)
+ if (fabs(wish_angle_y) < 15)
+ {
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ self.animflag = ANIM_MELEE;
+ }
+ }
+ else if (self.tur_head.attack_finished_single < time)
+ {
+ if(self.tur_head.shot_volly)
+ {
+ self.animflag = ANIM_NO;
+
+ self.tur_head.shot_volly = self.tur_head.shot_volly -1;
+ if(self.tur_head.shot_volly == 0)
+ self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
+ else
+ self.tur_head.attack_finished_single = time + 0.2;
+
+ if(self.tur_head.shot_volly > 1)
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
+ else
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
+ }
+ else
+ {
+ if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
+ self.tur_head.shot_volly = 4;
+ }
+ }
+ else
+ {
+ if (self.animflag != ANIM_MELEE)
+ walker_move_to(self.enemy.origin, self.tur_dist_enemy);
+ }
+ }
+
+ {
+ vector real_angle;
+ float turny = 0, turnx = 0;
+ float vz;
+
+ real_angle = vectoangles(self.steerto) - self.angles;
+ vz = self.velocity_z;
+
+ switch (self.animflag)
+ {
+ case ANIM_NO:
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_TURN:
+ turny = (autocvar_g_turrets_unit_walker_turn);
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_WALK:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
+ break;
+
+ case ANIM_RUN:
+ turny = (autocvar_g_turrets_unit_walker_turn_run);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
+ break;
+
+ case ANIM_STRAFE_L:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_STRAFE_R:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_JUMP:
+ self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
+ break;
+
+ case ANIM_LAND:
+ break;
+
+ case ANIM_PAIN:
+ if(self.frame != ANIM_PAIN)
+ defer(0.25, walker_setnoanim);
+
+ break;
+
+ case ANIM_MELEE:
+ if(self.frame != ANIM_MELEE)
+ {
+ defer(0.41, walker_setnoanim);
+ defer(0.21, walker_melee_do_dmg);
+ }
+
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_SWIM:
+ turny = (autocvar_g_turrets_unit_walker_turn_swim);
+ turnx = (autocvar_g_turrets_unit_walker_turn_swim);
+
+ self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
+ vz = self.velocity_z + sin(time * 4) * 8;
+ break;
+
+ case ANIM_ROAM:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
+ break;
+ }
+
+ if(turny)
+ {
+ turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
+ self.angles_y += turny;
+ }
+
+ if(turnx)
+ {
+ turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
+ self.angles_x += turnx;
+ }
+
+ self.velocity_z = vz;
+ }
+
+
+ if(self.origin != self.oldorigin)
+ self.SendFlags |= TNSF_MOVE;
+
+ self.oldorigin = self.origin;
+ turrets_setframe(self.animflag, false);
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+#ifdef WALKER_FANCYPATHING
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ticrate = 0.05;
+
+ entity e;
+
+ // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ if(self.pos1)
+ setorigin(self, self.pos1);
+ if(self.pos2)
+ self.angles = self.pos2;
+ }
+
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
+ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.iscreature = true;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = true;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ if(self.movetype != MOVETYPE_WALK)
+ {
+ setorigin(self, self.origin);
+ tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
+ setorigin(self, trace_endpos + '0 0 4');
+ self.pos1 = self.origin;
+ self.pos2 = self.angles;
+ }
+ self.movetype = MOVETYPE_WALK;
+ self.idle_aim = '0 0 0';
+ self.turret_firecheckfunc = walker_firecheck;
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ {
+#ifdef WALKER_FANCYPATHING
+ self.pathcurrent = WALKER_PATH(self.origin, e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/walker_body.md3");
+ precache_model ("models/turrets/walker_head_minigun.md3");
+ precache_model ("models/turrets/rocket.md3");
+ precache_sound ("weapons/rocket_impact.wav");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+#include "../../../server/movelib.qh"
+
+void walker_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ movelib_groundalign4point(300, 100, 0.25, 45);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.15)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_walker(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = walker_draw;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+/*
+* Return a angle within +/- 360.
+*/
+float anglemods(float v)
+{
+ v = v - 360 * floor(v / 360);
+
+ if(v >= 180)
+ return v - 360;
+ else if(v <= -180)
+ return v + 360;
+ else
+ return v;
+}
+
+/*
+* Return the short angle
+*/
+float shortangle_f(float ang1, float ang2)
+{
+ if(ang1 > ang2)
+ {
+ if(ang1 > 180)
+ return ang1 - 360;
+ }
+ else
+ {
+ if(ang1 < -180)
+ return ang1 + 360;
+ }
+
+ return ang1;
+}
+
+vector shortangle_v(vector ang1, vector ang2)
+{
+ vector vtmp;
+
+ vtmp_x = shortangle_f(ang1_x,ang2_x);
+ vtmp_y = shortangle_f(ang1_y,ang2_y);
+ vtmp_z = shortangle_f(ang1_z,ang2_z);
+
+ return vtmp;
+}
+
+vector shortangle_vxy(vector ang1, vector ang2)
+{
+ vector vtmp = '0 0 0';
+
+ vtmp_x = shortangle_f(ang1_x,ang2_x);
+ vtmp_y = shortangle_f(ang1_y,ang2_y);
+
+ return vtmp;
+}
+
+
+/*
+* Get "real" origin, in worldspace, even if ent is attached to something else.
+*/
+vector real_origin(entity ent)
+{
+ entity e;
+ vector v = ((ent.absmin + ent.absmax) * 0.5);
+
+ e = ent.tag_entity;
+ while(e)
+ {
+ v = v + ((e.absmin + e.absmax) * 0.5);
+ e = e.tag_entity;
+ }
+
+ return v;
+}
+
+/*
+* Return the angle between two enteties
+*/
+vector angleofs(entity from, entity to)
+{
+ vector v_res;
+
+ v_res = normalize(to.origin - from.origin);
+ v_res = vectoangles(v_res);
+ v_res = v_res - from.angles;
+
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
+
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
+
+ return v_res;
+}
+
+vector angleofs3(vector from, vector from_a, entity to)
+{
+ vector v_res;
+
+ v_res = normalize(to.origin - from);
+ v_res = vectoangles(v_res);
+ v_res = v_res - from_a;
+
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
+
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
+
+ return v_res;
+}
+
+/*
+* Update self.tur_shotorg by getting up2date bone info
+* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
+*/
+float turret_tag_fire_update()
+{
+ if(!self.tur_head)
+ {
+ error("Call to turret_tag_fire_update with self.tur_head missing!\n");
+ self.tur_shotorg = '0 0 0';
+ return false;
+ }
+
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
+ v_forward = normalize(v_forward);
+
+ return true;
+}
+
+/*
+* Railgun-like beam, but has thickness and suppots slowing of target
+*/
+void FireImoBeam (vector start, vector end, vector smin, vector smax,
+ float bforce, float f_dmg, float f_velfactor, int deathtype)
+
+{
+ vector hitloc, force, endpoint, dir;
+ entity ent;
+
+ dir = normalize(end - start);
+ force = dir * bforce;
+
+ // go a little bit into the wall because we need to hit this wall later
+ end = end + dir;
+
+ // trace multiple times until we hit a wall, each obstacle will be made unsolid.
+ // note down which entities were hit so we can damage them later
+ while (1)
+ {
+ tracebox(start, smin, smax, end, false, self);
+
+ // if it is world we can't hurt it so stop now
+ if (trace_ent == world || trace_fraction == 1)
+ break;
+
+ if (trace_ent.solid == SOLID_BSP)
+ break;
+
+ // make the entity non-solid so we can hit the next one
+ trace_ent.railgunhit = true;
+ trace_ent.railgunhitloc = end;
+ trace_ent.railgunhitsolidbackup = trace_ent.solid;
+
+ // stop if this is a wall
+
+ // make the entity non-solid
+ trace_ent.solid = SOLID_NOT;
+ }
+
+ endpoint = trace_endpos;
+
+ // find all the entities the railgun hit and restore their solid state
+ ent = findfloat(world, railgunhit, true);
+ while (ent)
+ {
+ // restore their solid type
+ ent.solid = ent.railgunhitsolidbackup;
+ ent = findfloat(ent, railgunhit, true);
+ }
+
+ // find all the entities the railgun hit and hurt them
+ ent = findfloat(world, railgunhit, true);
+ while (ent)
+ {
+ // get the details we need to call the damage function
+ hitloc = ent.railgunhitloc;
+ ent.railgunhitloc = '0 0 0';
+ ent.railgunhitsolidbackup = SOLID_NOT;
+ ent.railgunhit = false;
+
+ // apply the damage
+ if (ent.takedamage)
+ {
+ Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
+ ent.velocity = ent.velocity * f_velfactor;
+ //ent.alpha = 0.25 + random() * 0.75;
+ }
+
+ // advance to the next entity
+ ent = findfloat(ent, railgunhit, true);
+ }
+ trace_endpos = endpoint;
+}
+
+#ifdef TURRET_DEBUG
+void SUB_Remove();
+void marker_think()
+{
+ if(self.cnt)
+ if(self.cnt < time)
+ {
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ return;
+ }
+
+ self.frame += 1;
+ if(self.frame > 29)
+ self.frame = 0;
+
+ self.nextthink = time;
+}
+
+void mark_error(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "error_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 0;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+void mark_info(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "info_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 1;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+entity mark_misc(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "mark_misc";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 3;
+ if(lifetime)
+ err.cnt = lifetime + time;
+ return err;
+}
+
+/*
+* Paint a v_color colord circle on target onwho
+* that fades away over f_time
+*/
+void paint_target(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ //setsize(e, '0 0 0', '0 0 0');
+ //setattachment(e,onwho,"");
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+ e.avelocity_x = -128;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target3(vector where, float f_size, vector v_color, float f_time)
+{
+ entity e;
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+ setorigin(e,where+ '0 0 1');
+ e.movetype = MOVETYPE_NONE;
+ e.velocity = '0 0 0';
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+#endif
--- /dev/null
+#ifndef TURRETS_UTIL_H
+#define TURRETS_UTIL_H
+
+vector real_origin(entity ent);
+float shortangle_f(float ang1, float ang2);
+float anglemods(float v);
+float turret_tag_fire_update();
+vector shortangle_vxy(vector ang1, vector ang2);
+vector angleofs(entity from, entity to);
+vector angleofs3(vector from, vector from_a, entity to);
+void FireImoBeam (vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float f_velfactor, float deathtype);
+
+#endif
#define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
#endif
+#define CVAR_DESCRIBE(var, desc) localcmd(sprintf("\nset %s \"%s\" \"%s\"\n", #var, ftos(autocvar_##var), desc))
+#define CVAR_DESCRIBESTR(var, desc) localcmd(sprintf("\nset %s \"%s\" \"%s\"\n", #var, autocvar_##var, desc))
+#define CVAR_DESCRIBEVEC(var, desc) localcmd(sprintf("\nset %s \"%s %s %s\" \"%s\"\n", #var, ftos(autocvar_##var##.x), ftos(autocvar_##var##.y), ftos(autocvar_##var##.z), desc))
+
#endif
--- /dev/null
+#include "unit/spiderbot.qc"
+#include "unit/raptor.qc"
+#include "unit/racer.qc"
+#ifndef VEHICLES_NO_UNSTABLE
+ #include "unit/bumblebee.qc"
+#endif
--- /dev/null
+#ifndef VEHICLES_ALL_C
+#define VEHICLES_ALL_C
+
+#include "all.qh"
+
+#if defined(SVQC)
+ #include "sv_vehicles.qc"
+#elif defined(CSQC)
+ #include "cl_vehicles.qc"
+#endif
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
+
+#ifndef MENUQC
+STATIC_INIT(vehicles_common_initialize)
+{
+#ifdef CSQC
+ precache_model("models/vehicles/bomblet.md3");
+ precache_model("models/vehicles/clusterbomb.md3");
+ precache_model("models/vehicles/clusterbomb_fragment.md3");
+ precache_model("models/vehicles/rocket01.md3");
+ precache_model("models/vehicles/rocket02.md3");
+
+ precache_sound ("vehicles/alarm.wav");
+ precache_sound ("vehicles/alarm_shield.wav");
+#endif // CSQC
+#ifdef SVQC
+ precache_sound("onslaught/ons_hit2.wav");
+ precache_sound("onslaught/electricity_explode.wav");
+
+ addstat(STAT_HUD, AS_INT, hud);
+ addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health);
+ addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield);
+ addstat(STAT_VEHICLESTAT_ENERGY, AS_INT, vehicle_energy);
+
+ addstat(STAT_VEHICLESTAT_W2MODE, AS_INT, vehicle_weapon2mode);
+
+ addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1);
+ addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
+
+ addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2);
+ addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
+#endif // SVQC
+}
+#endif
+
+entity get_vehicleinfo(int id)
+{
+ if (id < VEH_FIRST || id > VEH_LAST) return VEH_NULL;
+ entity m = vehicle_info[id];
+ return m ? m : VEH_NULL;
+}
+
+#endif
+#ifndef VEHICLES_ALL_H
+#define VEHICLES_ALL_H
+
#if defined(SVQC)
#include "sv_vehicles.qh"
#elif defined(CSQC)
#include "cl_vehicles.qh"
#endif
-# ifndef VEHICLES_NO_UNSTABLE
-# include "unit/bumblebee.qh"
-# include "unit/raptor.qh"
-# endif
+
+// vehicle requests
+const int VR_SETUP = 1; // (BOTH) setup vehicle data
+const int VR_THINK = 2; // (SERVER) logic to run every frame
+const int VR_DEATH = 3; // (SERVER) called when vehicle dies
+const int VR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this vehicle
+const int VR_ENTER = 5; // (SERVER) called when a player enters this vehicle
+const int VR_SPAWN = 6; // (SERVER) called when the vehicle re-spawns
+const int VR_IMPACT = 7; // (SERVER) called when a vehicle hits something
+const int VR_HUD = 8; // (CLIENT) logic to run every frame
+
+// vehicle spawn flags (need them here for common registrations)
+const int VHF_ISVEHICLE = 2; /// Indicates vehicle
+const int VHF_HASSHIELD = 4; /// Vehicle has shileding
+const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates
+const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates
+const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates
+const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage
+const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound
+const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound
+const int VHF_MOVE_FLY = 512; /// Vehicle is airborn
+const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50%
+const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50%
+const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50%
+const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots
+const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle
+
+// functions:
+entity get_vehicleinfo(float id);
+
+// fields:
+.entity tur_head;
+
+
+// other useful macros
+#define VEH_ACTION(vehicletype,mrequest) (get_vehicleinfo(vehicletype)).vehicle_func(mrequest)
+#define VEH_NAME(vehicletype) (get_vehicleinfo(vehicletype)).vehicle_name
+
+// =====================
+// Vehicle Registration
+// =====================
+
+void RegisterVehicles();
+const int VEH_MAXCOUNT = 24;
+entity vehicle_info[VEH_MAXCOUNT], vehicle_info_first, vehicle_info_last;
+int VEH_COUNT;
+const int VEH_FIRST = 1;
+#define VEH_LAST (VEH_FIRST + VEH_COUNT - 1)
+/** If you register a new vehicle, make sure to add it to all.inc */
+#define REGISTER_VEHICLE(id, class) REGISTER(RegisterVehicles, VEH, vehicle_info, VEH_COUNT, id, vehicleid, NEW(class))
+#include "vehicle.qh"
+#define REGISTER_VEHICLE_SIMPLE(id, vehicleflags, min_s, max_s, modelname, headmodelname, hudmodelname, headtag, hudtag, viewtag, shortname, vname) \
+ REGISTER_VEHICLE(id, Vehicle) { \
+ this.netname = shortname; \
+ this.vehicle_name = vname; \
+ this.mdl = modelname; \
+ this.spawnflags = vehicleflags; \
+ this.mins = min_s; \
+ this.maxs = max_s; \
+ this.model = modelname; \
+ this.head_model = headmodelname; \
+ this.hud_model = hudmodelname; \
+ this.tag_head = headtag; \
+ this.tag_hud = hudtag; \
+ this.tag_view = viewtag; \
+ } \
+ REGISTER_INIT(VEH, id)
+REGISTER_REGISTRY(RegisterVehicles)
+
+REGISTER_VEHICLE(NULL, Vehicle);
+
+#include "all.inc"
+
+#endif
}
// Bumblebee gunner crosshairs
- if(hud == VEH_BUMBLEBEE)
+ if(hud == VEH_BUMBLEBEE.vehicleid)
{
tmpSize = '1 1 1' * hud_fontsize;
tmpPos.x = hudPos.x + hudSize.x * (520/768);
}
// Raptor bomb crosshair
- if(hud == VEH_RAPTOR && weapon2mode != RSM_FLARE)
+ if(hud == VEH_RAPTOR.vehicleid && weapon2mode != RSM_FLARE)
{
vector where;
-#include "../effects.qh"
-#include "vehicles.qh"
#include "sv_vehicles.qh"
+#include "../effects.qh"
#if 0
bool vehicle_send(entity to, int sf)
void vehicles_think()
{
self.nextthink = time;
-
+
if(self.owner)
self.owner.vehicle_weapon2mode = self.vehicle_weapon2mode;
-
+
VEH_ACTION(self.vehicleid, VR_THINK);
CSQCMODEL_AUTOUPDATE();
CSQCMODEL_AUTOINIT();
}
-bool vehicle_initialize(int vehicle_id, bool nodrop)
+bool vehicle_initialize(entity veh, bool nodrop)
{
if(!autocvar_g_vehicles)
return false;
- entity veh = get_vehicleinfo(vehicle_id);
-
if(!veh.vehicleid)
return false;
-
- if(!veh.tur_head) { VEH_ACTION(vehicle_id, VR_PRECACHE); }
+
+ if(!veh.tur_head) { VEH_ACTION(veh.vehicleid, VR_PRECACHE); }
if(self.targetname && self.targetname != "")
{
self.iscreature = true;
self.teleportable = false; // no teleporting for vehicles, too buggy
self.damagedbycontents = true;
- self.vehicleid = vehicle_id;
+ self.vehicleid = veh.vehicleid;
self.PlayerPhysplug = veh.PlayerPhysplug;
self.event_damage = func_null;
self.touch = vehicles_touch;
self.pos2 = self.angles;
self.tur_head.team = self.team;
- VEH_ACTION(vehicle_id, VR_SETUP);
+ VEH_ACTION(veh.vehicleid, VR_SETUP);
if(self.active == ACTIVE_NOT)
self.nextthink = 0; // wait until activated
#define VEHICLES_DEF_H
#ifdef SVQC
-#include "../server/tturrets/include/turrets_early.qh"
-#include "sv_vehicles.qh"
+#include "../turrets/sv_turrets.qh"
// #define VEHICLES_USE_ODE
.float vehicle_enter_delay; // prevent players jumping to and from vehicles instantly
void vehicles_exit(float eject);
-float vehicle_initialize(float vehicle_id, float nodrop);
+float vehicle_initialize(entity vehicle, float nodrop);
bool vehicle_impulse(int imp);
bool vehicles_crushable(entity e);
#endif
-
#endif
+++ /dev/null
-#include "spiderbot.qc"
-#include "raptor.qc"
-#include "racer.qc"
-#ifndef VEHICLES_NO_UNSTABLE
- #include "bumblebee.qc"
-#endif
-#ifdef REGISTER_VEHICLE
-REGISTER_VEHICLE(
+#ifndef VEHICLE_BUMBLEBEE
+#define VEHICLE_BUMBLEBEE
+#include "bumblebee.qh"
+#ifndef MENUQC
+int v_bumblebee(int);
+#endif
+REGISTER_VEHICLE_SIMPLE(
/* VEH_##id */ BUMBLEBEE,
-/* function */ v_bumblebee,
/* spawnflags */ VHF_DMGSHAKE,
/* mins,maxs */ '-245 -130 -130', '230 130 130',
/* model */ "models/vehicles/bumblebee_body.dpm",
/* tags */ "", "", "tag_viewport",
/* netname */ "bumblebee",
/* fullname */ _("Bumblebee")
-);
-#else
+) {
+ this.m_icon = "vehicle_bumble";
+#ifndef MENUQC
+ this.vehicle_func = v_bumblebee;
+#endif
+}
+#endif
+
+#ifdef IMPLEMENTATION
const float BRG_SETUP = 2;
const float BRG_START = 4;
{
entity pilot, vehic;
vector newvel;
-
+
if(intermission_running)
{
self.vehicle.velocity = '0 0 0';
self.think = vehicles_think;
self.nextthink = time;
-
+
CSQCMODEL_AUTOUPDATE();
}
void bumblebee_exit(float eject)
{
- if(self.owner.vehicleid == VEH_BUMBLEBEE)
+ if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
{
bumblebee_gunner_exit(eject);
return;
self.think = bumblebee_land;
self.nextthink = time;
}
-
+
self.movetype = MOVETYPE_TOSS;
if(!self.owner)
{
if(autocvar_g_vehicle_bumblebee_bouncepain)
vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
-
+
return true;
}
case VR_ENTER:
{
self.angles_z *= 0.8;
self.angles_x *= 0.8;
-
+
self.nextthink = time;
-
+
if(!self.owner)
{
- entity oldself = self;
+ entity oldself = self;
if(self.gunner1)
{
self = self.gunner1;
other = oldother;
return true;
}
-
+
if(self.gunner2)
{
self = self.gunner2;
self.touch();
other = oldother;
return true;
- }
+ }
}
-
+
return true;
}
case VR_DEATH:
// Hide beam
if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
self.gun3.enemy.effects |= EF_NODRAW;
-
+
if(self.gunner1)
{
self = self.gunner1;
_body.touch = bumblebee_blowup;
else
_body.touch = func_null;
-
+
_body.think = bumblebee_diethink;
_body.nextthink = time;
_body.wait = time + 2 + (random() * 8);
_body.angles = self.angles;
Send_Effect("explosion_medium", findbetterlocation(self.origin, 16), '0 0 0', 1);
-
+
self.health = 0;
self.event_damage = func_null;
self.solid = SOLID_NOT;
setorigin(self.gun2.vehicle_viewport, '-85 0 50');
self.scale = 1.5;
-
+
// Raygun beam
if(self.gun3.enemy == world)
- {
+ {
self.gun3.enemy = spawn();
Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
- self.gun3.enemy.SendFlags = BRG_SETUP;
- self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
+ self.gun3.enemy.SendFlags = BRG_SETUP;
+ self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
}
}
self.solid = SOLID_BBOX;
self.movetype = MOVETYPE_TOSS;
self.damageforcescale = 0.025;
-
+
self.PlayerPhysplug = bumblebee_pilot_frame;
-
+
setorigin(self, self.origin + '0 0 25');
return true;
}
if(autocvar_g_vehicle_bumblebee_health_regen)
self.vehicle_flags |= VHF_HEALTHREGEN;
-
+
self.vehicle_exit = bumblebee_exit;
self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
self.max_health = self.vehicle_health;
self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
-
+
return true;
}
case VR_PRECACHE:
{
case VR_HUD:
{
- Vehicles_drawHUD("vehicle_bumble", "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
+ Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
"vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
"vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
vCROSS_HEAL);
-#ifdef REGISTER_VEHICLE
-REGISTER_VEHICLE(
+#ifndef VEHICLE_RACER
+#define VEHICLE_RACER
+#ifndef MENUQC
+int v_racer(int);
+#endif
+REGISTER_VEHICLE_SIMPLE(
/* VEH_##id */ RACER,
-/* function */ v_racer,
/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
/* mins,maxs */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5,
/* model */ "models/vehicles/wakizashi.dpm",
/* tags */ "", "", "tag_viewport",
/* netname */ "racer",
/* fullname */ _("Racer")
-);
-#else
+) {
+ this.m_icon = "vehicle_racer";
+#ifndef MENUQC
+ this.vehicle_func = v_racer;
+#endif
+}
+#endif
+
+#ifdef IMPLEMENTATION
#ifdef SVQC
#include "../../effects.qh"
#include "../../triggers/trigger/impulse.qh"
self.velocity += push_vector * _delta;
float uforce = autocvar_g_vehicle_racer_upforcedamper;
-
+
int cont = pointcontents(self.origin - '0 0 64');
if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
{
else
self.velocity_z += 200;
}
-
+
// Anti ocilation
if(self.velocity_z > 0)
self.velocity = olddir * newvel;
self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
}
-
+
int cont = pointcontents(self.origin - '0 0 32');
if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
self.velocity_z += 200;
self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
-
+
CSQCMODEL_AUTOUPDATE();
}
void racer_blowup_think()
{
self.nextthink = time;
-
+
if(time >= self.delay)
racer_blowup();
-
+
CSQCMODEL_AUTOUPDATE();
}
self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
-
+
Movetype_Physics_MatchServer(false);
}
#endif
self.move_movetype = MOVETYPE_BOUNCE;
#endif
-
+
return true;
}
self.solid = SOLID_SLIDEBOX;
self.delay = time;
self.scale = 0.5;
-
+
self.PlayerPhysplug = racer_frame;
-
+
self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
self.damageforcescale = 0.5;
#ifdef CSQC
case VR_HUD:
{
- Vehicles_drawHUD("vehicle_racer", "vehicle_racer_weapon1", "vehicle_racer_weapon2",
+ Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
"vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
"vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
vCROSS_GUIDE);
precache_model ("models/vhshield.md3");
#endif
-
+ #ifndef MENUQC
precache_model ("models/vehicles/wakizashi.dpm");
precache_model ("models/vehicles/wakizashi_cockpit.dpm");
+ #endif
return true;
}
}
-#ifdef REGISTER_VEHICLE
-REGISTER_VEHICLE(
+#ifndef VEHICLE_RAPTOR
+#define VEHICLE_RAPTOR
+#include "raptor.qh"
+#ifndef MENUQC
+int v_raptor(int);
+#endif
+REGISTER_VEHICLE_SIMPLE(
/* VEH_##id */ RAPTOR,
-/* function */ v_raptor,
/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
/* mins,maxs */ '-80 -80 0', '80 80 70',
/* model */ "models/vehicles/raptor.dpm",
/* tags */ "", "tag_hud", "tag_camera",
/* netname */ "raptor",
/* fullname */ _("Raptor")
-);
-#else
+) {
+ this.m_icon = "vehicle_raptor";
+#ifndef MENUQC
+ this.vehicle_func = v_raptor;
+#endif
+}
+#endif
+
+#ifdef IMPLEMENTATION
#ifdef SVQC
bool autocvar_g_vehicle_raptor;
}
self.nextthink = time;
-
+
CSQCMODEL_AUTOUPDATE();
}
player = self;
raptor = self.vehicle;
self = raptor;
-
+
vehicles_painframe();
/*
ftmp = vlen(self.velocity);
player = self;
raptor = self.vehicle;
self = raptor;
-
+
self.nextthink = time;
CSQCMODEL_AUTOUPDATE();
self.nextthink = 0; // will this work?
-
+
if(self.sound_nexttime < time)
{
self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
Send_Effect("explosion_small", randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
}
self.nextthink = time;
-
+
CSQCMODEL_AUTOUPDATE();
}
{
if(autocvar_g_vehicle_raptor_bouncepain)
vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
-
+
return true;
}
case VR_ENTER:
self.movetype = MOVETYPE_TOSS;
self.solid = SOLID_SLIDEBOX;
self.vehicle_energy = 1;
-
+
self.PlayerPhysplug = raptor_frame;
self.bomb1.gun1.avelocity_y = 90;
self.bomb1.gun2.avelocity_y = -90;
-
+
self.delay = time;
self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
if(autocvar_g_vehicle_raptor_energy_regen)
self.vehicle_flags |= VHF_ENERGYREGEN;
-
+
self.vehicle_exit = raptor_exit;
self.respawntime = autocvar_g_vehicle_raptor_respawntime;
self.vehicle_health = autocvar_g_vehicle_raptor_health;
self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
self.max_health = self.vehicle_health;
-
+
return true;
}
case VR_PRECACHE:
precache_sound ("vehicles/raptor_fly.wav");
precache_sound ("vehicles/raptor_speed.wav");
precache_sound ("vehicles/missile_alarm.wav");
-
+
return true;
}
}
case RSM_BOMB: crosshair = vCROSS_BURST; break;
default: crosshair = vCROSS_BURST;
}
-
- Vehicles_drawHUD("vehicle_raptor", "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
+
+ Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
"vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
"vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
crosshair);
-#ifdef REGISTER_VEHICLE
-REGISTER_VEHICLE(
+#ifndef VEHICLE_SPIDERBOT
+#define VEHICLE_SPIDERBOT
+#ifndef MENUQC
+int v_spiderbot(int);
+#endif
+REGISTER_VEHICLE_SIMPLE(
/* VEH_##id */ SPIDERBOT,
-/* function */ v_spiderbot,
/* spawnflags */ VHF_DMGSHAKE,
/* mins,maxs */ '-75 -75 10', '75 75 125',
/* model */ "models/vehicles/spiderbot.dpm",
/* tags */ "tag_head", "tag_hud", "",
/* netname */ "spiderbot",
/* fullname */ _("Spiderbot")
-);
-#else
+) {
+ this.m_icon = "vehicle_spider";
+#ifndef MENUQC
+ this.vehicle_func = v_spiderbot;
+#endif
+}
+#endif
+
+#ifdef IMPLEMENTATION
const int SBRM_FIRST = 1;
const int SBRM_VOLLY = 1;
if(self.wait != -10)
if(!self.owner.BUTTON_ATCK2)
return;
-
+
if(forbidWeaponUse(self.owner))
return;
{
if(autocvar_g_vehicle_spiderbot_bouncepain)
vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
-
+
return true;
}
case VR_ENTER:
setattachment(self.owner.flagcarried, self.tur_head, "");
setorigin(self.owner.flagcarried, '-20 0 120');
}
-
+
return true;
}
case VR_THINK:
{
if(self.flags & FL_ONGROUND)
movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
-
+
return true;
}
case VR_DEATH:
self.colormod = self.tur_head.colormod = '-1 -1 -1';
self.frame = 10;
self.movetype = MOVETYPE_TOSS;
-
+
CSQCModel_UnlinkEntity(); // networking the death scene would be a nightmare
return true;
self.damageforcescale = 0.03;
self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
-
+
self.PlayerPhysplug = spiderbot_frame;
return true;
default: crosshair = vCROSS_BURST;
}
- Vehicles_drawHUD("vehicle_spider", "vehicle_spider_weapon1", "vehicle_spider_weapon2",
+ Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
"vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
"vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
crosshair);
{
AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
-
+
return true;
}
case VR_PRECACHE:
--- /dev/null
+#ifndef VEHICLE_H
+#define VEHICLE_H
+
+int v_null(int) { return 0; }
+
+CLASS(Vehicle, Object)
+ ATTRIB(Vehicle, vehicleid, int, 0)
+ /** hud icon */
+ ATTRIB(Vehicle, m_icon, string, string_null)
+ /** short name */
+ ATTRIB(Vehicle, netname, string, "")
+ /** human readable name */
+ ATTRIB(Vehicle, vehicle_name, string, "Vehicle")
+ /** */
+ ATTRIB(Vehicle, vehicle_func, int(int), v_null)
+ /** full name of model */
+ ATTRIB(Vehicle, model, string, "")
+ /** currently a copy of the model */
+ ATTRIB(Vehicle, mdl, string, "")
+ /** full name of tur_head model */
+ ATTRIB(Vehicle, head_model, string, "")
+ /** cockpit model */
+ ATTRIB(Vehicle, hud_model, string, "")
+ /** tur_head model tag */
+ ATTRIB(Vehicle, tag_head, string, string_null)
+ /** hud model tag */
+ ATTRIB(Vehicle, tag_hud, string, string_null)
+ /** cockpit model tag */
+ ATTRIB(Vehicle, tag_view, string, string_null)
+ /** player physics mod */
+ ATTRIB(Vehicle, PlayerPhysplug, int(), func_null)
+ /** */
+ ATTRIB(Vehicle, spawnflags, int, 0)
+ /** vehicle hitbox size */
+ ATTRIB(Vehicle, mins, vector, '-0 -0 -0')
+ /** vehicle hitbox size */
+ ATTRIB(Vehicle, maxs, vector, '0 0 0')
+ENDCLASS(Vehicle)
+
+#endif
+++ /dev/null
-#include "unit/all.qh"
-
-#include "vehicles_include.qc"
-
-// VEHICLE PLUGIN SYSTEM
-entity vehicle_info[VEH_MAXCOUNT];
-entity dummy_vehicle_info;
-
-void vehicles_common_initialize()
-{
-#ifdef CSQC
- precache_model("models/vehicles/bomblet.md3");
- precache_model("models/vehicles/clusterbomb.md3");
- precache_model("models/vehicles/clusterbomb_fragment.md3");
- precache_model("models/vehicles/rocket01.md3");
- precache_model("models/vehicles/rocket02.md3");
-
- precache_sound ("vehicles/alarm.wav");
- precache_sound ("vehicles/alarm_shield.wav");
-#endif // CSQC
-#ifdef SVQC
- precache_sound("onslaught/ons_hit2.wav");
- precache_sound("onslaught/electricity_explode.wav");
-
- addstat(STAT_HUD, AS_INT, hud);
- addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health);
- addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield);
- addstat(STAT_VEHICLESTAT_ENERGY, AS_INT, vehicle_energy);
-
- addstat(STAT_VEHICLESTAT_W2MODE, AS_INT, vehicle_weapon2mode);
-
- addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1);
- addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
-
- addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2);
- addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
-#endif // SVQC
-}
-
-void register_vehicle(float id, float(float) func, float vehicleflags, vector min_s, vector max_s, string modelname, string headmodelname, string hudmodelname, string headtag, string hudtag, string viewtag, string shortname, string vname)
-{
- entity e;
- vehicle_info[id - 1] = e = spawn();
- e.classname = "vehicle_info";
- e.vehicleid = id;
- e.netname = shortname;
- e.vehicle_name = vname;
- e.vehicle_func = func;
- e.mdl = modelname;
- e.spawnflags = vehicleflags;
- e.mins = min_s;
- e.maxs = max_s;
- e.model = modelname;
- e.head_model = headmodelname;
- e.hud_model = hudmodelname;
- e.tag_head = headtag;
- e.tag_hud = hudtag;
- e.tag_view = viewtag;
-
- #ifndef MENUQC
- vehicles_common_initialize();
- #endif
-}
-float v_null(float dummy) { return 0; }
-void register_vehicles_done()
-{
- dummy_vehicle_info = spawn();
- dummy_vehicle_info.classname = "vehicle_info";
- dummy_vehicle_info.vehicleid = 0; // you can recognize dummies by this
- dummy_vehicle_info.netname = "";
- dummy_vehicle_info.vehicle_name = "Vehicle";
- dummy_vehicle_info.vehicle_func = v_null;
- dummy_vehicle_info.mdl = "";
- dummy_vehicle_info.mins = '-0 -0 -0';
- dummy_vehicle_info.maxs = '0 0 0';
- dummy_vehicle_info.model = "";
- dummy_vehicle_info.head_model = "";
- dummy_vehicle_info.hud_model = "";
-}
-entity get_vehicleinfo(float id)
-{
- entity m;
- if(id < VEH_FIRST || id > VEH_LAST)
- return dummy_vehicle_info;
- m = vehicle_info[id - 1];
- if(m)
- return m;
- return dummy_vehicle_info;
-}
+++ /dev/null
-#ifndef VEHICLES_H
-#define VEHICLES_H
-
-#include "sv_vehicles.qh"
-
-// vehicle requests
-const int VR_SETUP = 1; // (BOTH) setup vehicle data
-const int VR_THINK = 2; // (SERVER) logic to run every frame
-const int VR_DEATH = 3; // (SERVER) called when vehicle dies
-const int VR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this vehicle
-const int VR_ENTER = 5; // (SERVER) called when a player enters this vehicle
-const int VR_SPAWN = 6; // (SERVER) called when the vehicle re-spawns
-const int VR_IMPACT = 7; // (SERVER) called when a vehicle hits something
-const int VR_HUD = 8; // (CLIENT) logic to run every frame
-
-// vehicle spawn flags (need them here for common registrations)
-const int VHF_ISVEHICLE = 2; /// Indicates vehicle
-const int VHF_HASSHIELD = 4; /// Vehicle has shileding
-const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates
-const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates
-const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates
-const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage
-const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound
-const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound
-const int VHF_MOVE_FLY = 512; /// Vehicle is airborn
-const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50%
-const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50%
-const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50%
-const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots
-const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle
-
-// functions:
-entity get_vehicleinfo(float id);
-
-// fields:
-.entity tur_head;
-
-
-// entity properties of vehicleinfo:
-.int vehicleid; // VEH_...
-.string netname; // short name
-.string vehicle_name; // human readable name
-.int(int) vehicle_func; // v_...
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.string head_model; // full name of tur_head model
-.string hud_model; // cockpit model
-.string tag_head; // tur_head model tag
-.string tag_hud; // hud model tag
-.string tag_view; // cockpit model tag
-.int() PlayerPhysplug; // player physics mod
-.int spawnflags;
-.vector mins, maxs; // vehicle hitbox size
-
-// other useful macros
-#define VEH_ACTION(vehicletype,mrequest) (get_vehicleinfo(vehicletype)).vehicle_func(mrequest)
-#define VEH_NAME(vehicletype) (get_vehicleinfo(vehicletype)).vehicle_name
-
-// =====================
-// Vehicle Registration
-// =====================
-
-int v_null(int dummy);
-void register_vehicle(int id, int(int) func, float vehicleflags, vector min_s, vector max_s, string modelname, string headmodelname, string hudmodelname, string headtag, string hudtag, string viewtag, string shortname, string vname);
-void register_vehicles_done();
-
-const int VEH_MAXCOUNT = 24;
-#define VEH_FIRST 1
-int VEH_COUNT;
-int VEH_LAST;
-
-#define REGISTER_VEHICLE_2(id,func,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname) \
- int id; \
- int func(int); \
- void RegisterVehicles_##id() \
- { \
- VEH_LAST = (id = VEH_FIRST + VEH_COUNT); \
- ++VEH_COUNT; \
- register_vehicle(id,func,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname); \
- } \
- ACCUMULATE_FUNCTION(RegisterVehicles, RegisterVehicles_##id)
-#ifdef MENUQC
-#define REGISTER_VEHICLE(id,func,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname) \
- REGISTER_VEHICLE_2(VEH_##id,v_null,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname)
-#else
-#define REGISTER_VEHICLE(id,func,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname) \
- REGISTER_VEHICLE_2(VEH_##id,func,vehicleflags,min_s,max_s,modelname,headmodelname,hudmodelname,headtag,hudtag,viewtag,shortname,vname)
-#endif
-
-#include "unit/all.qh"
-
-#undef REGISTER_VEHICLE
-ACCUMULATE_FUNCTION(RegisterVehicles, register_vehicles_done);
-
-#endif
+++ /dev/null
-#ifndef VEHICLES_INCLUDE_C
-#define VEHICLES_INCLUDE_C
-
-#include "vehicles_include.qh"
-
-#ifdef CSQC
-#include "cl_vehicles.qc"
-#include "vehicles.qc"
-#endif // CSQC
-#ifdef SVQC
-#include "sv_vehicles.qc"
-#include "vehicles.qc"
-#endif // SVQC
-
-#endif
+++ /dev/null
-#ifndef VEHICLES_INCLUDE_H
-#define VEHICLES_INCLUDE_H
-
-#include "all.qh"
-
-#ifdef CSQC
-#include "vehicles.qh"
-#include "cl_vehicles.qh"
-#elif defined(SVQC)
-#include "vehicles.qh"
-#include "sv_vehicles.qh"
-#endif // SVQC
-
-#endif
position_a = view.viewloc.enemy.origin;
position_b = view.viewloc.goalentity.origin;
-#if 0
+#if 0
/*TODO: have the camera only move when a player moves too much from the center of the camera
* basically the player can move around in a "box" in the center of th screen with out changing the camera position or angles
*/
camera_angle = '0 0 0';
- // a tracking camera follows the player when it leaves the world box
+ // a tracking camera follows the player when it leaves the world box
if (cvar("cam_track")) {
camera_angle = aim_vec (camera_position, view.origin);
}
-
+
// hard snap changes the angle as soon as it crosses over the nearest 90 degree mark
if (cvar("cam_snap_hard")){
camera_angle = angle_snap_vec(aim_vec(camera_position, view.origin), 90);
}
-
+
// tries to avoid snapping unless it *really* needs to
if (cvar("cam_snap_close")){
-
+
// like hard snap, but don't snap angles yet.
camera_angle = aim_vec(camera_position, view.origin);
-
+
/* if the difference between the old and new angle is 60 degrees or more, switch angles.
* NOTE: bug/feature: this will use non-snaped angles for one frame.
* doing this resualts in less code, faster code, and a smoother transisition between angles.
else
camera_angle_y = old_camera_angle_y;
}
-
+
//unlocking this allows the camera to look up and down. this also allows a top-down view.
if (!cvar("cam_snap_unlock")) {
camera_angle_x = 0;
camera_angle_z = 0;
}
-
+
#if 0
dprint(vtos(camera_position), "\n");
dprint(vtos(old_camera_angle), "\n");
freeze_ang = getpropertyvec(VF_ANGLES);
setproperty(VF_ORIGIN, camera_position);
setproperty(VF_ANGLES, camera_angle);
-
+
forward = vectoangles(normalize(vec_to_min(position_b, position_a) - vec_to_max(position_b, position_a)));
backward = vectoangles(normalize(vec_to_max(position_b, position_a) - vec_to_min(position_b, position_a)));
-
+
if(input_movevalues_y < 0) // left
view.angles_y = backward_y;
if(input_movevalues_y > 0) // favour right
{
runstandardplayerphysics(self);
#ifdef CSQC
- self.flags =
+ self.flags =
((self.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) |
(!(self.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) |
((self.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0);
//darkplaces implementation: Blub\0
//cvar definitions:
// utf8_enable: enable utf8 encoding
-//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc.,
+//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc.,
//and count as 1 char for string functions like strlen, substring, etc.
// note: utf8_enable is run-time cvar, could be changed during execution
// note: beware that str2chr() could return value bigger than 255 once utf8 is enabled
// description: allows alternative 'static' lightstyle syntax : "=value"
// examples: "=0.5", "=2.0", "=2.75"
// could be used to control switchable lights or making styled lights with brightness > 2
-// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact
+// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact
// that other engines (which do not support this extension) could connect to a game and misunderstand this kind of lightstyle syntax
//DP_LITSPRITES
//syntax of .dpsubs files: each line in .dpsubs file defines 1 subtitle, there are three tokens:
// <start> <end> "string"
// start: subtitle start time in seconds
-// end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started,
+// end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started,
// if below 0 - show until next subtitles minus this number of seconds
// text: subtitle text, color codes (Q3-style and ^xRGB) are allowed
//example of subtitle file:
// 3 0 "Vengeance! Vengeance for my eternity of suffering!"
// 9 0 "Whelp! As if you knew what eternity was!"
// 13 0 "Grovel before your true master."
-// 17 0 "Never!"
+// 17 0 "Never!"
// 18 7 "I'll hack you from crotch to gizzard and feed what's left of you to your brides..."
//DP_SOLIDCORPSE
.vector massofs; // offsets a mass center out of object center, if not set a center of model bounds is used
.float friction; // a friction of object, get multiplied by second objects's friction on contact
.float bouncefactor;
-.float bouncestop;
+.float bouncestop;
.float jointtype; // type of joint
.float forcetype; // type of force
-.float erp; // error restitution parameter, makes ODE solver attempt to fix errors in contacts,
- // bringing together 2 joints or fixing object being stuch in other object,
+.float erp; // error restitution parameter, makes ODE solver attempt to fix errors in contacts,
+ // bringing together 2 joints or fixing object being stuch in other object,
// a value of 0.1 will fix slightly, a value of 1.0 attempts to fix whole error in one frame
// use with care as high values makes system unstable and likely to explode
//builtin definitions:
float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467;
vector drawcolorcodedstring2(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #467;
-
+
float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
#include "../oo/base.qh"
void setterDummy(entity, float);
CLASS(Animation, Object)
- METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float))
- METHOD(Animation, setTimeStartEnd, void(entity, float, float))
- METHOD(Animation, setTimeStartDuration, void(entity, float, float))
- METHOD(Animation, setValueStartEnd, void(entity, float, float))
- METHOD(Animation, setValueStartDelta, void(entity, float, float))
- METHOD(Animation, setObjectSetter, void(entity, entity, void(entity, float)))
- METHOD(Animation, tick, void(entity, float))
- METHOD(Animation, calcValue, float(entity, float, float, float, float))
- METHOD(Animation, isStopped, float(entity))
- METHOD(Animation, stopAnim, void(entity))
- METHOD(Animation, resumeAnim, void(entity))
- METHOD(Animation, isFinished, float(entity))
- METHOD(Animation, finishAnim, void(entity))
+ METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float));
+ METHOD(Animation, setTimeStartEnd, void(entity, float, float));
+ METHOD(Animation, setTimeStartDuration, void(entity, float, float));
+ METHOD(Animation, setValueStartEnd, void(entity, float, float));
+ METHOD(Animation, setValueStartDelta, void(entity, float, float));
+ METHOD(Animation, setObjectSetter, void(entity, entity, void(entity, float)));
+ METHOD(Animation, tick, void(entity, float));
+ METHOD(Animation, calcValue, float(entity, float, float, float, float));
+ METHOD(Animation, isStopped, float(entity));
+ METHOD(Animation, stopAnim, void(entity));
+ METHOD(Animation, resumeAnim, void(entity));
+ METHOD(Animation, isFinished, float(entity));
+ METHOD(Animation, finishAnim, void(entity));
ATTRIB(Animation, object, entity, NULL)
ATTRIB(Animation, setter, void(entity, float), setterDummy)
ATTRIB(Animation, value, float, 0)
#define ANIM_ANIMHOST_H
#include "../oo/base.qh"
CLASS(AnimHost, Object)
- METHOD(AnimHost, addAnim, void(entity, entity))
- METHOD(AnimHost, removeAnim, void(entity, entity))
- METHOD(AnimHost, removeAllAnim, void(entity))
- METHOD(AnimHost, removeObjAnim, void(entity, entity))
- METHOD(AnimHost, stopAllAnim, void(entity))
- METHOD(AnimHost, stopObjAnim, void(entity, entity))
- METHOD(AnimHost, resumeAllAnim, void(entity))
- METHOD(AnimHost, resumeObjAnim, void(entity, entity))
- METHOD(AnimHost, finishAllAnim, void(entity))
- METHOD(AnimHost, finishObjAnim, void(entity, entity))
- METHOD(AnimHost, tickAll, void(entity))
+ METHOD(AnimHost, addAnim, void(entity, entity));
+ METHOD(AnimHost, removeAnim, void(entity, entity));
+ METHOD(AnimHost, removeAllAnim, void(entity));
+ METHOD(AnimHost, removeObjAnim, void(entity, entity));
+ METHOD(AnimHost, stopAllAnim, void(entity));
+ METHOD(AnimHost, stopObjAnim, void(entity, entity));
+ METHOD(AnimHost, resumeAllAnim, void(entity));
+ METHOD(AnimHost, resumeObjAnim, void(entity, entity));
+ METHOD(AnimHost, finishAllAnim, void(entity));
+ METHOD(AnimHost, finishObjAnim, void(entity, entity));
+ METHOD(AnimHost, tickAll, void(entity));
ATTRIB(AnimHost, firstChild, entity, NULL)
ATTRIB(AnimHost, lastChild, entity, NULL)
ENDCLASS(AnimHost)
float easingQuadOut(float, float, float, float);
float easingQuadInOut(float, float, float, float);
CLASS(Easing, Animation)
- METHOD(Easing, calcValue, float(entity, float, float, float, float))
- METHOD(Easing, setMath, void(entity, float(float, float, float, float)))
+ METHOD(Easing, calcValue, float(entity, float, float, float, float));
+ METHOD(Easing, setMath, void(entity, float(float, float, float, float)));
ATTRIB(Easing, math, float(float, float, float, float), easingLinear)
ENDCLASS(Easing)
#endif
#define ANIM_KEYFRAME_H
#include "animation.qc"
CLASS(Keyframe, Animation)
- METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
- METHOD(Keyframe, addAnim, void(entity, entity))
- METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
+ METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)));
+ METHOD(Keyframe, addAnim, void(entity, entity));
+ METHOD(Keyframe, calcValue, float(entity, float, float, float, float));
ATTRIB(Keyframe, currentChild, entity, NULL)
ATTRIB(Keyframe, firstChild, entity, NULL)
ATTRIB(Keyframe, lastChild, entity, NULL)
#include "skin.qh"
#include "oo/base.qh"
CLASS(Item, Object)
- METHOD(Item, draw, void(entity))
- METHOD(Item, keyDown, float(entity, float, float, float))
- METHOD(Item, keyUp, float(entity, float, float, float))
- METHOD(Item, mouseMove, float(entity, vector))
- METHOD(Item, mousePress, float(entity, vector))
- METHOD(Item, mouseDrag, float(entity, vector))
- METHOD(Item, mouseRelease, float(entity, vector))
- METHOD(Item, focusEnter, void(entity))
- METHOD(Item, focusLeave, void(entity))
- METHOD(Item, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Item, relinquishFocus, void(entity))
- METHOD(Item, showNotify, void(entity))
- METHOD(Item, hideNotify, void(entity))
- METHOD(Item, toString, string(entity))
- METHOD(Item, destroy, void(entity))
+ METHOD(Item, draw, void(entity));
+ METHOD(Item, keyDown, float(entity, float, float, float));
+ METHOD(Item, keyUp, float(entity, float, float, float));
+ METHOD(Item, mouseMove, float(entity, vector));
+ METHOD(Item, mousePress, float(entity, vector));
+ METHOD(Item, mouseDrag, float(entity, vector));
+ METHOD(Item, mouseRelease, float(entity, vector));
+ METHOD(Item, focusEnter, void(entity));
+ METHOD(Item, focusLeave, void(entity));
+ METHOD(Item, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Item, relinquishFocus, void(entity));
+ METHOD(Item, showNotify, void(entity));
+ METHOD(Item, hideNotify, void(entity));
+ METHOD(Item, toString, string(entity));
+ METHOD(Item, destroy, void(entity));
ATTRIB(Item, focused, float, 0)
ATTRIB(Item, focusable, float, 0)
ATTRIB(Item, allowFocusSound, float, 0)
#define ITEM_BORDERIMAGE_H
#include "label.qc"
CLASS(BorderImage, Label)
- METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float))
- METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(BorderImage, recalcPositionWithText, void(entity, string))
+ METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float));
+ METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(BorderImage, recalcPositionWithText, void(entity, string));
ATTRIB(BorderImage, isBold, float, 1)
- METHOD(BorderImage, draw, void(entity))
+ METHOD(BorderImage, draw, void(entity));
ATTRIB(BorderImage, src, string, string_null)
ATTRIB(BorderImage, borderHeight, float, 0)
ATTRIB(BorderImage, borderVec, vector, '0 0 0')
#define ITEM_BUTTON_H
#include "label.qc"
CLASS(Button, Label)
- METHOD(Button, configureButton, void(entity, string, float, string))
- METHOD(Button, draw, void(entity))
- METHOD(Button, showNotify, void(entity))
- METHOD(Button, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Button, keyDown, float(entity, float, float, float))
- METHOD(Button, mousePress, float(entity, vector))
- METHOD(Button, mouseDrag, float(entity, vector))
- METHOD(Button, mouseRelease, float(entity, vector))
- METHOD(Button, playClickSound, void(entity))
+ METHOD(Button, configureButton, void(entity, string, float, string));
+ METHOD(Button, draw, void(entity));
+ METHOD(Button, showNotify, void(entity));
+ METHOD(Button, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Button, keyDown, float(entity, float, float, float));
+ METHOD(Button, mousePress, float(entity, vector));
+ METHOD(Button, mouseDrag, float(entity, vector));
+ METHOD(Button, mouseRelease, float(entity, vector));
+ METHOD(Button, playClickSound, void(entity));
ATTRIB(Button, onClick, void(entity, entity), func_null)
ATTRIB(Button, onClickEntity, entity, NULL)
ATTRIB(Button, src, string, string_null)
#include "button.qc"
void CheckBox_Click(entity me, entity other);
CLASS(CheckBox, Button)
- METHOD(CheckBox, configureCheckBox, void(entity, string, float, string))
- METHOD(CheckBox, draw, void(entity))
- METHOD(CheckBox, playClickSound, void(entity))
- METHOD(CheckBox, toString, string(entity))
- METHOD(CheckBox, setChecked, void(entity, float))
+ METHOD(CheckBox, configureCheckBox, void(entity, string, float, string));
+ METHOD(CheckBox, draw, void(entity));
+ METHOD(CheckBox, playClickSound, void(entity));
+ METHOD(CheckBox, toString, string(entity));
+ METHOD(CheckBox, setChecked, void(entity, float));
ATTRIB(CheckBox, useDownAsChecked, float, 0)
ATTRIB(CheckBox, checked, float, 0)
ATTRIB(CheckBox, onClick, void(entity, entity), CheckBox_Click)
#define ITEM_CONTAINER_H
#include "../item.qc"
CLASS(Container, Item)
- METHOD(Container, draw, void(entity))
- METHOD(Container, keyUp, float(entity, float, float, float))
- METHOD(Container, keyDown, float(entity, float, float, float))
- METHOD(Container, mouseMove, float(entity, vector))
- METHOD(Container, mousePress, float(entity, vector))
- METHOD(Container, mouseDrag, float(entity, vector))
- METHOD(Container, mouseRelease, float(entity, vector))
- METHOD(Container, focusLeave, void(entity))
- METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector))
- METHOD(Container, addItem, void(entity, entity, vector, vector, float))
- METHOD(Container, addItemCentered, void(entity, entity, vector, float))
- METHOD(Container, addItemRightCentered, void(entity, entity, vector, float))
- METHOD(Container, moveItemAfter, void(entity, entity, entity))
- METHOD(Container, removeItem, void(entity, entity))
- METHOD(Container, setFocus, void(entity, entity))
- METHOD(Container, saveFocus, void(entity))
- METHOD(Container, setAlphaOf, void(entity, entity, float))
- METHOD(Container, itemFromPoint, entity(entity, vector))
- METHOD(Container, showNotify, void(entity))
- METHOD(Container, hideNotify, void(entity))
- METHOD(Container, preferredFocusedGrandChild, entity(entity))
+ METHOD(Container, draw, void(entity));
+ METHOD(Container, keyUp, float(entity, float, float, float));
+ METHOD(Container, keyDown, float(entity, float, float, float));
+ METHOD(Container, mouseMove, float(entity, vector));
+ METHOD(Container, mousePress, float(entity, vector));
+ METHOD(Container, mouseDrag, float(entity, vector));
+ METHOD(Container, mouseRelease, float(entity, vector));
+ METHOD(Container, focusLeave, void(entity));
+ METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector));
+ METHOD(Container, addItem, void(entity, entity, vector, vector, float));
+ METHOD(Container, addItemCentered, void(entity, entity, vector, float));
+ METHOD(Container, addItemRightCentered, void(entity, entity, vector, float));
+ METHOD(Container, moveItemAfter, void(entity, entity, entity));
+ METHOD(Container, removeItem, void(entity, entity));
+ METHOD(Container, setFocus, void(entity, entity));
+ METHOD(Container, saveFocus, void(entity));
+ METHOD(Container, setAlphaOf, void(entity, entity, float));
+ METHOD(Container, itemFromPoint, entity(entity, vector));
+ METHOD(Container, showNotify, void(entity));
+ METHOD(Container, hideNotify, void(entity));
+ METHOD(Container, preferredFocusedGrandChild, entity(entity));
ATTRIB(Container, focusable, float, 0)
ATTRIB(Container, firstChild, entity, NULL)
ATTRIB(Container, lastChild, entity, NULL)
ATTRIB(Container, savedFocus, entity, NULL)
ATTRIB(Container, shown, float, 0)
- METHOD(Container, enterSubitem, void(entity, entity))
- METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float))
- METHOD(Container, leaveSubitem, void(entity))
+ METHOD(Container, enterSubitem, void(entity, entity));
+ METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float));
+ METHOD(Container, leaveSubitem, void(entity));
ENDCLASS(Container)
.entity nextSibling;
.entity prevSibling;
#define ITEM_DIALOG_H
#include "inputcontainer.qc"
CLASS(Dialog, InputContainer)
- METHOD(Dialog, configureDialog, void(entity)) // no runtime configuration, all parameters are given in the code!
- METHOD(Dialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
- METHOD(Dialog, keyDown, float(entity, float, float, float))
- METHOD(Dialog, close, void(entity))
- METHOD(Dialog, addItemSimple, void(entity, float, float, float, float, entity, vector))
-
- METHOD(Dialog, TD, void(entity, float, float, entity))
- METHOD(Dialog, TDNoMargin, void(entity, float, float, entity, vector))
- METHOD(Dialog, TDempty, void(entity, float))
- METHOD(Dialog, setFirstColumn, void(entity, float))
- METHOD(Dialog, TR, void(entity))
- METHOD(Dialog, gotoRC, void(entity, float, float))
+ METHOD(Dialog, configureDialog, void(entity)); // no runtime configuration, all parameters are given in the code!
+ METHOD(Dialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
+ METHOD(Dialog, keyDown, float(entity, float, float, float));
+ METHOD(Dialog, close, void(entity));
+ METHOD(Dialog, addItemSimple, void(entity, float, float, float, float, entity, vector));
+
+ METHOD(Dialog, TD, void(entity, float, float, entity));
+ METHOD(Dialog, TDNoMargin, void(entity, float, float, entity, vector));
+ METHOD(Dialog, TDempty, void(entity, float));
+ METHOD(Dialog, setFirstColumn, void(entity, float));
+ METHOD(Dialog, TR, void(entity));
+ METHOD(Dialog, gotoRC, void(entity, float, float));
ATTRIB(Dialog, isTabRoot, float, 1)
ATTRIB(Dialog, closeButton, entity, NULL)
#define ITEM_IMAGE_H
#include "../item.qc"
CLASS(Image, Item)
- METHOD(Image, configureImage, void(entity, string))
- METHOD(Image, draw, void(entity))
- METHOD(Image, toString, string(entity))
- METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Image, updateAspect, void(entity))
- METHOD(Image, initZoom, void(entity))
- METHOD(Image, setZoom, void(entity, float, float))
- METHOD(Image, drag_setStartPos, float(entity, vector))
- METHOD(Image, drag, float(entity, vector))
+ METHOD(Image, configureImage, void(entity, string));
+ METHOD(Image, draw, void(entity));
+ METHOD(Image, toString, string(entity));
+ METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Image, updateAspect, void(entity));
+ METHOD(Image, initZoom, void(entity));
+ METHOD(Image, setZoom, void(entity, float, float));
+ METHOD(Image, drag_setStartPos, float(entity, vector));
+ METHOD(Image, drag, float(entity, vector));
ATTRIB(Image, src, string, string_null)
ATTRIB(Image, color, vector, '1 1 1')
ATTRIB(Image, forcedAspect, float, 0) // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
#define ITEM_INPUTBOX_H
#include "label.qc"
CLASS(InputBox, Label)
- METHOD(InputBox, configureInputBox, void(entity, string, float, float, string))
- METHOD(InputBox, draw, void(entity))
- METHOD(InputBox, setText, void(entity, string))
- METHOD(InputBox, enterText, void(entity, string))
- METHOD(InputBox, keyDown, float(entity, float, float, float))
- METHOD(InputBox, mouseMove, float(entity, vector))
- METHOD(InputBox, mouseRelease, float(entity, vector))
- METHOD(InputBox, mousePress, float(entity, vector))
- METHOD(InputBox, mouseDrag, float(entity, vector))
- METHOD(InputBox, showNotify, void(entity))
- METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(InputBox, configureInputBox, void(entity, string, float, float, string));
+ METHOD(InputBox, draw, void(entity));
+ METHOD(InputBox, setText, void(entity, string));
+ METHOD(InputBox, enterText, void(entity, string));
+ METHOD(InputBox, keyDown, float(entity, float, float, float));
+ METHOD(InputBox, mouseMove, float(entity, vector));
+ METHOD(InputBox, mouseRelease, float(entity, vector));
+ METHOD(InputBox, mousePress, float(entity, vector));
+ METHOD(InputBox, mouseDrag, float(entity, vector));
+ METHOD(InputBox, showNotify, void(entity));
+ METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector));
ATTRIB(InputBox, src, string, string_null)
#define ITEM_INPUTCONTAINER_H
#include "container.qc"
CLASS(InputContainer, Container)
- METHOD(InputContainer, keyDown, float(entity, float, float, float))
- METHOD(InputContainer, mouseMove, float(entity, vector))
- METHOD(InputContainer, mousePress, float(entity, vector))
- METHOD(InputContainer, mouseRelease, float(entity, vector))
- METHOD(InputContainer, mouseDrag, float(entity, vector))
- METHOD(InputContainer, focusLeave, void(entity))
- METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(InputContainer, keyDown, float(entity, float, float, float));
+ METHOD(InputContainer, mouseMove, float(entity, vector));
+ METHOD(InputContainer, mousePress, float(entity, vector));
+ METHOD(InputContainer, mouseRelease, float(entity, vector));
+ METHOD(InputContainer, mouseDrag, float(entity, vector));
+ METHOD(InputContainer, focusLeave, void(entity));
+ METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector));
- METHOD(InputContainer, _changeFocusXY, float(entity, vector))
+ METHOD(InputContainer, _changeFocusXY, float(entity, vector));
ATTRIB(InputContainer, mouseFocusedChild, entity, NULL)
ATTRIB(InputContainer, isTabRoot, float, 0)
ENDCLASS(InputContainer)
#define ITEM_LABEL_H
#include "../item.qc"
CLASS(Label, Item)
- METHOD(Label, configureLabel, void(entity, string, float, float))
- METHOD(Label, draw, void(entity))
- METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Label, setText, void(entity, string))
- METHOD(Label, toString, string(entity))
- METHOD(Label, recalcPositionWithText, void(entity, string))
+ METHOD(Label, configureLabel, void(entity, string, float, float));
+ METHOD(Label, draw, void(entity));
+ METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Label, setText, void(entity, string));
+ METHOD(Label, toString, string(entity));
+ METHOD(Label, recalcPositionWithText, void(entity, string));
ATTRIB(Label, isBold, float, 0)
ATTRIB(Label, text, string, string_null)
ATTRIB(Label, currentText, string, string_null)
#define ITEM_LISTBOX_H
#include "../item.qc"
CLASS(ListBox, Item)
- METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(ListBox, configureListBox, void(entity, float, float))
- METHOD(ListBox, draw, void(entity))
- METHOD(ListBox, keyDown, float(entity, float, float, float))
- METHOD(ListBox, mouseMove, float(entity, vector))
- METHOD(ListBox, mousePress, float(entity, vector))
- METHOD(ListBox, mouseDrag, float(entity, vector))
- METHOD(ListBox, mouseRelease, float(entity, vector))
- METHOD(ListBox, focusLeave, void(entity))
+ METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(ListBox, configureListBox, void(entity, float, float));
+ METHOD(ListBox, draw, void(entity));
+ METHOD(ListBox, keyDown, float(entity, float, float, float));
+ METHOD(ListBox, mouseMove, float(entity, vector));
+ METHOD(ListBox, mousePress, float(entity, vector));
+ METHOD(ListBox, mouseDrag, float(entity, vector));
+ METHOD(ListBox, mouseRelease, float(entity, vector));
+ METHOD(ListBox, focusLeave, void(entity));
ATTRIB(ListBox, focusable, float, 1)
ATTRIB(ListBox, focusedItem, int, -1)
ATTRIB(ListBox, focusedItemAlpha, float, 0.3)
ATTRIB(ListBox, scrollPos, float, 0) // measured in window heights, fixed when needed
ATTRIB(ListBox, scrollPosTarget, float, 0)
ATTRIB(ListBox, needScrollToItem, float, -1)
- METHOD(ListBox, scrollToItem, void(entity, int))
+ METHOD(ListBox, scrollToItem, void(entity, int));
ATTRIB(ListBox, previousValue, float, 0)
ATTRIB(ListBox, pressed, float, 0) // 0 = normal, 1 = scrollbar dragging, 2 = item dragging, 3 = released
ATTRIB(ListBox, pressOffset, float, 0)
- METHOD(ListBox, updateControlTopBottom, void(entity))
+ METHOD(ListBox, updateControlTopBottom, void(entity));
ATTRIB(ListBox, controlTop, float, 0)
ATTRIB(ListBox, controlBottom, float, 0)
ATTRIB(ListBox, controlWidth, float, 0)
ATTRIB(ListBox, lastClickedItem, float, -1)
ATTRIB(ListBox, lastClickedTime, float, 0)
- METHOD(ListBox, drawListBoxItem, void(entity, int, vector, bool, bool)) // item number, width/height, isSelected, isFocused
- METHOD(ListBox, clickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
- METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
- METHOD(ListBox, setSelected, void(entity, float))
+ METHOD(ListBox, drawListBoxItem, void(entity, int, vector, bool, bool)); // item number, width/height, isSelected, isFocused
+ METHOD(ListBox, clickListBoxItem, void(entity, float, vector)); // item number, relative clickpos
+ METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)); // item number, relative clickpos
+ METHOD(ListBox, setSelected, void(entity, float));
- METHOD(ListBox, getLastFullyVisibleItemAtScrollPos, float(entity, float))
- METHOD(ListBox, getFirstFullyVisibleItemAtScrollPos, float(entity, float))
+ METHOD(ListBox, getLastFullyVisibleItemAtScrollPos, float(entity, float));
+ METHOD(ListBox, getFirstFullyVisibleItemAtScrollPos, float(entity, float));
// NOTE: override these four methods if you want variable sized list items
- METHOD(ListBox, getTotalHeight, float(entity))
- METHOD(ListBox, getItemAtPos, float(entity, float))
- METHOD(ListBox, getItemStart, float(entity, float))
- METHOD(ListBox, getItemHeight, float(entity, float))
+ METHOD(ListBox, getTotalHeight, float(entity));
+ METHOD(ListBox, getItemAtPos, float(entity, float));
+ METHOD(ListBox, getItemStart, float(entity, float));
+ METHOD(ListBox, getItemHeight, float(entity, float));
// NOTE: if getItemAt* are overridden, it may make sense to cache the
// start and height of the last item returned by getItemAtPos and fast
// track returning their properties for getItemStart and getItemHeight.
#define ITEM_MODALCONTROLLER_H
#include "container.qc"
CLASS(ModalController, Container)
- METHOD(ModalController, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(ModalController, draw, void(entity))
- METHOD(ModalController, showChild, void(entity, entity, vector, vector, float))
- METHOD(ModalController, hideChild, void(entity, entity, float))
- METHOD(ModalController, hideAll, void(entity, float))
- METHOD(ModalController, addItem, void(entity, entity, vector, vector, float))
- METHOD(ModalController, addTab, void(entity, entity, entity))
+ METHOD(ModalController, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(ModalController, draw, void(entity));
+ METHOD(ModalController, showChild, void(entity, entity, vector, vector, float));
+ METHOD(ModalController, hideChild, void(entity, entity, float));
+ METHOD(ModalController, hideAll, void(entity, float));
+ METHOD(ModalController, addItem, void(entity, entity, vector, vector, float));
+ METHOD(ModalController, addTab, void(entity, entity, entity));
- METHOD(ModalController, initializeDialog, void(entity, entity))
+ METHOD(ModalController, initializeDialog, void(entity, entity));
- METHOD(ModalController, switchState, void(entity, entity, float, float))
+ METHOD(ModalController, switchState, void(entity, entity, float, float));
ATTRIB(ModalController, origin, vector, '0 0 0')
ATTRIB(ModalController, size, vector, '0 0 0')
ATTRIB(ModalController, previousButton, entity, NULL)
#define ITEM_NEXPOSEE_H
#include "container.qc"
CLASS(Nexposee, Container)
- METHOD(Nexposee, draw, void(entity))
- METHOD(Nexposee, keyDown, float(entity, float, float, float))
- METHOD(Nexposee, keyUp, float(entity, float, float, float))
- METHOD(Nexposee, mousePress, float(entity, vector))
- METHOD(Nexposee, mouseMove, float(entity, vector))
- METHOD(Nexposee, mouseRelease, float(entity, vector))
- METHOD(Nexposee, mouseDrag, float(entity, vector))
- METHOD(Nexposee, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Nexposee, focusEnter, void(entity))
- METHOD(Nexposee, close, void(entity))
+ METHOD(Nexposee, draw, void(entity));
+ METHOD(Nexposee, keyDown, float(entity, float, float, float));
+ METHOD(Nexposee, keyUp, float(entity, float, float, float));
+ METHOD(Nexposee, mousePress, float(entity, vector));
+ METHOD(Nexposee, mouseMove, float(entity, vector));
+ METHOD(Nexposee, mouseRelease, float(entity, vector));
+ METHOD(Nexposee, mouseDrag, float(entity, vector));
+ METHOD(Nexposee, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Nexposee, focusEnter, void(entity));
+ METHOD(Nexposee, close, void(entity));
ATTRIB(Nexposee, animationState, float, -1)
ATTRIB(Nexposee, animationFactor, float, 0)
ATTRIB(Nexposee, selectedChild, entity, NULL)
ATTRIB(Nexposee, mouseFocusedChild, entity, NULL)
- METHOD(Nexposee, addItem, void(entity, entity, vector, vector, float))
- METHOD(Nexposee, calc, void(entity))
- METHOD(Nexposee, setNexposee, void(entity, entity, vector, float, float))
+ METHOD(Nexposee, addItem, void(entity, entity, vector, vector, float));
+ METHOD(Nexposee, calc, void(entity));
+ METHOD(Nexposee, setNexposee, void(entity, entity, vector, float, float));
ATTRIB(Nexposee, mousePosition, vector, '0 0 0')
- METHOD(Nexposee, pullNexposee, void(entity, entity, vector))
+ METHOD(Nexposee, pullNexposee, void(entity, entity, vector));
ENDCLASS(Nexposee)
void ExposeeCloseButton_Click(entity button, entity other); // un-exposees the current state
#include "checkbox.qc"
void RadioButton_Click(entity me, entity other);
CLASS(RadioButton, CheckBox)
- METHOD(RadioButton, configureRadioButton, void(entity, string, float, string, float, float))
+ METHOD(RadioButton, configureRadioButton, void(entity, string, float, string, float, float));
ATTRIB(RadioButton, checked, float, 0)
ATTRIB(RadioButton, group, float, 0)
ATTRIB(RadioButton, allowDeselect, float, 0)
#define ITEM_SLIDER_H
#include "label.qc"
CLASS(Slider, Label)
- METHOD(Slider, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(Slider, configureSliderVisuals, void(entity, float, float, float, string))
- METHOD(Slider, configureSliderValues, void(entity, float, float, float, float, float, float))
- METHOD(Slider, draw, void(entity))
- METHOD(Slider, keyDown, float(entity, float, float, float))
- METHOD(Slider, keyUp, float(entity, float, float, float))
- METHOD(Slider, mousePress, float(entity, vector))
- METHOD(Slider, mouseDrag, float(entity, vector))
- METHOD(Slider, mouseRelease, float(entity, vector))
- METHOD(Slider, valueToText, string(entity, float))
- METHOD(Slider, toString, string(entity))
- METHOD(Slider, setValue, void(entity, float))
- METHOD(Slider, setSliderValue, void(entity, float))
- METHOD(Slider, showNotify, void(entity))
+ METHOD(Slider, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(Slider, configureSliderVisuals, void(entity, float, float, float, string));
+ METHOD(Slider, configureSliderValues, void(entity, float, float, float, float, float, float));
+ METHOD(Slider, draw, void(entity));
+ METHOD(Slider, keyDown, float(entity, float, float, float));
+ METHOD(Slider, keyUp, float(entity, float, float, float));
+ METHOD(Slider, mousePress, float(entity, vector));
+ METHOD(Slider, mouseDrag, float(entity, vector));
+ METHOD(Slider, mouseRelease, float(entity, vector));
+ METHOD(Slider, valueToText, string(entity, float));
+ METHOD(Slider, toString, string(entity));
+ METHOD(Slider, setValue, void(entity, float));
+ METHOD(Slider, setSliderValue, void(entity, float));
+ METHOD(Slider, showNotify, void(entity));
ATTRIB(Slider, src, string, string_null)
ATTRIB(Slider, focusable, float, 1)
ATTRIB(Slider, allowFocusSound, float, 1)
#define ITEM_TEXTSLIDER_H
#include "slider.qc"
CLASS(TextSlider, Slider)
- METHOD(TextSlider, valueToText, string(entity, float))
- METHOD(TextSlider, valueToIdentifier, string(entity, float))
- METHOD(TextSlider, setValueFromIdentifier, void(entity, string))
- METHOD(TextSlider, getIdentifier, string(entity))
- METHOD(TextSlider, clearValues, void(entity))
- METHOD(TextSlider, addValue, void(entity, string, string))
- METHOD(TextSlider, insertValue, void(entity, float, string, string))
- METHOD(TextSlider, configureTextSliderValues, void(entity, string))
+ METHOD(TextSlider, valueToText, string(entity, float));
+ METHOD(TextSlider, valueToIdentifier, string(entity, float));
+ METHOD(TextSlider, setValueFromIdentifier, void(entity, string));
+ METHOD(TextSlider, getIdentifier, string(entity));
+ METHOD(TextSlider, clearValues, void(entity));
+ METHOD(TextSlider, addValue, void(entity, string, string));
+ METHOD(TextSlider, insertValue, void(entity, float, string, string));
+ METHOD(TextSlider, configureTextSliderValues, void(entity, string));
ATTRIBARRAY(TextSlider, valueStrings, string, 256)
ATTRIBARRAY(TextSlider, valueIdentifiers, string, 256)
ATTRIB(TextSlider, nValues, int, 0)
../common/util.qc
../common/items/all.qc
-
../common/monsters/all.qc
-
-../common/weapons/all.qc // TODO
+../common/vehicles/all.qc
+../common/weapons/all.qc
../warpzonelib/mathlib.qc
#define BIGBUTTON_H
#include "button.qc"
CLASS(XonoticBigButton, XonoticButton)
- METHOD(XonoticBigButton, configureXonoticBigButton, void(entity, string, vector))
+ METHOD(XonoticBigButton, configureXonoticBigButton, void(entity, string, vector));
ATTRIB(XonoticBigButton, image, string, SKINGFX_BUTTON_BIG)
ATTRIB(XonoticBigButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY)
ENDCLASS(XonoticBigButton)
#define BIGCOMMANDBUTTON_H
#include "commandbutton.qc"
CLASS(XonoticBigCommandButton, XonoticCommandButton)
- METHOD(XonoticBigCommandButton, configureXonoticBigCommandButton, void(entity, string, vector, string, float))
+ METHOD(XonoticBigCommandButton, configureXonoticBigCommandButton, void(entity, string, vector, string, float));
ATTRIB(XonoticBigCommandButton, image, string, SKINGFX_BUTTON_BIG)
ATTRIB(XonoticBigCommandButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY)
ENDCLASS(XonoticBigCommandButton)
#define BUTTON_H
#include "../item/button.qc"
CLASS(XonoticButton, Button)
- METHOD(XonoticButton, configureXonoticButton, void(entity, string, vector))
+ METHOD(XonoticButton, configureXonoticButton, void(entity, string, vector));
ATTRIB(XonoticButton, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticButton, image, string, SKINGFX_BUTTON)
ATTRIB(XonoticButton, grayImage, string, SKINGFX_BUTTON_GRAY)
#define CAMPAIGN_H
#include "listbox.qc"
CLASS(XonoticCampaignList, XonoticListBox)
- METHOD(XonoticCampaignList, configureXonoticCampaignList, void(entity))
+ METHOD(XonoticCampaignList, configureXonoticCampaignList, void(entity));
ATTRIB(XonoticCampaignList, rowsPerItem, float, 10)
- METHOD(XonoticCampaignList, draw, void(entity))
- METHOD(XonoticCampaignList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticCampaignList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticCampaignList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticCampaignList, setSelected, void(entity, float))
- METHOD(XonoticCampaignList, keyDown, float(entity, float, float, float))
- METHOD(XonoticCampaignList, campaignGo, void(entity, float))
- METHOD(XonoticCampaignList, destroy, void(entity))
+ METHOD(XonoticCampaignList, draw, void(entity));
+ METHOD(XonoticCampaignList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticCampaignList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticCampaignList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticCampaignList, setSelected, void(entity, float));
+ METHOD(XonoticCampaignList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticCampaignList, campaignGo, void(entity, float));
+ METHOD(XonoticCampaignList, destroy, void(entity));
ATTRIB(XonoticCampaignList, campaignGlob, float, 0)
ATTRIB(XonoticCampaignList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticCampaignList, campaignIndex, float, 0)
ATTRIB(XonoticCampaignList, cvarName, string, string_null)
- METHOD(XonoticCampaignList, loadCvars, void(entity))
- METHOD(XonoticCampaignList, saveCvars, void(entity))
+ METHOD(XonoticCampaignList, loadCvars, void(entity));
+ METHOD(XonoticCampaignList, saveCvars, void(entity));
ATTRIB(XonoticCampaignList, buttonNext, entity, NULL)
ATTRIB(XonoticCampaignList, buttonPrev, entity, NULL)
#define CHARMAP_H
#include "picker.qc"
CLASS(XonoticCharmap, XonoticPicker)
- METHOD(XonoticCharmap, configureXonoticCharmap, void(entity, entity))
- METHOD(XonoticCharmap, focusLeave, void(entity))
- METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticCharmap, keyDown, float(entity, float, float, float))
+ METHOD(XonoticCharmap, configureXonoticCharmap, void(entity, entity));
+ METHOD(XonoticCharmap, focusLeave, void(entity));
+ METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticCharmap, keyDown, float(entity, float, float, float));
ATTRIB(XonoticCharmap, inputBox, entity, NULL)
ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0')
ATTRIB(XonoticCharmap, rows, float, 10)
ATTRIB(XonoticCharmap, columns, float, 14)
- METHOD(XonoticCharmap, cellSelect, void(entity, vector))
- METHOD(XonoticCharmap, cellIsValid, bool(entity, vector))
- METHOD(XonoticCharmap, cellDraw, void(entity, vector, vector))
- METHOD(XonoticCharmap, charOffset, vector)
+ METHOD(XonoticCharmap, cellSelect, void(entity, vector));
+ METHOD(XonoticCharmap, cellIsValid, bool(entity, vector));
+ METHOD(XonoticCharmap, cellDraw, void(entity, vector, vector));
+ ATTRIB(XonoticCharmap, charOffset, vector, '0 0 0')
ENDCLASS(XonoticCharmap)
entity makeXonoticCharmap(entity controlledInputBox);
#endif
#define CHECKBOX_H
#include "../item/checkbox.qc"
CLASS(XonoticCheckBox, CheckBox)
- METHOD(XonoticCheckBox, configureXonoticCheckBox, void(entity, float, float, string, string))
- METHOD(XonoticCheckBox, setChecked, void(entity, float))
+ METHOD(XonoticCheckBox, configureXonoticCheckBox, void(entity, float, float, string, string));
+ METHOD(XonoticCheckBox, setChecked, void(entity, float));
ATTRIB(XonoticCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticCheckBox, image, string, SKINGFX_CHECKBOX)
ATTRIB(XonoticCheckBox, yesValue, float, 1)
ATTRIB(XonoticCheckBox, colorD, vector, SKINCOLOR_CHECKBOX_D)
ATTRIB(XonoticCheckBox, cvarName, string, string_null)
- METHOD(XonoticCheckBox, loadCvars, void(entity))
- METHOD(XonoticCheckBox, saveCvars, void(entity))
+ METHOD(XonoticCheckBox, loadCvars, void(entity));
+ METHOD(XonoticCheckBox, saveCvars, void(entity));
ATTRIB(XonoticCheckBox, sendCvars, float, 0)
ATTRIB(XonoticCheckBox, alpha, float, SKINALPHA_TEXT)
#define CHECKBOX_SLIDER_INVALID_H
#include "../item/checkbox.qc"
CLASS(XonoticSliderCheckBox, CheckBox)
- METHOD(XonoticSliderCheckBox, configureXonoticSliderCheckBox, void(entity, float, float, entity, string))
- METHOD(XonoticSliderCheckBox, setChecked, void(entity, float))
- METHOD(XonoticSliderCheckBox, draw, void(entity))
+ METHOD(XonoticSliderCheckBox, configureXonoticSliderCheckBox, void(entity, float, float, entity, string));
+ METHOD(XonoticSliderCheckBox, setChecked, void(entity, float));
+ METHOD(XonoticSliderCheckBox, draw, void(entity));
ATTRIB(XonoticSliderCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticSliderCheckBox, image, string, SKINGFX_CHECKBOX)
#define CHECKBOX_STRING_H
#include "../item/checkbox.qc"
CLASS(XonoticCheckBoxString, CheckBox)
- METHOD(XonoticCheckBoxString, configureXonoticCheckBoxString, void(entity, string, string, string, string))
- METHOD(XonoticCheckBoxString, setChecked, void(entity, float))
+ METHOD(XonoticCheckBoxString, configureXonoticCheckBoxString, void(entity, string, string, string, string));
+ METHOD(XonoticCheckBoxString, setChecked, void(entity, float));
ATTRIB(XonoticCheckBoxString, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticCheckBoxString, image, string, SKINGFX_CHECKBOX)
ATTRIB(XonoticCheckBoxString, yesString, string, string_null)
ATTRIB(XonoticCheckBoxString, colorD, vector, SKINCOLOR_CHECKBOX_D)
ATTRIB(XonoticCheckBoxString, cvarName, string, string_null)
- METHOD(XonoticCheckBoxString, loadCvars, void(entity))
- METHOD(XonoticCheckBoxString, saveCvars, void(entity))
+ METHOD(XonoticCheckBoxString, loadCvars, void(entity));
+ METHOD(XonoticCheckBoxString, saveCvars, void(entity));
ATTRIB(XonoticCheckBoxString, sendCvars, float, 0)
ATTRIB(XonoticCheckBoxString, alpha, float, SKINALPHA_TEXT)
#define COLORBUTTON_H
#include "../item/radiobutton.qc"
CLASS(XonoticColorButton, RadioButton)
- METHOD(XonoticColorButton, configureXonoticColorButton, void(entity, float, float, float))
- METHOD(XonoticColorButton, setChecked, void(entity, float))
- METHOD(XonoticColorButton, draw, void(entity))
+ METHOD(XonoticColorButton, configureXonoticColorButton, void(entity, float, float, float));
+ METHOD(XonoticColorButton, setChecked, void(entity, float));
+ METHOD(XonoticColorButton, draw, void(entity));
ATTRIB(XonoticColorButton, fontSize, float, 0)
ATTRIB(XonoticColorButton, image, string, SKINGFX_COLORBUTTON)
ATTRIB(XonoticColorButton, cvarPart, float, 0)
ATTRIB(XonoticColorButton, cvarName, string, string_null)
ATTRIB(XonoticColorButton, cvarValueFloat, float, 0)
- METHOD(XonoticColorButton, loadCvars, void(entity))
- METHOD(XonoticColorButton, saveCvars, void(entity))
+ METHOD(XonoticColorButton, loadCvars, void(entity));
+ METHOD(XonoticColorButton, saveCvars, void(entity));
ENDCLASS(XonoticColorButton)
entity makeXonoticColorButton(float, float, float);
#endif
#define COLORPICKER_H
#include "../item/image.qc"
CLASS(XonoticColorpicker, Image)
- METHOD(XonoticColorpicker, configureXonoticColorpicker, void(entity, entity))
- METHOD(XonoticColorpicker, mousePress, float(entity, vector))
- METHOD(XonoticColorpicker, mouseRelease, float(entity, vector))
- METHOD(XonoticColorpicker, mouseDrag, float(entity, vector))
+ METHOD(XonoticColorpicker, configureXonoticColorpicker, void(entity, entity));
+ METHOD(XonoticColorpicker, mousePress, float(entity, vector));
+ METHOD(XonoticColorpicker, mouseRelease, float(entity, vector));
+ METHOD(XonoticColorpicker, mouseDrag, float(entity, vector));
ATTRIB(XonoticColorpicker, controlledTextbox, entity, NULL)
ATTRIB(XonoticColorpicker, image, string, SKINGFX_COLORPICKER)
ATTRIB(XonoticColorpicker, imagemargin, vector, SKINMARGIN_COLORPICKER)
ATTRIB(XonoticColorpicker, focusable, float, 1)
- METHOD(XonoticColorpicker, focusLeave, void(entity))
- METHOD(XonoticColorpicker, keyDown, float(entity, float, float, float))
- METHOD(XonoticColorpicker, draw, void(entity))
+ METHOD(XonoticColorpicker, focusLeave, void(entity));
+ METHOD(XonoticColorpicker, keyDown, float(entity, float, float, float));
+ METHOD(XonoticColorpicker, draw, void(entity));
ENDCLASS(XonoticColorpicker)
entity makeXonoticColorpicker(entity theTextbox);
#endif
#define COLORPICKER_STRING_H
#include "../item/image.qc"
CLASS(XonoticColorpickerString, Image)
- METHOD(XonoticColorpickerString, configureXonoticColorpickerString, void(entity, string, string))
- METHOD(XonoticColorpickerString, mousePress, float(entity, vector))
- METHOD(XonoticColorpickerString, mouseRelease, float(entity, vector))
- METHOD(XonoticColorpickerString, mouseDrag, float(entity, vector))
+ METHOD(XonoticColorpickerString, configureXonoticColorpickerString, void(entity, string, string));
+ METHOD(XonoticColorpickerString, mousePress, float(entity, vector));
+ METHOD(XonoticColorpickerString, mouseRelease, float(entity, vector));
+ METHOD(XonoticColorpickerString, mouseDrag, float(entity, vector));
ATTRIB(XonoticColorpickerString, cvarName, string, string_null)
- METHOD(XonoticColorpickerString, loadCvars, void(entity))
- METHOD(XonoticColorpickerString, saveCvars, void(entity))
+ METHOD(XonoticColorpickerString, loadCvars, void(entity));
+ METHOD(XonoticColorpickerString, saveCvars, void(entity));
ATTRIB(XonoticColorpickerString, prevcoords, vector, '0 0 0')
ATTRIB(XonoticColorpickerString, image, string, SKINGFX_COLORPICKER)
ATTRIB(XonoticColorpickerString, imagemargin, vector, SKINMARGIN_COLORPICKER)
ATTRIB(XonoticColorpickerString, focusable, float, 1)
- METHOD(XonoticColorpickerString, draw, void(entity))
+ METHOD(XonoticColorpickerString, draw, void(entity));
ATTRIB(XonoticColorpickerString, disabledAlpha, float, 0.3)
ENDCLASS(XonoticColorpickerString)
entity makeXonoticColorpickerString(string theCvar, string theDefaultCvar);
#define COMMANDBUTTON_H
#include "button.qc"
CLASS(XonoticCommandButton, XonoticButton)
- METHOD(XonoticCommandButton, configureXonoticCommandButton, void(entity, string, vector, string, float))
+ METHOD(XonoticCommandButton, configureXonoticCommandButton, void(entity, string, vector, string, float));
ATTRIB(XonoticCommandButton, onClickCommand, string, string_null)
ATTRIB(XonoticCommandButton, flags, float, 0)
ENDCLASS(XonoticCommandButton)
#define CREDITS_H
#include "listbox.qc"
CLASS(XonoticCreditsList, XonoticListBox)
- METHOD(XonoticCreditsList, configureXonoticCreditsList, void(entity))
+ METHOD(XonoticCreditsList, configureXonoticCreditsList, void(entity));
ATTRIB(XonoticCreditsList, rowsPerItem, float, 1)
- METHOD(XonoticCreditsList, draw, void(entity))
- METHOD(XonoticCreditsList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticCreditsList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticCreditsList, keyDown, float(entity, float, float, float))
- METHOD(XonoticCreditsList, destroy, void(entity))
+ METHOD(XonoticCreditsList, draw, void(entity));
+ METHOD(XonoticCreditsList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticCreditsList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticCreditsList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticCreditsList, destroy, void(entity));
ATTRIB(XonoticCreditsList, selectionDoesntMatter, bool, true)
ATTRIB(XonoticCreditsList, realFontSize, vector, '0 0 0')
#define CROSSHAIRPICKER_H
#include "picker.qc"
CLASS(XonoticCrosshairPicker, XonoticPicker)
- METHOD(XonoticCrosshairPicker, configureXonoticCrosshairPicker, void(entity))
+ METHOD(XonoticCrosshairPicker, configureXonoticCrosshairPicker, void(entity));
ATTRIB(XonoticCrosshairPicker, rows, float, 3)
ATTRIB(XonoticCrosshairPicker, columns, float, 12)
- METHOD(XonoticCrosshairPicker, cellSelect, void(entity, vector))
- METHOD(XonoticCrosshairPicker, cellIsValid, bool(entity, vector))
- METHOD(XonoticCrosshairPicker, cellDraw, void(entity, vector, vector))
+ METHOD(XonoticCrosshairPicker, cellSelect, void(entity, vector));
+ METHOD(XonoticCrosshairPicker, cellIsValid, bool(entity, vector));
+ METHOD(XonoticCrosshairPicker, cellDraw, void(entity, vector, vector));
ENDCLASS(XonoticCrosshairPicker)
entity makeXonoticCrosshairPicker();
#endif
#define CROSSHAIRPREVIEW_H
#include "../item.qc"
CLASS(XonoticCrosshairPreview, Item)
- METHOD(XonoticCrosshairPreview, configureXonoticCrosshairPreview, void(entity))
- METHOD(XonoticCrosshairPreview, draw, void(entity))
+ METHOD(XonoticCrosshairPreview, configureXonoticCrosshairPreview, void(entity));
+ METHOD(XonoticCrosshairPreview, draw, void(entity));
ATTRIB(XonoticCrosshairPreview, src, string, string_null)
ATTRIB(XonoticCrosshairPreview, src2, string, string_null)
ATTRIB(XonoticCrosshairPreview, disabled, float, 0)
#define CVARLIST_H
#include "listbox.qc"
CLASS(XonoticCvarList, XonoticListBox)
- METHOD(XonoticCvarList, configureXonoticCvarList, void(entity))
+ METHOD(XonoticCvarList, configureXonoticCvarList, void(entity));
ATTRIB(XonoticCvarList, rowsPerItem, float, 1)
- METHOD(XonoticCvarList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticCvarList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticCvarList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticCvarList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticCvarList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticCvarList, keyDown, float(entity, float, float, float));
- METHOD(XonoticCvarList, destroy, void(entity))
+ METHOD(XonoticCvarList, destroy, void(entity));
ATTRIB(XonoticCvarList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticCvarList, realUpperMargin, float, 0)
ATTRIB(XonoticCvarList, columnValueOrigin, float, 0)
ATTRIB(XonoticCvarList, columnValueSize, float, 0)
- METHOD(XonoticCvarList, mouseRelease, float(entity, vector))
- METHOD(XonoticCvarList, setSelected, void(entity, float))
- METHOD(XonoticCvarList, updateCvarType, float(entity))
+ METHOD(XonoticCvarList, mouseRelease, float(entity, vector));
+ METHOD(XonoticCvarList, setSelected, void(entity, float));
+ METHOD(XonoticCvarList, updateCvarType, float(entity));
ATTRIB(XonoticCvarList, controlledTextbox, entity, NULL)
ATTRIB(XonoticCvarList, cvarNameBox, entity, NULL)
#define DEMOLIST_H
#include "listbox.qc"
CLASS(XonoticDemoList, XonoticListBox)
- METHOD(XonoticDemoList, configureXonoticDemoList, void(entity))
+ METHOD(XonoticDemoList, configureXonoticDemoList, void(entity));
ATTRIB(XonoticDemoList, rowsPerItem, float, 1)
- METHOD(XonoticDemoList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticDemoList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticDemoList, getDemos, void(entity))
- METHOD(XonoticDemoList, startDemo, void(entity))
- METHOD(XonoticDemoList, timeDemo, void(entity))
- METHOD(XonoticDemoList, demoName, string(entity, float))
- METHOD(XonoticDemoList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticDemoList, keyDown, float(entity, float, float, float))
- METHOD(XonoticDemoList, destroy, void(entity))
- METHOD(XonoticDemoList, showNotify, void(entity))
+ METHOD(XonoticDemoList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticDemoList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticDemoList, getDemos, void(entity));
+ METHOD(XonoticDemoList, startDemo, void(entity));
+ METHOD(XonoticDemoList, timeDemo, void(entity));
+ METHOD(XonoticDemoList, demoName, string(entity, float));
+ METHOD(XonoticDemoList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticDemoList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticDemoList, destroy, void(entity));
+ METHOD(XonoticDemoList, showNotify, void(entity));
ATTRIB(XonoticDemoList, listDemo, float, -1)
ATTRIB(XonoticDemoList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticDialog, alpha, float, SKINALPHA_TEXT)
- METHOD(XonoticDialog, configureDialog, void(entity))
+ METHOD(XonoticDialog, configureDialog, void(entity));
ENDCLASS(XonoticDialog)
#ifndef IMPLEMENTATION
entity currentDialog;
#define DIALOG_CREDITS_H
#include "dialog.qc"
CLASS(XonoticCreditsDialog, XonoticDialog)
- METHOD(XonoticCreditsDialog, fill, void(entity))
- METHOD(XonoticCreditsDialog, focusEnter, void(entity))
+ METHOD(XonoticCreditsDialog, fill, void(entity));
+ METHOD(XonoticCreditsDialog, focusEnter, void(entity));
ATTRIB(XonoticCreditsDialog, title, string, _("Credits"))
ATTRIB(XonoticCreditsDialog, color, vector, SKINCOLOR_DIALOG_CREDITS)
ATTRIB(XonoticCreditsDialog, intendedWidth, float, SKINWIDTH_CREDITS)
#define DIALOG_FIRSTRUN_H
#include "rootdialog.qc"
CLASS(XonoticFirstRunDialog, XonoticRootDialog)
- METHOD(XonoticFirstRunDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
+ METHOD(XonoticFirstRunDialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"))
ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN)
ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.7)
#define DIALOG_HUDPANEL_AMMO_H
#include "rootdialog.qc"
CLASS(XonoticHUDAmmoDialog, XonoticRootDialog)
- METHOD(XonoticHUDAmmoDialog, fill, void(entity))
+ METHOD(XonoticHUDAmmoDialog, fill, void(entity));
ATTRIB(XonoticHUDAmmoDialog, title, string, _("Ammo Panel"))
ATTRIB(XonoticHUDAmmoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDAmmoDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_CENTERPRINT_H
#include "rootdialog.qc"
CLASS(XonoticHUDCenterprintDialog, XonoticRootDialog)
- METHOD(XonoticHUDCenterprintDialog, fill, void(entity))
+ METHOD(XonoticHUDCenterprintDialog, fill, void(entity));
ATTRIB(XonoticHUDCenterprintDialog, title, string, _("Centerprint Panel"))
ATTRIB(XonoticHUDCenterprintDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDCenterprintDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_CHAT_H
#include "rootdialog.qc"
CLASS(XonoticHUDChatDialog, XonoticRootDialog)
- METHOD(XonoticHUDChatDialog, fill, void(entity))
+ METHOD(XonoticHUDChatDialog, fill, void(entity));
ATTRIB(XonoticHUDChatDialog, title, string, _("Chat Panel"))
ATTRIB(XonoticHUDChatDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDChatDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_ENGINEINFO_H
#include "rootdialog.qc"
CLASS(XonoticHUDEngineInfoDialog, XonoticRootDialog)
- METHOD(XonoticHUDEngineInfoDialog, fill, void(entity))
+ METHOD(XonoticHUDEngineInfoDialog, fill, void(entity));
ATTRIB(XonoticHUDEngineInfoDialog, title, string, _("Engine Info Panel"))
ATTRIB(XonoticHUDEngineInfoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDEngineInfoDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_HEALTHARMOR_H
#include "rootdialog.qc"
CLASS(XonoticHUDHealthArmorDialog, XonoticRootDialog)
- METHOD(XonoticHUDHealthArmorDialog, fill, void(entity))
+ METHOD(XonoticHUDHealthArmorDialog, fill, void(entity));
ATTRIB(XonoticHUDHealthArmorDialog, title, string, _("Health/Armor Panel"))
ATTRIB(XonoticHUDHealthArmorDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDHealthArmorDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_INFOMESSAGES_H
#include "rootdialog.qc"
CLASS(XonoticHUDInfoMessagesDialog, XonoticRootDialog)
- METHOD(XonoticHUDInfoMessagesDialog, fill, void(entity))
+ METHOD(XonoticHUDInfoMessagesDialog, fill, void(entity));
ATTRIB(XonoticHUDInfoMessagesDialog, title, string, _("Info Messages Panel"))
ATTRIB(XonoticHUDInfoMessagesDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDInfoMessagesDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_ITEMSTIME_H
#include "rootdialog.qc"
CLASS(XonoticHUDItemsTimeDialog, XonoticRootDialog)
- METHOD(XonoticHUDItemsTimeDialog, fill, void(entity))
+ METHOD(XonoticHUDItemsTimeDialog, fill, void(entity));
ATTRIB(XonoticHUDItemsTimeDialog, title, string, _("Items Time Panel"))
ATTRIB(XonoticHUDItemsTimeDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDItemsTimeDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_MODICONS_H
#include "rootdialog.qc"
CLASS(XonoticHUDModIconsDialog, XonoticRootDialog)
- METHOD(XonoticHUDModIconsDialog, fill, void(entity))
+ METHOD(XonoticHUDModIconsDialog, fill, void(entity));
ATTRIB(XonoticHUDModIconsDialog, title, string, _("Mod Icons Panel"))
ATTRIB(XonoticHUDModIconsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDModIconsDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_NOTIFICATION_H
#include "rootdialog.qc"
CLASS(XonoticHUDNotificationDialog, XonoticRootDialog)
- METHOD(XonoticHUDNotificationDialog, fill, void(entity))
+ METHOD(XonoticHUDNotificationDialog, fill, void(entity));
ATTRIB(XonoticHUDNotificationDialog, title, string, _("Notification Panel"))
ATTRIB(XonoticHUDNotificationDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDNotificationDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_PHYSICS_H
#include "rootdialog.qc"
CLASS(XonoticHUDPhysicsDialog, XonoticRootDialog)
- METHOD(XonoticHUDPhysicsDialog, fill, void(entity))
+ METHOD(XonoticHUDPhysicsDialog, fill, void(entity));
ATTRIB(XonoticHUDPhysicsDialog, title, string, _("Physics Panel"))
ATTRIB(XonoticHUDPhysicsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDPhysicsDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_POWERUPS_H
#include "rootdialog.qc"
CLASS(XonoticHUDPowerupsDialog, XonoticRootDialog)
- METHOD(XonoticHUDPowerupsDialog, fill, void(entity))
+ METHOD(XonoticHUDPowerupsDialog, fill, void(entity));
ATTRIB(XonoticHUDPowerupsDialog, title, string, _("Powerups Panel"))
ATTRIB(XonoticHUDPowerupsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDPowerupsDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_PRESSEDKEYS_H
#include "rootdialog.qc"
CLASS(XonoticHUDPressedKeysDialog, XonoticRootDialog)
- METHOD(XonoticHUDPressedKeysDialog, fill, void(entity))
+ METHOD(XonoticHUDPressedKeysDialog, fill, void(entity));
ATTRIB(XonoticHUDPressedKeysDialog, title, string, _("Pressed Keys Panel"))
ATTRIB(XonoticHUDPressedKeysDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDPressedKeysDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_RACETIMER_H
#include "rootdialog.qc"
CLASS(XonoticHUDRaceTimerDialog, XonoticRootDialog)
- METHOD(XonoticHUDRaceTimerDialog, fill, void(entity))
+ METHOD(XonoticHUDRaceTimerDialog, fill, void(entity));
ATTRIB(XonoticHUDRaceTimerDialog, title, string, _("Race Timer Panel"))
ATTRIB(XonoticHUDRaceTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDRaceTimerDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_RADAR_H
#include "rootdialog.qc"
CLASS(XonoticHUDRadarDialog, XonoticRootDialog)
- METHOD(XonoticHUDRadarDialog, fill, void(entity))
+ METHOD(XonoticHUDRadarDialog, fill, void(entity));
ATTRIB(XonoticHUDRadarDialog, title, string, _("Radar Panel"))
ATTRIB(XonoticHUDRadarDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDRadarDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_SCORE_H
#include "rootdialog.qc"
CLASS(XonoticHUDScoreDialog, XonoticRootDialog)
- METHOD(XonoticHUDScoreDialog, fill, void(entity))
+ METHOD(XonoticHUDScoreDialog, fill, void(entity));
ATTRIB(XonoticHUDScoreDialog, title, string, _("Score Panel"))
ATTRIB(XonoticHUDScoreDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDScoreDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_TIMER_H
#include "rootdialog.qc"
CLASS(XonoticHUDTimerDialog, XonoticRootDialog)
- METHOD(XonoticHUDTimerDialog, fill, void(entity))
+ METHOD(XonoticHUDTimerDialog, fill, void(entity));
ATTRIB(XonoticHUDTimerDialog, title, string, _("Timer Panel"))
ATTRIB(XonoticHUDTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDTimerDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_VOTE_H
#include "rootdialog.qc"
CLASS(XonoticHUDVoteDialog, XonoticRootDialog)
- METHOD(XonoticHUDVoteDialog, fill, void(entity))
+ METHOD(XonoticHUDVoteDialog, fill, void(entity));
ATTRIB(XonoticHUDVoteDialog, title, string, _("Vote Panel"))
ATTRIB(XonoticHUDVoteDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDVoteDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDPANEL_WEAPONS_H
#include "rootdialog.qc"
CLASS(XonoticHUDWeaponsDialog, XonoticRootDialog)
- METHOD(XonoticHUDWeaponsDialog, fill, void(entity))
+ METHOD(XonoticHUDWeaponsDialog, fill, void(entity));
ATTRIB(XonoticHUDWeaponsDialog, title, string, _("Weapons Panel"))
ATTRIB(XonoticHUDWeaponsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDWeaponsDialog, intendedWidth, float, 0.4)
#define DIALOG_HUDSETUP_EXIT_H
#include "rootdialog.qc"
CLASS(XonoticHUDExitDialog, XonoticRootDialog)
- METHOD(XonoticHUDExitDialog, fill, void(entity))
+ METHOD(XonoticHUDExitDialog, fill, void(entity));
ATTRIB(XonoticHUDExitDialog, title, string, _("Panel HUD Setup"))
ATTRIB(XonoticHUDExitDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticHUDExitDialog, intendedWidth, float, 0.4)
#define DIALOG_MONSTERTOOLS_H
#include "rootdialog.qc"
CLASS(XonoticMonsterToolsDialog, XonoticRootDialog)
- METHOD(XonoticMonsterToolsDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
+ METHOD(XonoticMonsterToolsDialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
ATTRIB(XonoticMonsterToolsDialog, title, string, _("Monster Tools"))
ATTRIB(XonoticMonsterToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
ATTRIB(XonoticMonsterToolsDialog, intendedWidth, float, 0.8)
#define DIALOG_MULTIPLAYER_H
#include "dialog.qc"
CLASS(XonoticMultiplayerDialog, XonoticDialog)
- METHOD(XonoticMultiplayerDialog, fill, void(entity))
+ METHOD(XonoticMultiplayerDialog, fill, void(entity));
ATTRIB(XonoticMultiplayerDialog, title, string, _("Multiplayer"))
ATTRIB(XonoticMultiplayerDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER)
ATTRIB(XonoticMultiplayerDialog, intendedWidth, float, 0.96)
#define DIALOG_MULTIPLAYER_CREATE_H
#include "tab.qc"
CLASS(XonoticServerCreateTab, XonoticTab)
- METHOD(XonoticServerCreateTab, fill, void(entity))
- METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity))
- METHOD(XonoticServerCreateTab, gameTypeSelectNotify, void(entity))
+ METHOD(XonoticServerCreateTab, fill, void(entity));
+ METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity));
+ METHOD(XonoticServerCreateTab, gameTypeSelectNotify, void(entity));
ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9)
ATTRIB(XonoticServerCreateTab, rows, float, 23)
ATTRIB(XonoticServerCreateTab, columns, float, 6.2) // added extra .2 for center space
#define DIALOG_MULTIPLAYER_CREATE_MAPINFO_H
#include "dialog.qc"
CLASS(XonoticMapInfoDialog, XonoticDialog)
- METHOD(XonoticMapInfoDialog, fill, void(entity))
- METHOD(XonoticMapInfoDialog, loadMapInfo, void(entity, float, entity))
+ METHOD(XonoticMapInfoDialog, fill, void(entity));
+ METHOD(XonoticMapInfoDialog, loadMapInfo, void(entity, float, entity));
ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information"))
ATTRIB(XonoticMapInfoDialog, color, vector, SKINCOLOR_DIALOG_MAPINFO)
ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 1.0)
#define DIALOG_MULTIPLAYER_CREATE_MUTATORS_H
#include "dialog.qc"
CLASS(XonoticMutatorsDialog, XonoticDialog)
- METHOD(XonoticMutatorsDialog, toString, string(entity))
- METHOD(XonoticMutatorsDialog, fill, void(entity))
- METHOD(XonoticMutatorsDialog, showNotify, void(entity))
- METHOD(XonoticMutatorsDialog, close, void(entity))
+ METHOD(XonoticMutatorsDialog, toString, string(entity));
+ METHOD(XonoticMutatorsDialog, fill, void(entity));
+ METHOD(XonoticMutatorsDialog, showNotify, void(entity));
+ METHOD(XonoticMutatorsDialog, close, void(entity));
ATTRIB(XonoticMutatorsDialog, title, string, _("Mutators"))
ATTRIB(XonoticMutatorsDialog, color, vector, SKINCOLOR_DIALOG_MUTATORS)
ATTRIB(XonoticMutatorsDialog, intendedWidth, float, 0.9)
#define DIALOG_MULTIPLAYER_JOIN_H
#include "tab.qc"
CLASS(XonoticServerListTab, XonoticTab)
- METHOD(XonoticServerListTab, fill, void(entity))
+ METHOD(XonoticServerListTab, fill, void(entity));
ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9)
ATTRIB(XonoticServerListTab, rows, float, 23)
ATTRIB(XonoticServerListTab, columns, float, 6.5)
#define DIALOG_MULTIPLAYER_JOIN_SERVERINFO_H
#include "dialog.qc"
CLASS(XonoticServerInfoDialog, XonoticDialog)
- METHOD(XonoticServerInfoDialog, fill, void(entity))
- METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float))
+ METHOD(XonoticServerInfoDialog, fill, void(entity));
+ METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float));
ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"))
ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO)
ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8)
#define DIALOG_MULTIPLAYER_MEDIA_H
#include "tab.qc"
CLASS(XonoticMediaTab, XonoticTab)
- METHOD(XonoticMediaTab, fill, void(entity))
+ METHOD(XonoticMediaTab, fill, void(entity));
ATTRIB(XonoticMediaTab, intendedWidth, float, 0.9)
ATTRIB(XonoticMediaTab, rows, float, 23)
ATTRIB(XonoticMediaTab, columns, float, 3)
#define DIALOG_MULTIPLAYER_MEDIA_DEMO_H
#include "tab.qc"
CLASS(XonoticDemoBrowserTab, XonoticTab)
- METHOD(XonoticDemoBrowserTab, fill, void(entity))
+ METHOD(XonoticDemoBrowserTab, fill, void(entity));
ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9)
ATTRIB(XonoticDemoBrowserTab, rows, float, 21)
ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5)
#define DIALOG_MULTIPLAYER_MEDIA_DEMO_STARTCONFIRM_H
#include "dialog.qc"
CLASS(XonoticDemoStartConfirmDialog, XonoticDialog)
- METHOD(XonoticDemoStartConfirmDialog, fill, void(entity))
+ METHOD(XonoticDemoStartConfirmDialog, fill, void(entity));
ATTRIB(XonoticDemoStartConfirmDialog, title, string, _("Disconnect"))
ATTRIB(XonoticDemoStartConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
ATTRIB(XonoticDemoStartConfirmDialog, intendedWidth, float, 0.5)
#define DIALOG_MULTIPLAYER_MEDIA_DEMO_TIMECONFIRM_H
#include "dialog.qc"
CLASS(XonoticDemoTimeConfirmDialog, XonoticDialog)
- METHOD(XonoticDemoTimeConfirmDialog, fill, void(entity))
+ METHOD(XonoticDemoTimeConfirmDialog, fill, void(entity));
ATTRIB(XonoticDemoTimeConfirmDialog, title, string, _("Disconnect"))
ATTRIB(XonoticDemoTimeConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
ATTRIB(XonoticDemoTimeConfirmDialog, intendedWidth, float, 0.5)
#define DIALOG_MULTIPLAYER_MEDIA_MUSICPLAYER_H
#include "tab.qc"
CLASS(XonoticMusicPlayerTab, XonoticTab)
- METHOD(XonoticMusicPlayerTab, fill, void(entity))
+ METHOD(XonoticMusicPlayerTab, fill, void(entity));
ATTRIB(XonoticMusicPlayerTab, intendedWidth, float, 0.9)
ATTRIB(XonoticMusicPlayerTab, rows, float, 21)
ATTRIB(XonoticMusicPlayerTab, columns, float, 6.5)
#define DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_H
#include "tab.qc"
CLASS(XonoticScreenshotBrowserTab, XonoticTab)
- METHOD(XonoticScreenshotBrowserTab, fill, void(entity))
+ METHOD(XonoticScreenshotBrowserTab, fill, void(entity));
ATTRIB(XonoticScreenshotBrowserTab, intendedWidth, float, 1)
ATTRIB(XonoticScreenshotBrowserTab, rows, float, 21)
ATTRIB(XonoticScreenshotBrowserTab, columns, float, 6.5)
ATTRIB(XonoticScreenshotBrowserTab, name, string, "ScreenshotBrowser")
- METHOD(XonoticScreenshotBrowserTab, loadPreviewScreenshot, void(entity, string))
+ METHOD(XonoticScreenshotBrowserTab, loadPreviewScreenshot, void(entity, string));
ATTRIB(XonoticScreenshotBrowserTab, screenshotImage, entity, NULL)
ATTRIB(XonoticScreenshotBrowserTab, currentScrPath, string, string_null)
ENDCLASS(XonoticScreenshotBrowserTab)
#define DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_VIEWER_H
#include "dialog.qc"
CLASS(XonoticScreenshotViewerDialog, XonoticDialog)
- METHOD(XonoticScreenshotViewerDialog, fill, void(entity))
- METHOD(XonoticScreenshotViewerDialog, keyDown, float(entity, float, float, float))
- METHOD(XonoticScreenshotViewerDialog, loadScreenshot, void(entity, string))
- METHOD(XonoticScreenshotViewerDialog, close, void(entity))
+ METHOD(XonoticScreenshotViewerDialog, fill, void(entity));
+ METHOD(XonoticScreenshotViewerDialog, keyDown, float(entity, float, float, float));
+ METHOD(XonoticScreenshotViewerDialog, loadScreenshot, void(entity, string));
+ METHOD(XonoticScreenshotViewerDialog, close, void(entity));
ATTRIB(XonoticScreenshotViewerDialog, title, string, "Screenshot Viewer")
ATTRIB(XonoticScreenshotViewerDialog, name, string, "ScreenshotViewer")
ATTRIB(XonoticScreenshotViewerDialog, intendedWidth, float, 1)
#define DIALOG_MULTIPLAYER_PROFILE_H
#include "tab.qc"
CLASS(XonoticProfileTab, XonoticTab)
- METHOD(XonoticProfileTab, fill, void(entity))
- METHOD(XonoticProfileTab, draw, void(entity))
+ METHOD(XonoticProfileTab, fill, void(entity));
+ METHOD(XonoticProfileTab, draw, void(entity));
ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9)
ATTRIB(XonoticProfileTab, rows, float, 23)
ATTRIB(XonoticProfileTab, columns, float, 6.1) // added extra .2 for center space
#define DIALOG_QUIT_H
#include "dialog.qc"
CLASS(XonoticQuitDialog, XonoticDialog)
- METHOD(XonoticQuitDialog, fill, void(entity))
+ METHOD(XonoticQuitDialog, fill, void(entity));
ATTRIB(XonoticQuitDialog, title, string, _("Quit"))
ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
ATTRIB(XonoticQuitDialog, intendedWidth, float, 0.5)
#define DIALOG_SANDBOXTOOLS_H
#include "rootdialog.qc"
CLASS(XonoticSandboxToolsDialog, XonoticRootDialog)
- METHOD(XonoticSandboxToolsDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
+ METHOD(XonoticSandboxToolsDialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools")) // ;)
ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
ATTRIB(XonoticSandboxToolsDialog, intendedWidth, float, 0.8)
#define DIALOG_SETTINGS_H
#include "dialog.qc"
CLASS(XonoticSettingsDialog, XonoticDialog)
- METHOD(XonoticSettingsDialog, fill, void(entity))
+ METHOD(XonoticSettingsDialog, fill, void(entity));
ATTRIB(XonoticSettingsDialog, title, string, _("Settings"))
ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS)
ATTRIB(XonoticSettingsDialog, intendedWidth, float, 0.96)
#define DIALOG_SETTINGS_AUDIO_H
#include "tab.qc"
CLASS(XonoticAudioSettingsTab, XonoticTab)
- METHOD(XonoticAudioSettingsTab, fill, void(entity))
+ METHOD(XonoticAudioSettingsTab, fill, void(entity));
ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticAudioSettingsTab, rows, float, 15.5)
ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
#define DIALOG_SETTINGS_EFFECTS_H
#include "tab.qc"
CLASS(XonoticEffectsSettingsTab, XonoticTab)
- METHOD(XonoticEffectsSettingsTab, fill, void(entity))
+ METHOD(XonoticEffectsSettingsTab, fill, void(entity));
ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticEffectsSettingsTab, rows, float, 15.5)
ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
#define DIALOG_SETTINGS_GAME_H
#include "tab.qc"
CLASS(XonoticGameSettingsTab, XonoticTab)
- METHOD(XonoticGameSettingsTab, fill, void(entity))
+ METHOD(XonoticGameSettingsTab, fill, void(entity));
ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameSettingsTab, rows, float, 15.5)
ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
#define DIALOG_SETTINGS_GAME_CROSSHAIR_H
#include "tab.qc"
CLASS(XonoticGameCrosshairSettingsTab, XonoticTab)
- METHOD(XonoticGameCrosshairSettingsTab, fill, void(entity))
- METHOD(XonoticGameCrosshairSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameCrosshairSettingsTab, fill, void(entity));
+ METHOD(XonoticGameCrosshairSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameCrosshairSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameCrosshairSettingsTab, rows, float, 13)
ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2)
#define DIALOG_SETTINGS_GAME_HUD_H
#include "tab.qc"
CLASS(XonoticGameHUDSettingsTab, XonoticTab)
- METHOD(XonoticGameHUDSettingsTab, fill, void(entity))
- METHOD(XonoticGameHUDSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameHUDSettingsTab, fill, void(entity));
+ METHOD(XonoticGameHUDSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameHUDSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameHUDSettingsTab, rows, float, 13)
ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2)
#define DIALOG_SETTINGS_GAME_HUDCONFIRM_H
#include "dialog.qc"
CLASS(XonoticHUDConfirmDialog, XonoticDialog)
- METHOD(XonoticHUDConfirmDialog, fill, void(entity))
+ METHOD(XonoticHUDConfirmDialog, fill, void(entity));
ATTRIB(XonoticHUDConfirmDialog, title, string, _("Enter HUD editor"))
ATTRIB(XonoticHUDConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
ATTRIB(XonoticHUDConfirmDialog, intendedWidth, float, 0.5)
#define DIALOG_SETTINGS_GAME_MESSAGES_H
#include "tab.qc"
CLASS(XonoticGameMessageSettingsTab, XonoticTab)
- METHOD(XonoticGameMessageSettingsTab, fill, void(entity))
- METHOD(XonoticGameMessageSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameMessageSettingsTab, fill, void(entity));
+ METHOD(XonoticGameMessageSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameMessageSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameMessageSettingsTab, rows, float, 13)
ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6)
#define DIALOG_SETTINGS_GAME_MODEL_H
#include "tab.qc"
CLASS(XonoticGameModelSettingsTab, XonoticTab)
- METHOD(XonoticGameModelSettingsTab, fill, void(entity))
- METHOD(XonoticGameModelSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameModelSettingsTab, fill, void(entity));
+ METHOD(XonoticGameModelSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameModelSettingsTab, rows, float, 13)
ATTRIB(XonoticGameModelSettingsTab, columns, float, 5)
#define DIALOG_SETTINGS_GAME_VIEW_H
#include "tab.qc"
CLASS(XonoticGameViewSettingsTab, XonoticTab)
- METHOD(XonoticGameViewSettingsTab, fill, void(entity))
- METHOD(XonoticGameViewSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameViewSettingsTab, fill, void(entity));
+ METHOD(XonoticGameViewSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameViewSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameViewSettingsTab, rows, float, 13)
ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2)
#define DIALOG_SETTINGS_GAME_WEAPONS_H
#include "tab.qc"
CLASS(XonoticGameWeaponsSettingsTab, XonoticTab)
- METHOD(XonoticGameWeaponsSettingsTab, fill, void(entity))
- METHOD(XonoticGameWeaponsSettingsTab, showNotify, void(entity))
+ METHOD(XonoticGameWeaponsSettingsTab, fill, void(entity));
+ METHOD(XonoticGameWeaponsSettingsTab, showNotify, void(entity));
ATTRIB(XonoticGameWeaponsSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameWeaponsSettingsTab, rows, float, 13)
ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6)
#define DIALOG_SETTINGS_INPUT_H
#include "tab.qc"
CLASS(XonoticInputSettingsTab, XonoticTab)
- METHOD(XonoticInputSettingsTab, fill, void(entity))
+ METHOD(XonoticInputSettingsTab, fill, void(entity));
ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticInputSettingsTab, rows, float, 15.5)
ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
#define DIALOG_SETTINGS_INPUT_USERBIND_H
#include "dialog.qc"
CLASS(XonoticUserbindEditDialog, XonoticDialog)
- METHOD(XonoticUserbindEditDialog, loadUserBind, void(entity, string, string, string))
- METHOD(XonoticUserbindEditDialog, fill, void(entity))
+ METHOD(XonoticUserbindEditDialog, loadUserBind, void(entity, string, string, string));
+ METHOD(XonoticUserbindEditDialog, fill, void(entity));
ATTRIB(XonoticUserbindEditDialog, title, string, _("User defined key bind"))
ATTRIB(XonoticUserbindEditDialog, color, vector, SKINCOLOR_DIALOG_USERBIND)
ATTRIB(XonoticUserbindEditDialog, intendedWidth, float, 0.7)
#define DIALOG_SETTINGS_MISC_H
#include "tab.qc"
CLASS(XonoticMiscSettingsTab, XonoticTab)
- METHOD(XonoticMiscSettingsTab, fill, void(entity))
+ METHOD(XonoticMiscSettingsTab, fill, void(entity));
ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticMiscSettingsTab, rows, float, 15.5)
ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2)
#define DIALOG_SETTINGS_MISC_CVARS_H
#include "dialog.qc"
CLASS(XonoticCvarsDialog, XonoticDialog)
- METHOD(XonoticCvarsDialog, fill, void(entity))
- METHOD(XonoticCvarsDialog, showNotify, void(entity))
+ METHOD(XonoticCvarsDialog, fill, void(entity));
+ METHOD(XonoticCvarsDialog, showNotify, void(entity));
ATTRIB(XonoticCvarsDialog, title, string, _("Advanced settings"))
ATTRIB(XonoticCvarsDialog, color, vector, SKINCOLOR_DIALOG_CVARS)
ATTRIB(XonoticCvarsDialog, intendedWidth, float, 0.8)
#define DIALOG_SETTINGS_MISC_RESET_H
#include "dialog.qc"
CLASS(XonoticResetDialog, XonoticDialog)
- METHOD(XonoticResetDialog, fill, void(entity))
+ METHOD(XonoticResetDialog, fill, void(entity));
ATTRIB(XonoticResetDialog, title, string, _("Factory reset"))
ATTRIB(XonoticResetDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
ATTRIB(XonoticResetDialog, intendedWidth, float, 0.5)
#define DIALOG_SETTINGS_USER_H
#include "tab.qc"
CLASS(XonoticUserSettingsTab, XonoticTab)
- METHOD(XonoticUserSettingsTab, fill, void(entity))
+ METHOD(XonoticUserSettingsTab, fill, void(entity));
ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticUserSettingsTab, rows, float, 15.5)
ATTRIB(XonoticUserSettingsTab, columns, float, 6)
#define DIALOG_SETTINGS_USER_LANGUAGEWARNING_H
#include "dialog.qc"
CLASS(XonoticLanguageWarningDialog, XonoticDialog)
- METHOD(XonoticLanguageWarningDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
+ METHOD(XonoticLanguageWarningDialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
ATTRIB(XonoticLanguageWarningDialog, title, string, _("Warning"))
ATTRIB(XonoticLanguageWarningDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
ATTRIB(XonoticLanguageWarningDialog, intendedWidth, float, 0.6)
#define DIALOG_SETTINGS_VIDEO_H
#include "tab.qc"
CLASS(XonoticVideoSettingsTab, XonoticTab)
- METHOD(XonoticVideoSettingsTab, fill, void(entity))
+ METHOD(XonoticVideoSettingsTab, fill, void(entity));
ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticVideoSettingsTab, rows, float, 15.5)
ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2) // added extra .2 for center space
#define DIALOG_SINGLEPLAYER_H
#include "dialog.qc"
CLASS(XonoticSingleplayerDialog, XonoticDialog)
- METHOD(XonoticSingleplayerDialog, fill, void(entity))
+ METHOD(XonoticSingleplayerDialog, fill, void(entity));
ATTRIB(XonoticSingleplayerDialog, title, string, _("Singleplayer"))
ATTRIB(XonoticSingleplayerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER)
ATTRIB(XonoticSingleplayerDialog, intendedWidth, float, 0.80)
#define DIALOG_SINGLEPLAYER_WINNER_H
#include "dialog.qc"
CLASS(XonoticWinnerDialog, XonoticDialog)
- METHOD(XonoticWinnerDialog, fill, void(entity))
- METHOD(XonoticWinnerDialog, focusEnter, void(entity))
+ METHOD(XonoticWinnerDialog, fill, void(entity));
+ METHOD(XonoticWinnerDialog, focusEnter, void(entity));
ATTRIB(XonoticWinnerDialog, title, string, _("Winner"))
ATTRIB(XonoticWinnerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER)
ATTRIB(XonoticWinnerDialog, intendedWidth, float, 0.32)
#define DIALOG_TEAMSELECT_H
#include "rootdialog.qc"
CLASS(XonoticTeamSelectDialog, XonoticRootDialog)
- METHOD(XonoticTeamSelectDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
- METHOD(XonoticTeamSelectDialog, showNotify, void(entity))
+ METHOD(XonoticTeamSelectDialog, fill, void(entity)); // to be overridden by user to fill the dialog with controls
+ METHOD(XonoticTeamSelectDialog, showNotify, void(entity));
ATTRIB(XonoticTeamSelectDialog, title, string, _("Team Selection")) // ;)
ATTRIB(XonoticTeamSelectDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
ATTRIB(XonoticTeamSelectDialog, intendedWidth, float, 0.4)
#define GAMETYPEBUTTON_H
#include "../item/radiobutton.qc"
CLASS(XonoticGametypeButton, RadioButton)
- METHOD(XonoticGametypeButton, configureXonoticGametypeButton, void(entity, float, string, string))
- METHOD(XonoticGametypeButton, setChecked, void(entity, float))
+ METHOD(XonoticGametypeButton, configureXonoticGametypeButton, void(entity, float, string, string));
+ METHOD(XonoticGametypeButton, setChecked, void(entity, float));
ATTRIB(XonoticGametypeButton, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticGametypeButton, image, string, SKINGFX_BUTTON_BIG)
ATTRIB(XonoticGametypeButton, color, vector, SKINCOLOR_BUTTON_N)
ATTRIB(XonoticGametypeButton, useDownAsChecked, float, 1)
ATTRIB(XonoticGametypeButton, cvarName, string, string_null)
- METHOD(XonoticGametypeButton, loadCvars, void(entity))
- METHOD(XonoticGametypeButton, saveCvars, void(entity))
+ METHOD(XonoticGametypeButton, loadCvars, void(entity));
+ METHOD(XonoticGametypeButton, saveCvars, void(entity));
ATTRIB(XonoticGametypeButton, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticGametypeButton, disabledAlpha, float, SKINALPHA_DISABLED)
#define GAMETYPELIST_H
#include "listbox.qc"
CLASS(XonoticGametypeList, XonoticListBox)
- METHOD(XonoticGametypeList, configureXonoticGametypeList, void(entity))
+ METHOD(XonoticGametypeList, configureXonoticGametypeList, void(entity));
ATTRIB(XonoticGametypeList, rowsPerItem, float, 2)
- METHOD(XonoticGametypeList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticGametypeList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticGametypeList, setSelected, void(entity, float))
- METHOD(XonoticGametypeList, loadCvars, void(entity))
- METHOD(XonoticGametypeList, saveCvars, void(entity))
- METHOD(XonoticGametypeList, keyDown, float(entity, float, float, float))
- METHOD(XonoticGametypeList, clickListBoxItem, void(entity, float, vector))
+ METHOD(XonoticGametypeList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticGametypeList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticGametypeList, setSelected, void(entity, float));
+ METHOD(XonoticGametypeList, loadCvars, void(entity));
+ METHOD(XonoticGametypeList, saveCvars, void(entity));
+ METHOD(XonoticGametypeList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticGametypeList, clickListBoxItem, void(entity, float, vector));
ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticGametypeList, realUpperMargin, float, 0)
#define IMAGE_H
#include "../item/image.qc"
CLASS(XonoticImage, Image)
- METHOD(XonoticImage, configureXonoticImage, void(entity, string, float))
+ METHOD(XonoticImage, configureXonoticImage, void(entity, string, float));
ENDCLASS(XonoticImage)
entity makeXonoticImage(string theImage, float theAspect);
#endif
#define INPUTBOX_H
#include "../item/inputbox.qc"
CLASS(XonoticInputBox, InputBox)
- METHOD(XonoticInputBox, configureXonoticInputBox, void(entity, float, string))
- METHOD(XonoticInputBox, focusLeave, void(entity))
- METHOD(XonoticInputBox, setText, void(entity, string))
+ METHOD(XonoticInputBox, configureXonoticInputBox, void(entity, float, string));
+ METHOD(XonoticInputBox, focusLeave, void(entity));
+ METHOD(XonoticInputBox, setText, void(entity, string));
ATTRIB(XonoticInputBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticInputBox, image, string, SKINGFX_INPUTBOX)
ATTRIB(XonoticInputBox, onChange, void(entity, entity), func_null)
ATTRIB(XonoticInputBox, cb_colorC, vector, SKINCOLOR_CLEARBUTTON_C)
ATTRIB(XonoticInputBox, cvarName, string, string_null)
- METHOD(XonoticInputBox, loadCvars, void(entity))
- METHOD(XonoticInputBox, saveCvars, void(entity))
+ METHOD(XonoticInputBox, loadCvars, void(entity));
+ METHOD(XonoticInputBox, saveCvars, void(entity));
ATTRIB(XonoticInputBox, sendCvars, float, 0)
- METHOD(XonoticInputBox, keyDown, float(entity, float, float, float))
+ METHOD(XonoticInputBox, keyDown, float(entity, float, float, float));
ATTRIB(XonoticInputBox, saveImmediately, float, 0)
ENDCLASS(XonoticInputBox)
#define KEYBINDER_H
#include "listbox.qc"
CLASS(XonoticKeyBinder, XonoticListBox)
- METHOD(XonoticKeyBinder, configureXonoticKeyBinder, void(entity))
+ METHOD(XonoticKeyBinder, configureXonoticKeyBinder, void(entity));
ATTRIB(XonoticKeyBinder, rowsPerItem, int, 1)
- METHOD(XonoticKeyBinder, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticKeyBinder, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticKeyBinder, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticKeyBinder, setSelected, void(entity, float))
- METHOD(XonoticKeyBinder, keyDown, float(entity, float, float, float))
- METHOD(XonoticKeyBinder, keyGrabbed, void(entity, float, float))
+ METHOD(XonoticKeyBinder, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticKeyBinder, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticKeyBinder, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticKeyBinder, setSelected, void(entity, float));
+ METHOD(XonoticKeyBinder, keyDown, float(entity, float, float, float));
+ METHOD(XonoticKeyBinder, keyGrabbed, void(entity, float, float));
ATTRIB(XonoticKeyBinder, realFontSize, vector, '0 0 0')
ATTRIB(XonoticKeyBinder, realUpperMargin, float, 0)
ATTRIB(XonoticKeyBinder, keyGrabButton, entity, NULL)
ATTRIB(XonoticKeyBinder, clearButton, entity, NULL)
ATTRIB(XonoticKeyBinder, userbindEditDialog, entity, NULL)
- METHOD(XonoticKeyBinder, editUserbind, void(entity, string, string, string))
+ METHOD(XonoticKeyBinder, editUserbind, void(entity, string, string, string));
ENDCLASS(XonoticKeyBinder)
entity makeXonoticKeyBinder();
void KeyBinder_Bind_Change(entity btn, entity me);
#define LANGUAGELIST_H
#include "listbox.qc"
CLASS(XonoticLanguageList, XonoticListBox)
- METHOD(XonoticLanguageList, configureXonoticLanguageList, void(entity))
+ METHOD(XonoticLanguageList, configureXonoticLanguageList, void(entity));
ATTRIB(XonoticLanguageList, rowsPerItem, float, 1)
- METHOD(XonoticLanguageList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticLanguageList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticLanguageList, setSelected, void(entity, float))
- METHOD(XonoticLanguageList, loadCvars, void(entity))
- METHOD(XonoticLanguageList, saveCvars, void(entity))
+ METHOD(XonoticLanguageList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticLanguageList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticLanguageList, setSelected, void(entity, float));
+ METHOD(XonoticLanguageList, loadCvars, void(entity));
+ METHOD(XonoticLanguageList, saveCvars, void(entity));
ATTRIB(XonoticLanguageList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticLanguageList, realUpperMargin, float, 0)
ATTRIB(XonoticLanguageList, columnPercentageOrigin, float, 0)
ATTRIB(XonoticLanguageList, columnPercentageSize, float, 0)
- METHOD(XonoticLanguageList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticLanguageList, keyDown, float(entity, float, float, float)) // enter handling
+ METHOD(XonoticLanguageList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticLanguageList, keyDown, float(entity, float, float, float)); // enter handling
- METHOD(XonoticLanguageList, destroy, void(entity))
+ METHOD(XonoticLanguageList, destroy, void(entity));
ATTRIB(XonoticLanguageList, languagelist, float, -1)
- METHOD(XonoticLanguageList, getLanguages, void(entity))
- METHOD(XonoticLanguageList, setLanguage, void(entity))
- METHOD(XonoticLanguageList, languageParameter, string(entity, float, float))
+ METHOD(XonoticLanguageList, getLanguages, void(entity));
+ METHOD(XonoticLanguageList, setLanguage, void(entity));
+ METHOD(XonoticLanguageList, languageParameter, string(entity, float, float));
ATTRIB(XonoticLanguageList, name, string, "languageselector") // change this to make it noninteractive (for first run dialog)
ENDCLASS(XonoticLanguageList)
#define LISTBOX_H
#include "../item/listbox.qc"
CLASS(XonoticListBox, ListBox)
- METHOD(XonoticListBox, configureXonoticListBox, void(entity))
+ METHOD(XonoticListBox, configureXonoticListBox, void(entity));
ATTRIB(XonoticListBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticListBox, scrollbarWidth, float, SKINWIDTH_SCROLLBAR)
ATTRIB(XonoticListBox, src, string, SKINGFX_SCROLLBAR)
ATTRIB(XonoticListBox, tolerance, vector, SKINTOLERANCE_SLIDER)
ATTRIB(XonoticListBox, rowsPerItem, float, 1)
- METHOD(XonoticListBox, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(XonoticListBox, resizeNotify, void(entity, vector, vector, vector, vector));
ATTRIB(XonoticListBox, color, vector, SKINCOLOR_SCROLLBAR_N)
ATTRIB(XonoticListBox, colorF, vector, SKINCOLOR_SCROLLBAR_F)
ATTRIB(XonoticListBox, color2, vector, SKINCOLOR_SCROLLBAR_S)
#define MAINWINDOW_H
#include "../item/modalcontroller.qc"
CLASS(MainWindow, ModalController)
- METHOD(MainWindow, configureMainWindow, void(entity))
- METHOD(MainWindow, draw, void(entity))
+ METHOD(MainWindow, configureMainWindow, void(entity));
+ METHOD(MainWindow, draw, void(entity));
ATTRIB(MainWindow, firstRunDialog, entity, NULL)
ATTRIB(MainWindow, advancedDialog, entity, NULL)
ATTRIB(MainWindow, mutatorsDialog, entity, NULL)
#define MAPLIST_H
#include "listbox.qc"
CLASS(XonoticMapList, XonoticListBox)
- METHOD(XonoticMapList, configureXonoticMapList, void(entity))
+ METHOD(XonoticMapList, configureXonoticMapList, void(entity));
ATTRIB(XonoticMapList, rowsPerItem, float, 4)
- METHOD(XonoticMapList, draw, void(entity))
- METHOD(XonoticMapList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticMapList, clickListBoxItem, void(entity, float, vector))
- METHOD(XonoticMapList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticMapList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticMapList, refilter, void(entity))
- METHOD(XonoticMapList, refilterCallback, void(entity, entity))
- METHOD(XonoticMapList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticMapList, draw, void(entity));
+ METHOD(XonoticMapList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticMapList, clickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticMapList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticMapList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticMapList, refilter, void(entity));
+ METHOD(XonoticMapList, refilterCallback, void(entity, entity));
+ METHOD(XonoticMapList, keyDown, float(entity, float, float, float));
ATTRIB(XonoticMapList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticMapList, columnPreviewOrigin, float, 0)
ATTRIB(XonoticMapList, itemAbsSize, vector, '0 0 0')
ATTRIB(XonoticMapList, g_maplistCache, string, string_null)
- METHOD(XonoticMapList, g_maplistCacheToggle, void(entity, float))
- METHOD(XonoticMapList, g_maplistCacheQuery, float(entity, float))
+ METHOD(XonoticMapList, g_maplistCacheToggle, void(entity, float));
+ METHOD(XonoticMapList, g_maplistCacheQuery, float(entity, float));
ATTRIB(XonoticMapList, stringFilter, string, string_null)
ATTRIB(XonoticMapList, stringFilterBox, entity, NULL)
ATTRIB(XonoticMapList, startButton, entity, NULL)
- METHOD(XonoticMapList, loadCvars, void(entity))
+ METHOD(XonoticMapList, loadCvars, void(entity));
ATTRIB(XonoticMapList, typeToSearchString, string, string_null)
ATTRIB(XonoticMapList, typeToSearchTime, float, 0)
- METHOD(XonoticMapList, destroy, void(entity))
+ METHOD(XonoticMapList, destroy, void(entity));
ATTRIB(XonoticMapList, alphaBG, float, 0)
ENDCLASS(XonoticMapList)
me.stringFilter = strzone(box.text);
else
me.stringFilter = string_null;
-
+
me.refilter(me);
}
#define NEXPOSEE_H
#include "../item/nexposee.qc"
CLASS(XonoticNexposee, Nexposee)
- METHOD(XonoticNexposee, configureXonoticNexposee, void(entity))
- METHOD(XonoticNexposee, close, void(entity))
+ METHOD(XonoticNexposee, configureXonoticNexposee, void(entity));
+ METHOD(XonoticNexposee, close, void(entity));
ENDCLASS(XonoticNexposee)
entity makeXonoticNexposee();
#endif
#define PICKER_H
#include "../item.qc"
CLASS(XonoticPicker, Item)
- METHOD(XonoticPicker, configureXonoticPicker, void(entity))
- METHOD(XonoticPicker, mousePress, float(entity, vector))
- METHOD(XonoticPicker, mouseRelease, float(entity, vector))
- METHOD(XonoticPicker, mouseMove, float(entity, vector))
- METHOD(XonoticPicker, mouseDrag, float(entity, vector))
- METHOD(XonoticPicker, keyDown, float(entity, float, float, float))
- METHOD(XonoticPicker, draw, void(entity))
+ METHOD(XonoticPicker, configureXonoticPicker, void(entity));
+ METHOD(XonoticPicker, mousePress, float(entity, vector));
+ METHOD(XonoticPicker, mouseRelease, float(entity, vector));
+ METHOD(XonoticPicker, mouseMove, float(entity, vector));
+ METHOD(XonoticPicker, mouseDrag, float(entity, vector));
+ METHOD(XonoticPicker, keyDown, float(entity, float, float, float));
+ METHOD(XonoticPicker, draw, void(entity));
ATTRIB(XonoticPicker, focusable, float, 1)
ATTRIB(XonoticPicker, disabled, float, 0)
ATTRIB(XonoticPicker, alpha, float, 1)
ATTRIB(XonoticPicker, rows, float, 3)
ATTRIB(XonoticPicker, columns, float, 2)
- METHOD(XonoticPicker, moveFocus, void(entity, vector, vector))
- METHOD(XonoticPicker, cellSelect, void(entity, vector))
- METHOD(XonoticPicker, cellDraw, void(entity, vector, vector))
- METHOD(XonoticPicker, cellIsValid, bool(entity, vector))
+ METHOD(XonoticPicker, moveFocus, void(entity, vector, vector));
+ METHOD(XonoticPicker, cellSelect, void(entity, vector));
+ METHOD(XonoticPicker, cellDraw, void(entity, vector, vector));
+ METHOD(XonoticPicker, cellIsValid, bool(entity, vector));
ATTRIB(XonoticPicker, realCellSize, vector, '0 0 0')
ATTRIB(XonoticPicker, selectedCell, vector, '-1 -1 0')
ATTRIB(XonoticPicker, focusedCell, vector, '-1 -1 0')
#include "listbox.qc"
CLASS(XonoticPlayerList, XonoticListBox)
ATTRIB(XonoticPlayerList, rowsPerItem, float, 1)
- METHOD(XonoticPlayerList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticPlayerList, drawListBoxItem, void(entity, int, vector, bool, bool))
+ METHOD(XonoticPlayerList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticPlayerList, drawListBoxItem, void(entity, int, vector, bool, bool));
ATTRIB(XonoticPlayerList, allowFocusSound, float, 0)
ATTRIB(XonoticPlayerList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticPlayerList, columnNameOrigin, float, 0)
ATTRIB(XonoticPlayerList, realUpperMargin, float, 0)
ATTRIB(XonoticPlayerList, origin, vector, '0 0 0')
ATTRIB(XonoticPlayerList, itemAbsSize, vector, '0 0 0')
- METHOD(XonoticPlayerList, setPlayerList, void(entity, string))
- METHOD(XonoticPlayerList, getPlayerList, string(entity, float, float))
+ METHOD(XonoticPlayerList, setPlayerList, void(entity, string));
+ METHOD(XonoticPlayerList, getPlayerList, string(entity, float, float));
ATTRIB(XonoticPlayerList, playerList, float, -1)
ATTRIB(XonoticPlayerList, selectionDoesntMatter, bool, true)
ENDCLASS(XonoticPlayerList)
#define PLAYERMODEL_H
#include "image.qc"
CLASS(XonoticPlayerModelSelector, XonoticImage)
- METHOD(XonoticPlayerModelSelector, configureXonoticPlayerModelSelector, void(entity))
- METHOD(XonoticPlayerModelSelector, loadCvars, void(entity))
- METHOD(XonoticPlayerModelSelector, saveCvars, void(entity))
- METHOD(XonoticPlayerModelSelector, draw, void(entity))
- METHOD(XonoticPlayerModelSelector, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticPlayerModelSelector, showNotify, void(entity))
+ METHOD(XonoticPlayerModelSelector, configureXonoticPlayerModelSelector, void(entity));
+ METHOD(XonoticPlayerModelSelector, loadCvars, void(entity));
+ METHOD(XonoticPlayerModelSelector, saveCvars, void(entity));
+ METHOD(XonoticPlayerModelSelector, draw, void(entity));
+ METHOD(XonoticPlayerModelSelector, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticPlayerModelSelector, showNotify, void(entity));
ATTRIB(XonoticPlayerModelSelector, currentModel, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentSkin, float, 0)
ATTRIB(XonoticPlayerModelSelector, currentModelImage, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentModelTitle, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentModelDescription, string, string_null)
- METHOD(XonoticPlayerModelSelector, go, void(entity, float))
- METHOD(XonoticPlayerModelSelector, destroy, void(entity))
+ METHOD(XonoticPlayerModelSelector, go, void(entity, float));
+ METHOD(XonoticPlayerModelSelector, destroy, void(entity));
ATTRIB(XonoticPlayerModelSelector, origin, vector, '0 0 0')
ATTRIB(XonoticPlayerModelSelector, size, vector, '0 0 0')
ATTRIB(XonoticPlayerModelSelector, realFontSize, vector, '0 0 0')
#define PLAYLIST_H
#include "listbox.qc"
CLASS(XonoticPlayList, XonoticListBox)
- METHOD(XonoticPlayList, configureXonoticPlayList, void(entity))
+ METHOD(XonoticPlayList, configureXonoticPlayList, void(entity));
ATTRIB(XonoticPlayList, rowsPerItem, float, 1)
- METHOD(XonoticPlayList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticPlayList, draw, void(entity))
- METHOD(XonoticPlayList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticPlayList, stopSound, void(entity))
- METHOD(XonoticPlayList, startSound, void(entity, float))
- METHOD(XonoticPlayList, resumeSound, void(entity))
- METHOD(XonoticPlayList, pauseSound, void(entity))
- METHOD(XonoticPlayList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticPlayList, keyDown, float(entity, float, float, float))
- METHOD(XonoticPlayList, mouseDrag, float(entity, vector))
-
- METHOD(XonoticPlayList, addToPlayList, void(entity, string))
- METHOD(XonoticPlayList, removeSelectedFromPlayList, void(entity))
+ METHOD(XonoticPlayList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticPlayList, draw, void(entity));
+ METHOD(XonoticPlayList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticPlayList, stopSound, void(entity));
+ METHOD(XonoticPlayList, startSound, void(entity, float));
+ METHOD(XonoticPlayList, resumeSound, void(entity));
+ METHOD(XonoticPlayList, pauseSound, void(entity));
+ METHOD(XonoticPlayList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticPlayList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticPlayList, mouseDrag, float(entity, vector));
+
+ METHOD(XonoticPlayList, addToPlayList, void(entity, string));
+ METHOD(XonoticPlayList, removeSelectedFromPlayList, void(entity));
ATTRIB(XonoticPlayList, playingTrack, float, -1)
ATTRIB(XonoticPlayList, realFontSize, vector, '0 0 0')
#define RADIOBUTTON_H
#include "../item/radiobutton.qc"
CLASS(XonoticRadioButton, RadioButton)
- METHOD(XonoticRadioButton, configureXonoticRadioButton, void(entity, float, string, string, string))
- METHOD(XonoticRadioButton, draw, void(entity))
- METHOD(XonoticRadioButton, setChecked, void(entity, float))
+ METHOD(XonoticRadioButton, configureXonoticRadioButton, void(entity, float, string, string, string));
+ METHOD(XonoticRadioButton, draw, void(entity));
+ METHOD(XonoticRadioButton, setChecked, void(entity, float));
ATTRIB(XonoticRadioButton, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticRadioButton, image, string, SKINGFX_RADIOBUTTON)
ATTRIB(XonoticRadioButton, color, vector, SKINCOLOR_RADIOBUTTON_N)
ATTRIB(XonoticRadioButton, cvarValue, string, string_null)
ATTRIB(XonoticRadioButton, cvarOffValue, string, string_null)
ATTRIB(XonoticRadioButton, getCvarValueFromCvar, float, 0)
- METHOD(XonoticRadioButton, loadCvars, void(entity))
- METHOD(XonoticRadioButton, saveCvars, void(entity))
+ METHOD(XonoticRadioButton, loadCvars, void(entity));
+ METHOD(XonoticRadioButton, saveCvars, void(entity));
ATTRIB(XonoticRadioButton, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticRadioButton, disabledAlpha, float, SKINALPHA_DISABLED)
ATTRIB(XonoticDialog, rows, float, 3)
ATTRIB(XonoticDialog, columns, float, 2)
*/
- METHOD(XonoticRootDialog, close, void(entity))
+ METHOD(XonoticRootDialog, close, void(entity));
ENDCLASS(XonoticRootDialog)
#endif
#define SCREENSHOTIMAGE_H
#include "image.qc"
CLASS(XonoticScreenshotImage, XonoticImage)
- METHOD(XonoticScreenshotImage, configureXonoticScreenshotImage, void(entity))
- METHOD(XonoticScreenshotImage, load, void(entity, string))
- METHOD(XonoticScreenshotImage, draw, void(entity))
+ METHOD(XonoticScreenshotImage, configureXonoticScreenshotImage, void(entity));
+ METHOD(XonoticScreenshotImage, load, void(entity, string));
+ METHOD(XonoticScreenshotImage, draw, void(entity));
ATTRIB(XonoticScreenshotImage, focusable, float, 1) // mousePress and mouseDrag work only if focusable is set
- METHOD(XonoticScreenshotImage, mousePress, float(entity, vector))
- METHOD(XonoticScreenshotImage, mouseDrag, float(entity, vector))
- METHOD(XonoticScreenshotImage, mouseMove, float(entity, vector))
- METHOD(XonoticScreenshotImage, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(XonoticScreenshotImage, mousePress, float(entity, vector));
+ METHOD(XonoticScreenshotImage, mouseDrag, float(entity, vector));
+ METHOD(XonoticScreenshotImage, mouseMove, float(entity, vector));
+ METHOD(XonoticScreenshotImage, resizeNotify, void(entity, vector, vector, vector, vector));
ATTRIB(XonoticScreenshotImage, realFontSize, vector, '0 0 0')
ATTRIB(XonoticScreenshotImage, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticScreenshotImage, showTitle, float, 1)
#define SCREENSHOTLIST_H
#include "listbox.qc"
CLASS(XonoticScreenshotList, XonoticListBox)
- METHOD(XonoticScreenshotList, configureXonoticScreenshotList, void(entity))
+ METHOD(XonoticScreenshotList, configureXonoticScreenshotList, void(entity));
ATTRIB(XonoticScreenshotList, rowsPerItem, float, 1)
- METHOD(XonoticScreenshotList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticScreenshotList, setSelected, void(entity, float))
- METHOD(XonoticScreenshotList, draw, void(entity))
- METHOD(XonoticScreenshotList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticScreenshotList, getScreenshots, void(entity))
- METHOD(XonoticScreenshotList, previewScreenshot, void(entity))
- METHOD(XonoticScreenshotList, startScreenshot, void(entity))
- METHOD(XonoticScreenshotList, screenshotName, string(entity, float))
- METHOD(XonoticScreenshotList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticScreenshotList, keyDown, float(entity, float, float, float))
- METHOD(XonoticScreenshotList, destroy, void(entity))
- METHOD(XonoticScreenshotList, showNotify, void(entity))
+ METHOD(XonoticScreenshotList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticScreenshotList, setSelected, void(entity, float));
+ METHOD(XonoticScreenshotList, draw, void(entity));
+ METHOD(XonoticScreenshotList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticScreenshotList, getScreenshots, void(entity));
+ METHOD(XonoticScreenshotList, previewScreenshot, void(entity));
+ METHOD(XonoticScreenshotList, startScreenshot, void(entity));
+ METHOD(XonoticScreenshotList, screenshotName, string(entity, float));
+ METHOD(XonoticScreenshotList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticScreenshotList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticScreenshotList, destroy, void(entity));
+ METHOD(XonoticScreenshotList, showNotify, void(entity));
ATTRIB(XonoticScreenshotList, listScreenshot, float, -1)
ATTRIB(XonoticScreenshotList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticScreenshotList, columnNameOrigin, float, 0)
ATTRIB(XonoticScreenshotList, screenshotBrowserDialog, entity, NULL)
ATTRIB(XonoticScreenshotList, screenshotPreview, entity, NULL)
ATTRIB(XonoticScreenshotList, screenshotViewerDialog, entity, NULL)
- METHOD(XonoticScreenshotList, goScreenshot, void(entity, float))
- METHOD(XonoticScreenshotList, startSlideShow, void(entity))
- METHOD(XonoticScreenshotList, stopSlideShow, void(entity))
+ METHOD(XonoticScreenshotList, goScreenshot, void(entity, float));
+ METHOD(XonoticScreenshotList, startSlideShow, void(entity));
+ METHOD(XonoticScreenshotList, stopSlideShow, void(entity));
ENDCLASS(XonoticScreenshotList)
entity makeXonoticScreenshotList();
#define SERVERLIST_H
#include "listbox.qc"
CLASS(XonoticServerList, XonoticListBox)
- METHOD(XonoticServerList, configureXonoticServerList, void(entity))
+ METHOD(XonoticServerList, configureXonoticServerList, void(entity));
ATTRIB(XonoticServerList, rowsPerItem, float, 1)
- METHOD(XonoticServerList, draw, void(entity))
- METHOD(XonoticServerList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticServerList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticServerList, keyDown, float(entity, float, float, float))
- METHOD(XonoticServerList, toggleFavorite, void(entity, string))
+ METHOD(XonoticServerList, draw, void(entity));
+ METHOD(XonoticServerList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticServerList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticServerList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticServerList, toggleFavorite, void(entity, string));
ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
ATTRIB(XonoticServerList, lockedSelectedItem, bool, true) // initially keep selected the first item of the list, avoiding an unwanted scrolling
ATTRIB(XonoticServerList, selectedServer, string, string_null) // to restore selected server when needed
- METHOD(XonoticServerList, setSelected, void(entity, float))
- METHOD(XonoticServerList, setSortOrder, void(entity, float, float))
+ METHOD(XonoticServerList, setSelected, void(entity, float));
+ METHOD(XonoticServerList, setSortOrder, void(entity, float, float));
ATTRIB(XonoticServerList, filterShowEmpty, float, 1)
ATTRIB(XonoticServerList, filterShowFull, float, 1)
ATTRIB(XonoticServerList, filterString, string, string_null)
ATTRIB(XonoticServerList, ipAddressBox, entity, NULL)
ATTRIB(XonoticServerList, favoriteButton, entity, NULL)
ATTRIB(XonoticServerList, nextRefreshTime, float, 0)
- METHOD(XonoticServerList, refreshServerList, void(entity, float)) // refresh mode: REFRESHSERVERLIST_*
+ METHOD(XonoticServerList, refreshServerList, void(entity, float)); // refresh mode: REFRESHSERVERLIST_*
ATTRIB(XonoticServerList, needsRefresh, float, 1)
- METHOD(XonoticServerList, focusEnter, void(entity))
- METHOD(XonoticServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
+ METHOD(XonoticServerList, focusEnter, void(entity));
+ METHOD(XonoticServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)));
ATTRIB(XonoticServerList, sortButton1, entity, NULL)
ATTRIB(XonoticServerList, sortButton2, entity, NULL)
ATTRIB(XonoticServerList, sortButton3, entity, NULL)
ATTRIB(XonoticServerList, seenIPv6, float, 0)
ATTRIB(XonoticServerList, categoriesHeight, float, 1.25)
- METHOD(XonoticServerList, getTotalHeight, float(entity))
- METHOD(XonoticServerList, getItemAtPos, float(entity, float))
- METHOD(XonoticServerList, getItemStart, float(entity, float))
- METHOD(XonoticServerList, getItemHeight, float(entity, float))
+ METHOD(XonoticServerList, getTotalHeight, float(entity));
+ METHOD(XonoticServerList, getItemAtPos, float(entity, float));
+ METHOD(XonoticServerList, getItemStart, float(entity, float));
+ METHOD(XonoticServerList, getItemHeight, float(entity, float));
ENDCLASS(XonoticServerList)
entity makeXonoticServerList();
#define SKINLIST_H
#include "listbox.qc"
CLASS(XonoticSkinList, XonoticListBox)
- METHOD(XonoticSkinList, configureXonoticSkinList, void(entity))
+ METHOD(XonoticSkinList, configureXonoticSkinList, void(entity));
ATTRIB(XonoticSkinList, rowsPerItem, float, 4)
- METHOD(XonoticSkinList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticSkinList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticSkinList, getSkins, void(entity))
- METHOD(XonoticSkinList, setSkin, void(entity))
- METHOD(XonoticSkinList, loadCvars, void(entity))
- METHOD(XonoticSkinList, saveCvars, void(entity))
- METHOD(XonoticSkinList, skinParameter, string(entity, float, float))
- METHOD(XonoticSkinList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticSkinList, keyDown, float(entity, float, float, float))
- METHOD(XonoticSkinList, destroy, void(entity))
+ METHOD(XonoticSkinList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticSkinList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticSkinList, getSkins, void(entity));
+ METHOD(XonoticSkinList, setSkin, void(entity));
+ METHOD(XonoticSkinList, loadCvars, void(entity));
+ METHOD(XonoticSkinList, saveCvars, void(entity));
+ METHOD(XonoticSkinList, skinParameter, string(entity, float, float));
+ METHOD(XonoticSkinList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticSkinList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticSkinList, destroy, void(entity));
ATTRIB(XonoticSkinList, skinlist, float, -1)
ATTRIB(XonoticSkinList, realFontSize, vector, '0 0 0')
#define SLIDER_H
#include "../item/slider.qc"
CLASS(XonoticSlider, Slider)
- METHOD(XonoticSlider, configureXonoticSlider, void(entity, float, float, float, string))
- METHOD(XonoticSlider, setValue, void(entity, float))
+ METHOD(XonoticSlider, configureXonoticSlider, void(entity, float, float, float, string));
+ METHOD(XonoticSlider, setValue, void(entity, float));
ATTRIB(XonoticSlider, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
ATTRIB(XonoticSlider, image, string, SKINGFX_SLIDER)
ATTRIB(XonoticSlider, color2, vector, SKINCOLOR_SLIDER_S)
ATTRIB(XonoticSlider, cvarName, string, string_null)
- METHOD(XonoticSlider, loadCvars, void(entity))
- METHOD(XonoticSlider, saveCvars, void(entity))
+ METHOD(XonoticSlider, loadCvars, void(entity));
+ METHOD(XonoticSlider, saveCvars, void(entity));
ATTRIB(XonoticSlider, sendCvars, float, 0)
ATTRIB(XonoticSlider, alpha, float, SKINALPHA_TEXT)
#define SLIDER_DECIBELS_H
#include "slider.qc"
CLASS(XonoticDecibelsSlider, XonoticSlider)
- METHOD(XonoticDecibelsSlider, loadCvars, void(entity))
- METHOD(XonoticDecibelsSlider, saveCvars, void(entity))
- METHOD(XonoticDecibelsSlider, valueToText, string(entity, float))
+ METHOD(XonoticDecibelsSlider, loadCvars, void(entity));
+ METHOD(XonoticDecibelsSlider, saveCvars, void(entity));
+ METHOD(XonoticDecibelsSlider, valueToText, string(entity, float));
ENDCLASS(XonoticDecibelsSlider)
entity makeXonoticDecibelsSlider(float, float, float, string);
#endif
#define SLIDER_PARTICLES_H
#include "textslider.qc"
CLASS(XonoticParticlesSlider, XonoticTextSlider)
- METHOD(XonoticParticlesSlider, configureXonoticParticlesSlider, void(entity))
- METHOD(XonoticParticlesSlider, loadCvars, void(entity))
- METHOD(XonoticParticlesSlider, saveCvars, void(entity))
+ METHOD(XonoticParticlesSlider, configureXonoticParticlesSlider, void(entity));
+ METHOD(XonoticParticlesSlider, loadCvars, void(entity));
+ METHOD(XonoticParticlesSlider, saveCvars, void(entity));
ENDCLASS(XonoticParticlesSlider)
entity makeXonoticParticlesSlider();
#endif
#define SLIDER_PICMIP_H
#include "textslider.qc"
CLASS(XonoticPicmipSlider, XonoticTextSlider)
- METHOD(XonoticPicmipSlider, configureXonoticPicmipSlider, void(entity))
- METHOD(XonoticPicmipSlider, draw, void(entity))
- METHOD(XonoticPicmipSlider, autofix, void(entity))
+ METHOD(XonoticPicmipSlider, configureXonoticPicmipSlider, void(entity));
+ METHOD(XonoticPicmipSlider, draw, void(entity));
+ METHOD(XonoticPicmipSlider, autofix, void(entity));
ATTRIB(XonoticPicmipSlider, have_s3tc, float, 0)
ENDCLASS(XonoticPicmipSlider)
entity makeXonoticPicmipSlider(); // note: you still need to call addValue and configureXonoticTextSliderValues!
#define SLIDER_RESOLUTION_H
#include "textslider.qc"
CLASS(XonoticResolutionSlider, XonoticTextSlider)
- METHOD(XonoticResolutionSlider, configureXonoticResolutionSlider, void(entity))
- METHOD(XonoticResolutionSlider, loadResolutions, void(entity, float))
- METHOD(XonoticResolutionSlider, addResolution, void(entity, float, float, float))
- METHOD(XonoticResolutionSlider, loadCvars, void(entity))
- METHOD(XonoticResolutionSlider, saveCvars, void(entity))
- METHOD(XonoticResolutionSlider, draw, void(entity))
+ METHOD(XonoticResolutionSlider, configureXonoticResolutionSlider, void(entity));
+ METHOD(XonoticResolutionSlider, loadResolutions, void(entity, float));
+ METHOD(XonoticResolutionSlider, addResolution, void(entity, float, float, float));
+ METHOD(XonoticResolutionSlider, loadCvars, void(entity));
+ METHOD(XonoticResolutionSlider, saveCvars, void(entity));
+ METHOD(XonoticResolutionSlider, draw, void(entity));
ATTRIB(XonoticResolutionSlider, vid_fullscreen, float, -1)
ATTRIB(XonoticResolutionSlider, maxAllowedWidth, float, 0)
ATTRIB(XonoticResolutionSlider, maxAllowedHeight, float, 0)
#define SLIDER_SBFADETIME_H
#include "textslider.qc"
CLASS(XonoticScoreboardFadeTimeSlider, XonoticTextSlider)
- METHOD(XonoticScoreboardFadeTimeSlider, configureXonoticScoreboardFadeTimeSlider, void(entity))
- METHOD(XonoticScoreboardFadeTimeSlider, loadCvars, void(entity))
- METHOD(XonoticScoreboardFadeTimeSlider, saveCvars, void(entity))
+ METHOD(XonoticScoreboardFadeTimeSlider, configureXonoticScoreboardFadeTimeSlider, void(entity));
+ METHOD(XonoticScoreboardFadeTimeSlider, loadCvars, void(entity));
+ METHOD(XonoticScoreboardFadeTimeSlider, saveCvars, void(entity));
ENDCLASS(XonoticScoreboardFadeTimeSlider)
entity makeXonoticScoreboardFadeTimeSlider();
#endif
#define SOUNDLIST_H
#include "listbox.qc"
CLASS(XonoticSoundList, XonoticListBox)
- METHOD(XonoticSoundList, configureXonoticSoundList, void(entity))
+ METHOD(XonoticSoundList, configureXonoticSoundList, void(entity));
ATTRIB(XonoticSoundList, rowsPerItem, float, 1)
- METHOD(XonoticSoundList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticSoundList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticSoundList, getSounds, void(entity))
- METHOD(XonoticSoundList, soundName, string(entity, float))
- METHOD(XonoticSoundList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticSoundList, keyDown, float(entity, float, float, float))
- METHOD(XonoticSoundList, destroy, void(entity))
- METHOD(XonoticSoundList, showNotify, void(entity))
+ METHOD(XonoticSoundList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticSoundList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticSoundList, getSounds, void(entity));
+ METHOD(XonoticSoundList, soundName, string(entity, float));
+ METHOD(XonoticSoundList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticSoundList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticSoundList, destroy, void(entity));
+ METHOD(XonoticSoundList, showNotify, void(entity));
ATTRIB(XonoticSoundList, listSound, float, -1)
ATTRIB(XonoticSoundList, realFontSize, vector, '0 0 0')
#define STATSLIST_H
#include "listbox.qc"
CLASS(XonoticStatsList, XonoticListBox)
- METHOD(XonoticStatsList, configureXonoticStatsList, void(entity))
+ METHOD(XonoticStatsList, configureXonoticStatsList, void(entity));
ATTRIB(XonoticStatsList, rowsPerItem, float, 1.4)
- METHOD(XonoticStatsList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticStatsList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticStatsList, getStats, void(entity))
- METHOD(XonoticStatsList, doubleClickListBoxItem, void(entity, float, vector))
- METHOD(XonoticStatsList, keyDown, float(entity, float, float, float))
- METHOD(XonoticStatsList, destroy, void(entity))
- METHOD(XonoticStatsList, showNotify, void(entity))
+ METHOD(XonoticStatsList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticStatsList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticStatsList, getStats, void(entity));
+ METHOD(XonoticStatsList, doubleClickListBoxItem, void(entity, float, vector));
+ METHOD(XonoticStatsList, keyDown, float(entity, float, float, float));
+ METHOD(XonoticStatsList, destroy, void(entity));
+ METHOD(XonoticStatsList, showNotify, void(entity));
ATTRIB(XonoticStatsList, selectionDoesntMatter, bool, true)
ATTRIB(XonoticStatsList, listStats, float, -1)
ATTRIB(XonoticTab, rows, float, 3)
ATTRIB(XonoticTab, columns, float, 2)
*/
- METHOD(XonoticTab, showNotify, void(entity))
+ METHOD(XonoticTab, showNotify, void(entity));
ATTRIB(XonoticTab, marginTop, float, 0) // pixels
ATTRIB(XonoticTab, marginBottom, float, 0) // pixels
#define TABCONTROLLER_H
#include "../item/modalcontroller.qc"
CLASS(XonoticTabController, ModalController)
- METHOD(XonoticTabController, configureXonoticTabController, void(entity, float))
- METHOD(XonoticTabController, makeTabButton, entity(entity, string, entity))
+ METHOD(XonoticTabController, configureXonoticTabController, void(entity, float));
+ METHOD(XonoticTabController, makeTabButton, entity(entity, string, entity));
ATTRIB(XonoticTabController, rows, float, 0)
ATTRIB(XonoticTabController, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticTabController, image, string, SKINGFX_BUTTON)
#define TEXTLABEL_H
#include "../item/label.qc"
CLASS(XonoticTextLabel, Label)
- METHOD(XonoticTextLabel, configureXonoticTextLabel, void(entity, float, string))
- METHOD(XonoticTextLabel, draw, void(entity))
+ METHOD(XonoticTextLabel, configureXonoticTextLabel, void(entity, float, string));
+ METHOD(XonoticTextLabel, draw, void(entity));
ATTRIB(XonoticTextLabel, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticTextLabel, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticTextLabel, disabledAlpha, float, SKINALPHA_DISABLED)
#define TEXTSLIDER_H
#include "../item/textslider.qc"
CLASS(XonoticTextSlider, TextSlider)
- METHOD(XonoticTextSlider, configureXonoticTextSlider, void(entity, string))
- METHOD(XonoticTextSlider, setValue, void(entity, float))
- METHOD(XonoticTextSlider, configureXonoticTextSliderValues, void(entity))
+ METHOD(XonoticTextSlider, configureXonoticTextSlider, void(entity, string));
+ METHOD(XonoticTextSlider, setValue, void(entity, float));
+ METHOD(XonoticTextSlider, configureXonoticTextSliderValues, void(entity));
ATTRIB(XonoticTextSlider, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticTextSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
ATTRIB(XonoticTextSlider, image, string, SKINGFX_SLIDER)
ATTRIB(XonoticTextSlider, color2, vector, SKINCOLOR_SLIDER_S)
ATTRIB(XonoticTextSlider, cvarName, string, string_null)
- METHOD(XonoticTextSlider, loadCvars, void(entity))
- METHOD(XonoticTextSlider, saveCvars, void(entity))
+ METHOD(XonoticTextSlider, loadCvars, void(entity));
+ METHOD(XonoticTextSlider, saveCvars, void(entity));
ATTRIB(XonoticTextSlider, sendCvars, float, 0)
ATTRIB(XonoticTextSlider, alpha, float, SKINALPHA_TEXT)
#define WEAPONARENACHECKBOX_H
#include "../item/checkbox.qc"
CLASS(XonoticWeaponarenaCheckBox, CheckBox)
- METHOD(XonoticWeaponarenaCheckBox, configureXonoticWeaponarenaCheckBox, void(entity, string, string))
- METHOD(XonoticWeaponarenaCheckBox, setChecked, void(entity, float))
+ METHOD(XonoticWeaponarenaCheckBox, configureXonoticWeaponarenaCheckBox, void(entity, string, string));
+ METHOD(XonoticWeaponarenaCheckBox, setChecked, void(entity, float));
ATTRIB(XonoticWeaponarenaCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticWeaponarenaCheckBox, image, string, SKINGFX_CHECKBOX)
ATTRIB(XonoticWeaponarenaCheckBox, netname, string, string_null)
- METHOD(XonoticWeaponarenaCheckBox, loadCvars, void(entity))
- METHOD(XonoticWeaponarenaCheckBox, saveCvars, void(entity))
+ METHOD(XonoticWeaponarenaCheckBox, loadCvars, void(entity));
+ METHOD(XonoticWeaponarenaCheckBox, saveCvars, void(entity));
ENDCLASS(XonoticWeaponarenaCheckBox)
entity makeXonoticWeaponarenaCheckBox(string, string);
#endif
#define WEAPONSLIST_H
#include "listbox.qc"
CLASS(XonoticWeaponsList, XonoticListBox)
- METHOD(XonoticWeaponsList, configureXonoticWeaponsList, void(entity))
- METHOD(XonoticWeaponsList, toString, string(entity))
+ METHOD(XonoticWeaponsList, configureXonoticWeaponsList, void(entity));
+ METHOD(XonoticWeaponsList, toString, string(entity));
ATTRIB(XonoticWeaponsList, rowsPerItem, float, 1)
- METHOD(XonoticWeaponsList, draw, void(entity))
- METHOD(XonoticWeaponsList, drawListBoxItem, void(entity, int, vector, bool, bool))
- METHOD(XonoticWeaponsList, resizeNotify, void(entity, vector, vector, vector, vector))
- METHOD(XonoticWeaponsList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticWeaponsList, draw, void(entity));
+ METHOD(XonoticWeaponsList, drawListBoxItem, void(entity, int, vector, bool, bool));
+ METHOD(XonoticWeaponsList, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticWeaponsList, keyDown, float(entity, float, float, float));
ATTRIB(XonoticWeaponsList, realFontSize, vector, '0 0 0')
ATTRIB(XonoticWeaponsList, realUpperMargin, float, 0)
- METHOD(XonoticWeaponsList, mouseDrag, float(entity, vector))
+ METHOD(XonoticWeaponsList, mouseDrag, float(entity, vector));
ENDCLASS(XonoticWeaponsList)
entity makeXonoticWeaponsList();
void WeaponsList_MoveUp_Click(entity btn, entity me);
#elif defined(SVQC)
#include "../dpdefs/progsdefs.qh"
#include "../dpdefs/dpextensions.qh"
- #include "../common/vehicles/sv_vehicles.qh"
- #include "../common/vehicles/vehicles.qh"
+ #include "../common/vehicles/all.qh"
#include "antilag.qh"
#endif
bool autocvar_g_nodepthtestitems;
bool autocvar_g_nodepthtestplayers;
bool autocvar_g_norecoil;
-float autocvar_g_onslaught_cp_buildhealth;
-float autocvar_g_onslaught_cp_buildtime;
-float autocvar_g_onslaught_cp_health;
-float autocvar_g_onslaught_cp_regen;
-float autocvar_g_onslaught_gen_health;
int autocvar_g_pickup_cells_max;
int autocvar_g_pickup_plasma_max;
int autocvar_g_pickup_fuel_max;
bool autocvar_g_turrets_reloadcvars;
float autocvar_g_turrets_targetscan_maxdelay;
float autocvar_g_turrets_targetscan_mindelay;
-float autocvar_g_turrets_unit_ewheel_speed_fast;
-float autocvar_g_turrets_unit_ewheel_speed_slow;
-float autocvar_g_turrets_unit_ewheel_speed_slower;
-float autocvar_g_turrets_unit_ewheel_speed_stop;
-float autocvar_g_turrets_unit_ewheel_turnrate;
-float autocvar_g_turrets_unit_hellion_std_shot_speed_gain;
-float autocvar_g_turrets_unit_hellion_std_shot_speed_max;
-float autocvar_g_turrets_unit_hk_std_shot_speed;
-float autocvar_g_turrets_unit_hk_std_shot_speed_accel;
-float autocvar_g_turrets_unit_hk_std_shot_speed_accel2;
-float autocvar_g_turrets_unit_hk_std_shot_speed_decel;
-float autocvar_g_turrets_unit_hk_std_shot_speed_max;
-float autocvar_g_turrets_unit_hk_std_shot_speed_turnrate;
-float autocvar_g_turrets_unit_walker_speed_jump;
-float autocvar_g_turrets_unit_walker_speed_roam;
-float autocvar_g_turrets_unit_walker_speed_run;
-float autocvar_g_turrets_unit_walker_speed_stop;
-float autocvar_g_turrets_unit_walker_speed_swim;
-float autocvar_g_turrets_unit_walker_speed_walk;
-float autocvar_g_turrets_unit_walker_std_meele_dmg;
-float autocvar_g_turrets_unit_walker_std_meele_force;
-float autocvar_g_turrets_unit_walker_std_meele_range;
-float autocvar_g_turrets_unit_walker_std_rocket_dmg;
-float autocvar_g_turrets_unit_walker_std_rocket_force;
-float autocvar_g_turrets_unit_walker_std_rocket_radius;
-float autocvar_g_turrets_unit_walker_std_rocket_refire;
-float autocvar_g_turrets_unit_walker_std_rocket_speed;
-float autocvar_g_turrets_unit_walker_std_rocket_turnrate;
-float autocvar_g_turrets_unit_walker_std_rockets_range;
-float autocvar_g_turrets_unit_walker_std_rockets_range_min;
-float autocvar_g_turrets_unit_walker_turn;
-float autocvar_g_turrets_unit_walker_turn_walk;
-float autocvar_g_turrets_unit_walker_turn_run;
-float autocvar_g_turrets_unit_walker_turn_strafe;
-float autocvar_g_turrets_unit_walker_turn_swim;
bool autocvar_g_use_ammunition;
bool autocvar_g_waypointeditor;
int autocvar_g_waypointeditor_auto;
-int autocvar_g_waypoints_for_items;
+bool autocvar_g_waypoints_for_items;
float autocvar_g_weapon_charge_colormod_blue_full;
float autocvar_g_weapon_charge_colormod_blue_half;
float autocvar_g_weapon_charge_colormod_green_full;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
+float autocvar_g_onslaught_debug;
+float autocvar_g_onslaught_teleport_wait;
+bool autocvar_g_onslaught_spawn_at_controlpoints;
+bool autocvar_g_onslaught_spawn_at_generator;
+float autocvar_g_onslaught_cp_proxydecap;
+float autocvar_g_onslaught_cp_proxydecap_distance = 512;
+float autocvar_g_onslaught_cp_proxydecap_dps = 100;
+float autocvar_g_onslaught_spawn_at_controlpoints_chance = 0.5;
+float autocvar_g_onslaught_spawn_at_controlpoints_random;
+float autocvar_g_onslaught_spawn_at_generator_chance;
+float autocvar_g_onslaught_spawn_at_generator_random;
+float autocvar_g_onslaught_cp_buildhealth;
+float autocvar_g_onslaught_cp_buildtime;
+float autocvar_g_onslaught_cp_health;
+float autocvar_g_onslaught_cp_regen;
+float autocvar_g_onslaught_gen_health;
+float autocvar_g_onslaught_shield_force = 100;
+float autocvar_g_onslaught_allow_vehicle_touch;
+float autocvar_g_onslaught_round_timelimit;
+float autocvar_g_onslaught_point_limit;
+float autocvar_g_onslaught_warmup;
+float autocvar_g_onslaught_teleport_radius;
+float autocvar_g_onslaught_spawn_choose;
+float autocvar_g_onslaught_click_radius;
int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
bool autocvar_g_physics_clientselect;
+++ /dev/null
-#include "../../_all.qh"
-
-#include "havocbot.qh"
-
-#include "../bot.qh"
-#include "../navigation.qh"
-#include "../waypoints.qh"
-
-#include "../../mutators/mutators_include.qh"
-
-#include "../../../common/teams.qh"
-
-const int HAVOCBOT_ONS_ROLE_NONE = 0;
-const int HAVOCBOT_ONS_ROLE_DEFENSE = 2;
-const int HAVOCBOT_ONS_ROLE_ASSISTANT = 4;
-const int HAVOCBOT_ONS_ROLE_OFFENSE = 8;
-
-.int havocbot_role_flags;
-.float havocbot_attack_time;
-
-.void() havocbot_role;
-.void() havocbot_previous_role;
-
-void() havocbot_role_ons_defense;
-void() havocbot_role_ons_offense;
-void() havocbot_role_ons_assistant;
-
-void(entity bot) havocbot_ons_reset_role;
-void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
-void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
-
-.float isshielded;
-.float iscaptured;
-.float islinked;
-.float isgenneighbor_blue, iscpneighbor_blue;
-.float isgenneighbor_red, iscpneighbor_red;
-
-.entity havocbot_ons_target;
-
-void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
-{
- entity head;
- float t, i, c, needarmor = false, needweapons = false;
-
- // Needs armor/health?
- if(self.health<100)
- needarmor = true;
-
- // Needs weapons?
- c = 0;
- for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
- {
- // Find weapon
- if(self.weapons & WepSet_FromWeapon(i))
- if(++c>=4)
- break;
- }
-
- if(c<4)
- needweapons = true;
-
- if(!needweapons && !needarmor)
- return;
-
-// dprint(self.netname, " needs weapons ", ftos(needweapons) , "\n");
-// dprint(self.netname, " needs armor ", ftos(needarmor) , "\n");
-
- // See what is around
- head = findchainfloat(bot_pickup, true);
- while (head)
- {
- // gather health and armor only
- if (head.solid)
- if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
- if (vlen(head.origin - org) < sradius)
- {
- t = head.bot_pickupevalfunc(self, head);
- if (t > 0)
- navigation_routerating(head, t * ratingscale, 500);
- }
- head = head.chain;
- }
-}
-
-void havocbot_role_ons_setrole(entity bot, float role)
-{
- dprint(strcat(bot.netname," switched to "));
- switch(role)
- {
- case HAVOCBOT_ONS_ROLE_DEFENSE:
- dprint("defense");
- bot.havocbot_role = havocbot_role_ons_defense;
- bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
- bot.havocbot_role_timeout = 0;
- break;
- case HAVOCBOT_ONS_ROLE_ASSISTANT:
- dprint("assistant");
- bot.havocbot_role = havocbot_role_ons_assistant;
- bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
- bot.havocbot_role_timeout = 0;
- break;
- case HAVOCBOT_ONS_ROLE_OFFENSE:
- dprint("offense");
- bot.havocbot_role = havocbot_role_ons_offense;
- bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
- bot.havocbot_role_timeout = 0;
- break;
- }
- dprint("\n");
-}
-
-float havocbot_ons_teamcount(entity bot, int role)
-{
- float c = 0;
- entity head;
-
- FOR_EACH_PLAYER(head)
- if(head.team==self.team)
- if(head.havocbot_role_flags & role)
- ++c;
-
- return c;
-}
-
-void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
-{
- entity cp, cp1, cp2, best, pl, wp;
- float radius, found, bestvalue, c;
-
- cp1 = cp2 = findchain(classname, "onslaught_controlpoint");
-
- // Filter control points
- for (; cp2; cp2 = cp2.chain)
- {
- cp2.wpcost = c = 0;
- cp2.wpconsidered = false;
-
- if(cp2.isshielded)
- continue;
-
- // Ignore owned controlpoints
- if(self.team == NUM_TEAM_1)
- {
- if( (cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) && !(cp2.isgenneighbor_red || cp2.iscpneighbor_red) )
- continue;
- }
- else if(self.team == NUM_TEAM_2)
- {
- if( (cp2.isgenneighbor_red || cp2.iscpneighbor_red) && !(cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) )
- continue;
- }
-
- // Count team mates interested in this control point
- // (easier and cleaner than keeping counters per cp and teams)
- FOR_EACH_PLAYER(pl)
- if(pl.team==self.team)
- if(pl.havocbot_role_flags & HAVOCBOT_ONS_ROLE_OFFENSE)
- if(pl.havocbot_ons_target==cp2)
- ++c;
-
- // NOTE: probably decrease the cost of attackable control points
- cp2.wpcost = c;
- cp2.wpconsidered = true;
- }
-
- // We'll consider only the best case
- bestvalue = 99999999999;
- cp = world;
- for (; cp1; cp1 = cp1.chain)
- {
- if (!cp1.wpconsidered)
- continue;
-
- if(cp1.wpcost<bestvalue)
- {
- bestvalue = cp1.wpcost;
- cp = cp1;
- self.havocbot_ons_target = cp1;
- }
- }
-
- if (!cp)
- return;
-
-// dprint(self.netname, " chose cp ranked ", ftos(bestvalue), "\n");
-
- if(cp.goalentity)
- {
- // Should be attacked
- // Rate waypoints near it
- found = false;
- best = world;
- bestvalue = 99999999999;
- for(radius=0; radius<1000 && !found; radius+=500)
- {
- for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
- {
- if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
- if(wp.classname=="waypoint")
- if(checkpvs(wp.origin,cp))
- {
- found = true;
- if(wp.cnt<bestvalue)
- {
- best = wp;
- bestvalue = wp.cnt;
- }
- }
- }
- }
-
- if(best)
- {
- navigation_routerating(best, ratingscale, 10000);
- best.cnt += 1;
-
- self.havocbot_attack_time = 0;
- if(checkpvs(self.view_ofs,cp))
- if(checkpvs(self.view_ofs,best))
- self.havocbot_attack_time = time + 2;
- }
- else
- {
- navigation_routerating(cp, ratingscale, 10000);
- }
- // dprint(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n");
- }
- else
- {
- // Should be touched
- // dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
- found = false;
-
- // Look for auto generated waypoint
- if (!bot_waypoints_for_items)
- for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
- {
- if(wp.classname=="waypoint")
- {
- navigation_routerating(wp, ratingscale, 10000);
- found = true;
- }
- }
-
- // Nothing found, rate the controlpoint itself
- if (!found)
- navigation_routerating(cp, ratingscale, 10000);
- }
-}
-
-float havocbot_goalrating_ons_generator_attack(float ratingscale)
-{
- entity g, wp, bestwp;
- float found, best;
-
- for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
- {
- if(g.team == self.team || g.isshielded)
- continue;
-
- // Should be attacked
- // Rate waypoints near it
- found = false;
- bestwp = world;
- best = 99999999999;
-
- for(wp=findradius(g.origin,400); wp; wp=wp.chain)
- {
- if(wp.classname=="waypoint")
- if(checkpvs(wp.origin,g))
- {
- found = true;
- if(wp.cnt<best)
- {
- bestwp = wp;
- best = wp.cnt;
- }
- }
- }
-
- if(bestwp)
- {
- // dprint("waypoints found around generator\n");
- navigation_routerating(bestwp, ratingscale, 10000);
- bestwp.cnt += 1;
-
- self.havocbot_attack_time = 0;
- if(checkpvs(self.view_ofs,g))
- if(checkpvs(self.view_ofs,bestwp))
- self.havocbot_attack_time = time + 5;
-
- return true;
- }
- else
- {
- // dprint("generator found without waypoints around\n");
- // if there aren't waypoints near the generator go straight to it
- navigation_routerating(g, ratingscale, 10000);
- self.havocbot_attack_time = 0;
- return true;
- }
- }
- return false;
-}
-
-void havocbot_role_ons_offense()
-{
- if(self.deadflag != DEAD_NO)
- {
- self.havocbot_attack_time = 0;
- havocbot_ons_reset_role(self);
- return;
- }
-
- // Set the role timeout if necessary
- if (!self.havocbot_role_timeout)
- self.havocbot_role_timeout = time + 120;
-
- if (time > self.havocbot_role_timeout)
- {
- havocbot_ons_reset_role(self);
- return;
- }
-
- if(self.havocbot_attack_time>time)
- return;
-
- if (self.bot_strategytime < time)
- {
- navigation_goalrating_start();
- havocbot_goalrating_enemyplayers(20000, self.origin, 650);
- if(!havocbot_goalrating_ons_generator_attack(20000))
- havocbot_goalrating_ons_controlpoints_attack(20000);
- havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
- navigation_goalrating_end();
-
- self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
- }
-}
-
-void havocbot_role_ons_assistant()
-{
- havocbot_ons_reset_role(self);
-}
-
-void havocbot_role_ons_defense()
-{
- havocbot_ons_reset_role(self);
-}
-
-void havocbot_ons_reset_role(entity bot)
-{
- entity head;
- float c;
-
- if(self.deadflag != DEAD_NO)
- return;
-
- bot.havocbot_ons_target = world;
-
- // TODO: Defend control points or generator if necessary
-
- // if there is only me on the team switch to offense
- c = 0;
- FOR_EACH_PLAYER(head)
- if(head.team==self.team)
- ++c;
-
- if(c==1)
- {
- havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
- return;
- }
-
- havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
-}
-
-void havocbot_chooserole_ons()
-{
- havocbot_ons_reset_role(self);
-}
+++ /dev/null
-#ifndef ROLE_ONSLAUGHT_H
-#define ROLE_ONSLAUGHT_H
-void havocbot_chooserole_ons();
-#endif
#include "havocbot.qh"
#include "role_keyhunt.qh"
-#include "role_onslaught.qh"
#include "../bot.qh"
#include "../navigation.qh"
return;
else if (g_keyhunt)
havocbot_chooserole_kh();
- else if (g_onslaught)
- havocbot_chooserole_ons();
else // assume anything else is deathmatch
havocbot_chooserole_dm();
}
#include "bot/bot.qh"
#include "bot/navigation.qh"
-#include "../common/vehicles/sv_vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "weapons/hitplot.qh"
#include "weapons/weaponsystem.qh"
dh = dh - max(self.health, 0);
da = da - max(self.armorvalue, 0);
WeaponStats_LogDamage(awep, abot, self.weapon, vbot, dh + da);
+ MUTATOR_CALLHOOK(PlayerDamaged, attacker, self, dh, da, hitloc);
}
if (self.health < 1)
#include "../mutators/mutators_include.qh"
#ifdef SVQC
- #include "../../common/vehicles/sv_vehicles.qh"
+ #include "../../common/vehicles/all.qh"
#endif
#include "../../common/constants.qh"
case CMD_REQUEST_COMMAND:
{
string command = strtolower(argv(1));
-
+
if(!autocvar_g_physics_clientselect)
{
sprint(self, "Client physics selection is currently disabled.\n");
sprint(self, strcat("Available physics sets: \n\n", autocvar_g_physics_clientselect_options, " default\n"));
return;
}
-
+
if(Physics_Valid(command) || command == "default")
{
stuffcmd(self, strcat("\nseta cl_physics ", command, "\nsendcvar cl_physics\n"));
return;
}
}
-
+
default:
sprint(self, strcat("Current physics set: ^3", self.cvar_cl_physics, "\n"));
case CMD_REQUEST_USAGE:
--- /dev/null
+#include "controlpoint.qh"
+
+bool cpicon_send(entity to, int sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_CONTROLPOINT_ICON);
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & CPSF_SETUP)
+ {
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteByte(MSG_ENTITY, self.health);
+ WriteByte(MSG_ENTITY, self.max_health);
+ WriteByte(MSG_ENTITY, self.count);
+ WriteByte(MSG_ENTITY, self.team);
+ WriteByte(MSG_ENTITY, self.owner.iscaptured);
+ }
+
+ if(sf & CPSF_STATUS)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+
+ if(self.health <= 0)
+ WriteByte(MSG_ENTITY, 0);
+ else
+ WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255));
+ }
+
+ return true;
+}
+
+void onslaught_controlpoint_icon_link(entity e, void() spawnproc)
+{
+ Net_LinkEntity(e, true, 0, cpicon_send);
+ e.think = spawnproc;
+ e.nextthink = time * sys_frametime;
+}
--- /dev/null
+#ifndef CONTROLPOINT_H
+#define CONTROLPOINT_H
+
+const vector CPICON_MIN = '-32 -32 -9';
+const vector CPICON_MAX = '32 32 25';
+
+const int CPSF_STATUS = 4;
+const int CPSF_SETUP = 8;
+
+#endif
#include "scores.qh"
#include "waypointsprites.qh"
#include "spawnpoints.qh"
-#include "tturrets/include/turrets_early.qh"
#include "t_items.qh"
-#include "../common/vehicles/sv_vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "weapons/accuracy.qh"
#include "weapons/csqcprojectile.qh"
#include "weapons/selection.qh"
else
victim = targ;
- if(IS_PLAYER(victim) || IS_TURRET(victim) || IS_MONSTER(victim))
+ if(IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim) || MUTATOR_CALLHOOK(PlayHitsound, victim))
{
if(DIFF_TEAM(victim, attacker) && !victim.frozen)
{
#include "../common/notifications.qh"
#include "../common/deathtypes.qh"
#include "mutators/mutators_include.qh"
- #include "tturrets/include/turrets_early.qh"
- #include "../common/vehicles/sv_vehicles.qh"
+ #include "../common/turrets/sv_turrets.qh"
+ #include "../common/vehicles/all.qh"
#include "../csqcmodellib/sv_model.qh"
#include "../common/playerstats.qh"
#include "g_hook.qh"
#include "cl_player.qh"
#include "command/common.qh"
#include "round_handler.qh"
-#include "../common/vehicles/sv_vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "../common/constants.qh"
#include "../common/util.qh"
#include "../common/weapons/all.qh"
#include "../common/mapinfo.qh"
#include "../common/monsters/all.qh"
#include "../common/monsters/sv_monsters.qh"
-#include "../common/vehicles/vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "../common/notifications.qh"
#include "../common/playerstats.qh"
#include "../common/stats.qh"
BADCVAR("pausable");
BADCVAR("sv_allow_fullbright");
BADCVAR("sv_checkforpacketsduringsleep");
- BADCVAR("sv_fraginfo");
BADCVAR("sv_timeout");
BADPREFIX("sv_timeout_");
BADPREFIX("crypto_");
BADPREFIX("prvm_");
BADPREFIX("skill_");
BADPREFIX("sv_cullentities_");
- BADPREFIX("sv_fraginfo_");
BADPREFIX("sv_maxidle_");
BADPREFIX("sv_vote_");
BADPREFIX("timelimit_");
// needs to be done so early because of the constants they create
static_init();
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterEffects);
- CALL_ACCUMULATED_FUNCTION(RegisterVehicles);
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
// needs to be done so early because of the constants they create
static_init();
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterEffects);
- CALL_ACCUMULATED_FUNCTION(RegisterVehicles);
ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
head.winning = 0;
}
-// Onslaught winning condition:
-// game terminates if only one team has a working generator (or none)
-float WinningCondition_Onslaught()
-{
- entity head;
- float t1, t2, t3, t4;
-
- WinningConditionHelper(); // set worldstatus
-
- if(warmup_stage)
- return WINNING_NO;
-
- // first check if the game has ended
- t1 = t2 = t3 = t4 = 0;
- head = find(world, classname, "onslaught_generator");
- while (head)
- {
- if (head.health > 0)
- {
- if (head.team == NUM_TEAM_1) t1 = 1;
- if (head.team == NUM_TEAM_2) t2 = 1;
- if (head.team == NUM_TEAM_3) t3 = 1;
- if (head.team == NUM_TEAM_4) t4 = 1;
- }
- head = find(head, classname, "onslaught_generator");
- }
- if (t1 + t2 + t3 + t4 < 2)
- {
- // game over, only one team remains (or none)
- ClearWinners();
- if (t1) SetWinners(team, NUM_TEAM_1);
- if (t2) SetWinners(team, NUM_TEAM_2);
- if (t3) SetWinners(team, NUM_TEAM_3);
- if (t4) SetWinners(team, NUM_TEAM_4);
- dprint("Have a winner, ending game.\n");
- return WINNING_YES;
- }
-
- // Two or more teams remain
- return WINNING_NO;
-}
-
// Assault winning condition: If the attackers triggered a round end (by fulfilling all objectives)
// they win. Otherwise the defending team wins once the timelimit passes.
void assault_new_round();
return;
}
- if(g_onslaught)
- timelimit = 0; // ONS has its own overtime rule
-
float wantovertime;
wantovertime = 0;
{
checkrules_status = WinningCondition_LMS();
}
- else if (g_onslaught)
- {
- checkrules_status = WinningCondition_Onslaught(); // TODO remove this?
- }
else
{
checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
--- /dev/null
+#include "generator.qh"
+
+bool generator_send(entity to, int sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_GENERATOR);
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & GSF_SETUP)
+ {
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteByte(MSG_ENTITY, self.health);
+ WriteByte(MSG_ENTITY, self.max_health);
+ WriteByte(MSG_ENTITY, self.count);
+ WriteByte(MSG_ENTITY, self.team);
+ }
+
+ if(sf & GSF_STATUS)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+
+ if(self.health <= 0)
+ WriteByte(MSG_ENTITY, 0);
+ else
+ WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255));
+ }
+
+ return true;
+}
+
+void generator_link(void() spawnproc)
+{
+ Net_LinkEntity(self, true, 0, generator_send);
+ self.think = spawnproc;
+ self.nextthink = time;
+}
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+const vector GENERATOR_MIN = '-52 -52 -14';
+const vector GENERATOR_MAX = '52 52 75';
+
+const int GSF_STATUS = 4;
+const int GSF_SETUP = 8;
+
+bool generator_send(entity to, int sf);
+#endif
#include "g_hook.qh"
#include "ipban.qh"
#include "mutators/mutators_include.qh"
-#include "tturrets/include/turrets_early.qh"
#include "t_items.qh"
#include "weapons/accuracy.qh"
#include "weapons/csqcprojectile.qh"
#include "../common/triggers/subs.qh"
#include "../common/urllib.qh"
#include "../common/util.qh"
+#include "../common/turrets/sv_turrets.qh"
#include "../common/weapons/all.qh"
#include "../csqcmodellib/sv_model.qh"
#include "../warpzonelib/anglestransform.qh"
entity cursor_ent;
string escape;
string replacement;
+ string ammoitems;
p = 0;
n = 7;
+ ammoitems = "batteries";
+ if(self.items & ITEM_Plasma.m_itemid) ammoitems = ITEM_Plasma.m_name;
+ if(self.items & ITEM_Cells.m_itemid) ammoitems = ITEM_Cells.m_name;
+ if(self.items & ITEM_Rockets.m_itemid) ammoitems = ITEM_Rockets.m_name;
+ if(self.items & ITEM_Shells.m_itemid) ammoitems = ITEM_Shells.m_name;
+
WarpZone_crosshair_trace(self);
cursor = trace_endpos;
cursor_ent = trace_ent;
replacement = substring(msg, p, 2);
escape = substring(msg, p + 1, 1);
- if (escape == "%")
- replacement = "%";
- else if (escape == "\\")
- replacement = "\\";
- else if (escape == "n")
- replacement = "\n";
- else if (escape == "a")
- replacement = ftos(floor(self.armorvalue));
- else if (escape == "h")
- replacement = ftos(floor(self.health));
- else if (escape == "l")
- replacement = NearestLocation(self.origin);
- else if (escape == "y")
- replacement = NearestLocation(cursor);
- else if (escape == "d")
- replacement = NearestLocation(self.death_origin);
- else if (escape == "w") {
- float wep;
- wep = self.weapon;
- if (!wep)
- wep = self.switchweapon;
- if (!wep)
- wep = self.cnt;
- replacement = WEP_NAME(wep);
- } else if (escape == "W") {
- if (self.items & ITEM_Shells.m_itemid) replacement = "shells";
- else if (self.items & ITEM_Bullets.m_itemid) replacement = "bullets";
- else if (self.items & ITEM_Rockets.m_itemid) replacement = "rockets";
- else if (self.items & ITEM_Cells.m_itemid) replacement = "cells";
- else if (self.items & ITEM_Plasma.m_itemid) replacement = "plasma";
- else replacement = "batteries"; // ;)
- } else if (escape == "x") {
- replacement = cursor_ent.netname;
- if (replacement == "" || !cursor_ent)
- replacement = "nothing";
- } else if (escape == "s")
- replacement = ftos(vlen(self.velocity - self.velocity.z * '0 0 1'));
- else if (escape == "S")
- replacement = ftos(vlen(self.velocity));
+ switch(escape)
+ {
+ case "%": replacement = "%"; break;
+ case "\\":replacement = "\\"; break;
+ case "n": replacement = "\n"; break;
+ case "a": replacement = ftos(floor(self.armorvalue)); break;
+ case "h": replacement = ftos(floor(self.health)); break;
+ case "l": replacement = NearestLocation(self.origin); break;
+ case "y": replacement = NearestLocation(cursor); break;
+ case "d": replacement = NearestLocation(self.death_origin); break;
+ case "w": replacement = WEP_NAME((!self.weapon) ? (!self.switchweapon ? self.cnt : self.switchweapon) : self.weapon); break;
+ case "W": replacement = ammoitems; break;
+ case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
+ case "s": replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); break;
+ case "S": replacement = ftos(vlen(self.velocity)); break;
+ default:
+ {
+ MUTATOR_CALLHOOK(FormatMessage, escape, replacement);
+ break;
+ }
+ }
msg = strcat(substring(msg, 0, p), replacement, substring(msg, p+2, strlen(msg) - (p+2)));
p = p + strlen(replacement);
return p.netname;
}
-vector randompos(vector m1, vector m2)
-{
- vector v;
- m2 = m2 - m1;
- v.x = m2_x * random() + m1_x;
- v.y = m2_y * random() + m1_y;
- v.z = m2_z * random() + m1_z;
- return v;
-}
-
float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done?
{
int i = weaponinfo.weapon;
precache_model ("models/misc/chatbubble.spr");
precache_model("models/ice/ice.md3");
-#ifdef TTURRETS_ENABLED
- if (autocvar_g_turrets)
- turrets_precash();
-#endif
-
// Precache all player models if desired
if (autocvar_sv_precacheplayermodels)
{
#include "../common/constants.qh"
#include "../common/mapinfo.qh"
+#include "../common/turrets/turrets.qh"
#ifdef RELEASE
#define cvar_string_normal builtin_cvar_string
void shockwave_spawn(string m, vector org, float sz, float t1, float t2);
-vector randompos(vector m1, vector m2);
-
void play2team(float t, string filename);
void GetCvars_handleFloat(string thisname, float f, .float field, string name);
#define IS_MONSTER(v) (v.flags & FL_MONSTER)
#define IS_VEHICLE(v) (v.vehicle_flags & VHF_ISVEHICLE)
-#define IS_TURRET(v) (v.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+#define IS_TURRET(v) (v.turret_flags & TUR_FLAG_ISTURRET)
#define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
int frag_deathtype;
MUTATOR_HOOKABLE(PlayerDies, EV_PlayerDies);
+/** called when a player dies to e.g. remove stuff he was carrying. */
+#define EV_PlayHitsound(i, o) \
+ /**/ i(entity, frag_victim) \
+ /**/
+entity frag_victim;
+MUTATOR_HOOKABLE(PlayHitsound, EV_PlayHitsound);
+
/** called when a player presses the jump key */
#define EV_PlayerJump(i, o) \
/**/ i(float, player_multijump) \
/**/
MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
+/** called when formatting a chat message to replace fancy functions */
+#define EV_FormatMessage(i, o) \
+ /**/ i(string, format_escape) \
+ /**/ i(string, format_replacement) \
+ /**/ o(string, format_replacement) \
+ /**/
+string format_escape;
+string format_replacement;
+MUTATOR_HOOKABLE(FormatMessage, EV_FormatMessage);
+
/** returns 1 if throwing the current weapon shall not be allowed */
MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon, EV_NO_ARGS);
vector frag_force;
MUTATOR_HOOKABLE(PlayerDamage_Calculate, EV_PlayerDamage_Calculate);
+/**
+ * Called when a player is damaged
+ */
+#define EV_PlayerDamaged(i, o) \
+ /** attacker */ i(entity, mutator_argv_entity_0) \
+ /** target */ i(entity, mutator_argv_entity_1) \
+ /** health */ i(int, mutator_argv_int_0) \
+ /** armor */ i(int, mutator_argv_int_1) \
+ /** location */ i(vector, mutator_argv_vector_0) \
+ /**/
+MUTATOR_HOOKABLE(PlayerDamaged, EV_PlayerDamaged);
+
/** called at the end of player_powerups() in cl_client.qc, used for manipulating the values which are set by powerup items. */
#define EV_PlayerPowerups(i, o) \
/**/ i(entity, self) \
activator = self;
SUB_UseTargets();
-#ifdef TTURRETS_ENABLED
entity ent, oldself;
//(Re)spawn all turrets
self = ent;
// Dubbles as teamchange
- turret_stdproc_respawn();
+ turret_respawn();
ent = find(ent, classname, "turret_main");
}
self = oldself;
-#endif
}
void assault_wall_think()
return true;
}
+MUTATOR_HOOKFUNCTION(assault_PlayHitsound)
+{
+ return (frag_victim.classname == "func_assault_destructible");
+}
+
// scoreboard setup
void assault_ScoreRules()
{
MUTATOR_HOOK(TurretSpawn, assault_TurretSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(VehicleSpawn, assault_VehicleSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(HavocBot_ChooseRole, assault_BotRoles, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayHitsound, assault_PlayHitsound, CBC_ORDER_ANY);
MUTATOR_ONADD
{
#include "gamemode.qh"
#ifdef SVQC
-#include "../../common/vehicles/sv_vehicles.qh"
+#include "../../common/vehicles/all.qh"
#endif
#include "../../warpzonelib/common.qh"
if(!player) { return; } // without someone to give the reward to, we can't possibly cap
if(CTF_DIFFTEAM(player, flag)) { return; }
-
+
if(ctf_oneflag)
for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext)
if(SAME_TEAM(tmp_entity, player))
else { Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((SAME_TEAM(player, flag)) ? CENTER_CTF_PICKUP_TEAM : CENTER_CTF_PICKUP_TEAM_ENEMY), Team_ColorCode(flag.team)); }
Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, ((flag.team) ? APP_TEAM_ENT_4(flag, CHOICE_CTF_PICKUP_TEAM_) : CHOICE_CTF_PICKUP_TEAM_NEUTRAL), Team_ColorCode(player.team), player.netname);
-
+
if(!flag.team)
FOR_EACH_PLAYER(tmp_entity)
if(tmp_entity != player)
if(DIFF_TEAM(player, tmp_entity))
Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY_NEUTRAL, Team_ColorCode(player.team), player.netname);
-
+
if(flag.team)
FOR_EACH_PLAYER(tmp_entity)
if(tmp_entity != player)
default: flag.effects |= EF_DIMLIGHT; break;
}
}
-
+
// flag placement
if((flag.spawnflags & 1) || flag.noalign) // don't drop to floor, just stay at fixed location
{
int t = 0, t2 = 0, t3 = 0;
// initially clear items so they can be set as necessary later.
- self.ctf_flagstatus &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST
+ self.ctf_flagstatus &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST
| CTF_BLUE_FLAG_CARRYING | CTF_BLUE_FLAG_TAKEN | CTF_BLUE_FLAG_LOST
| CTF_YELLOW_FLAG_CARRYING | CTF_YELLOW_FLAG_TAKEN | CTF_YELLOW_FLAG_LOST
| CTF_PINK_FLAG_CARRYING | CTF_PINK_FLAG_TAKEN | CTF_PINK_FLAG_LOST
{
if((flag.owner == self) || (flag.pass_sender == self))
self.ctf_flagstatus |= t; // carrying: self is currently carrying the flag
- else
+ else
self.ctf_flagstatus |= t2; // taken: someone else is carrying the flag
break;
}
/*QUAKED spawnfunc_item_flag_team3 (0 0.5 0.8) (-48 -48 -37) (48 48 37)
CTF flag for team three (Yellow).
-Keys:
-"angle" Angle the flag will point (minus 90 degrees)...
+Keys:
+"angle" Angle the flag will point (minus 90 degrees)...
"model" model to use, note this needs red, blue yellow and pink as skins 0, 1, 2 and 3...
"noise" sound played when flag is picked up...
"noise1" sound played when flag is returned by a teammate...
"noise2" sound played when flag is captured...
-"noise3" sound played when flag is lost in the field and respawns itself...
+"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
void spawnfunc_item_flag_team3()
/*QUAKED spawnfunc_item_flag_team4 (0 0.5 0.8) (-48 -48 -37) (48 48 37)
CTF flag for team four (Pink).
-Keys:
-"angle" Angle the flag will point (minus 90 degrees)...
+Keys:
+"angle" Angle the flag will point (minus 90 degrees)...
"model" model to use, note this needs red, blue yellow and pink as skins 0, 1, 2 and 3...
"noise" sound played when flag is picked up...
"noise1" sound played when flag is returned by a teammate...
"noise2" sound played when flag is captured...
-"noise3" sound played when flag is lost in the field and respawns itself...
+"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
void spawnfunc_item_flag_team4()
/*QUAKED spawnfunc_item_flag_neutral (0 0.5 0.8) (-48 -48 -37) (48 48 37)
CTF flag (Neutral).
-Keys:
-"angle" Angle the flag will point (minus 90 degrees)...
+Keys:
+"angle" Angle the flag will point (minus 90 degrees)...
"model" model to use, note this needs red, blue yellow and pink as skins 0, 1, 2 and 3...
"noise" sound played when flag is picked up...
"noise1" sound played when flag is returned by a teammate...
"noise2" sound played when flag is captured...
-"noise3" sound played when flag is lost in the field and respawns itself...
+"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
void spawnfunc_item_flag_neutral()
#include "../_all.qh"
#include "gamemode.qh"
+#include "../controlpoint.qh"
+#include "../generator.qh"
-float autocvar_g_onslaught_spawn_at_controlpoints;
-float autocvar_g_onslaught_spawn_at_generator;
-float autocvar_g_onslaught_cp_proxydecap;
-float autocvar_g_onslaught_cp_proxydecap_distance = 512;
-float autocvar_g_onslaught_cp_proxydecap_dps = 100;
+vector randompos(vector m1, vector m2)
+{
+ vector v;
+ m2 = m2 - m1;
+ v_x = m2_x * random() + m1_x;
+ v_y = m2_y * random() + m1_y;
+ v_z = m2_z * random() + m1_z;
+ return v;
+}
-void onslaught_generator_updatesprite(entity e);
-void onslaught_controlpoint_updatesprite(entity e);
-void onslaught_link_checkupdate();
+// =======================
+// CaptureShield Functions
+// =======================
-.entity sprite;
-.string target2;
-.float iscaptured;
-.float islinked;
-.float isgenneighbor_red;
-.float isgenneighbor_blue;
-.float iscpneighbor_red;
-.float iscpneighbor_blue;
-.float isshielded;
-.float lasthealth;
-.float lastteam;
-.float lastshielded;
-.float lastcaptured;
+bool ons_CaptureShield_Customize()
+{
+ entity e = WaypointSprite_getviewentity(other);
-entity ons_red_generator;
-entity ons_blue_generator;
+ if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, e.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return false; }
+ if(SAME_TEAM(self, e)) { return false; }
-void ons_gib_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
- self.velocity = self.velocity + vforce;
+ return true;
}
-.float giblifetime;
-void ons_throwgib_think()
+void ons_CaptureShield_Touch()
{
- float d;
+ if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, other.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return; }
+ if(!IS_PLAYER(other)) { return; }
+ if(SAME_TEAM(other, self)) { return; }
- self.nextthink = time + 0.05;
+ vector mymid = (self.absmin + self.absmax) * 0.5;
+ vector othermid = (other.absmin + other.absmax) * 0.5;
- d = self.giblifetime - time;
+ Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ons_captureshield_force);
- if(d<0)
+ if(IS_REAL_CLIENT(other))
{
- self.think = SUB_Remove;
- return;
+ play2(other, "onslaught/damageblockedbyshield.wav");
+
+ if(self.enemy.classname == "onslaught_generator")
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_GENERATOR_SHIELDED);
+ else
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_CONTROLPOINT_SHIELDED);
}
- if(d<1)
- self.alpha = d;
+}
- if(d>2)
- if(random()<0.6)
- Send_Effect("onslaught_generator_gib_flame", self.origin, '0 0 0', 1);
+void ons_CaptureShield_Reset()
+{
+ self.colormap = self.enemy.colormap;
+ self.team = self.enemy.team;
}
-void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
+void ons_CaptureShield_Spawn(entity generator, bool is_generator)
{
- entity gib;
+ entity shield = spawn();
+
+ shield.enemy = generator;
+ shield.team = generator.team;
+ shield.colormap = generator.colormap;
+ shield.reset = ons_CaptureShield_Reset;
+ shield.touch = ons_CaptureShield_Touch;
+ shield.customizeentityforclient = ons_CaptureShield_Customize;
+ shield.classname = "ons_captureshield";
+ shield.effects = EF_ADDITIVE;
+ shield.movetype = MOVETYPE_NOCLIP;
+ shield.solid = SOLID_TRIGGER;
+ shield.avelocity = '7 0 11';
+ shield.scale = 1;
+ shield.model = ((is_generator) ? "models/onslaught/generator_shield.md3" : "models/onslaught/controlpoint_shield.md3");
+
+ precache_model(shield.model);
+ setorigin(shield, generator.origin);
+ setmodel(shield, shield.model);
+ setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
+}
- gib = spawn();
- setmodel(gib, smodel);
- setorigin(gib, v_from);
- gib.solid = SOLID_BBOX;
- gib.movetype = MOVETYPE_BOUNCE;
- gib.takedamage = DAMAGE_YES;
- gib.event_damage = ons_gib_damage;
- gib.health = -1;
- gib.effects = EF_LOWPRECISION;
- gib.flags = FL_NOTARGET;
- gib.velocity = v_to;
- gib.giblifetime = time + f_lifetime;
+// ==========
+// Junk Pile
+// ==========
- if (b_burn)
+void ons_debug(string input)
+{
+ switch(autocvar_g_onslaught_debug)
{
- gib.think = ons_throwgib_think;
- gib.nextthink = time + 0.05;
+ case 1: dprint(input); break;
+ case 2: print(input); break;
}
- else
- SUB_SetFade(gib, gib.giblifetime, 2);
+}
+
+void setmodel_fixsize(entity e, string m)
+{
+ setmodel(e, m);
+ FixSize(e);
}
void onslaught_updatelinks()
{
- entity l, links;
- float stop, t1, t2, t3, t4;
+ entity l;
// first check if the game has ended
- dprint("--- updatelinks ---\n");
- links = findchain(classname, "onslaught_link");
+ ons_debug("--- updatelinks ---\n");
// mark generators as being shielded and networked
- l = findchain(classname, "onslaught_generator");
- while (l)
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
{
if (l.iscaptured)
- dprint(etos(l), " (generator) belongs to team ", ftos(l.team), "\n");
+ ons_debug(strcat(etos(l), " (generator) belongs to team ", ftos(l.team), "\n"));
else
- dprint(etos(l), " (generator) is destroyed\n");
+ ons_debug(strcat(etos(l), " (generator) is destroyed\n"));
l.islinked = l.iscaptured;
l.isshielded = l.iscaptured;
- l = l.chain;
+ l.sprite.SendFlags |= 16;
}
// mark points as shielded and not networked
- l = findchain(classname, "onslaught_controlpoint");
- while (l)
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
{
l.islinked = false;
l.isshielded = true;
- l.isgenneighbor_red = false;
- l.isgenneighbor_blue = false;
- l.iscpneighbor_red = false;
- l.iscpneighbor_blue = false;
- dprint(etos(l), " (point) belongs to team ", ftos(l.team), "\n");
- l = l.chain;
+ int i;
+ for(i = 0; i < 17; ++i) { l.isgenneighbor[i] = false; l.iscpneighbor[i] = false; }
+ ons_debug(strcat(etos(l), " (point) belongs to team ", ftos(l.team), "\n"));
+ l.sprite.SendFlags |= 16;
}
// flow power outward from the generators through the network
- l = links;
- while (l)
- {
- dprint(etos(l), " (link) connects ", etos(l.goalentity), " with ", etos(l.enemy), "\n");
- l = l.chain;
- }
- stop = false;
+ bool stop = false;
while (!stop)
{
stop = true;
- l = links;
- while (l)
+ for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
{
// if both points are captured by the same team, and only one of
// them is powered, mark the other one as powered as well
if (l.enemy.iscaptured && l.goalentity.iscaptured)
if (l.enemy.islinked != l.goalentity.islinked)
- if (l.enemy.team == l.goalentity.team)
+ if(SAME_TEAM(l.enemy, l.goalentity))
{
if (!l.goalentity.islinked)
{
stop = false;
l.goalentity.islinked = true;
- dprint(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n"));
}
else if (!l.enemy.islinked)
{
stop = false;
l.enemy.islinked = true;
- dprint(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n"));
}
}
- l = l.chain;
}
}
// now that we know which points are powered we can mark their neighbors
// as unshielded if team differs
- l = links;
- while (l)
+ for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
{
if (l.goalentity.islinked)
{
- if (l.goalentity.team != l.enemy.team)
+ if(DIFF_TEAM(l.goalentity, l.enemy))
{
- dprint(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n"));
l.enemy.isshielded = false;
}
if(l.goalentity.classname == "onslaught_generator")
- {
- if(l.goalentity.team == NUM_TEAM_1)
- l.enemy.isgenneighbor_red = true;
- else if(l.goalentity.team == NUM_TEAM_2)
- l.enemy.isgenneighbor_blue = true;
- }
+ l.enemy.isgenneighbor[l.goalentity.team] = true;
else
- {
- if(l.goalentity.team == NUM_TEAM_1)
- l.enemy.iscpneighbor_red = true;
- else if(l.goalentity.team == NUM_TEAM_2)
- l.enemy.iscpneighbor_blue = true;
- }
+ l.enemy.iscpneighbor[l.goalentity.team] = true;
}
if (l.enemy.islinked)
{
- if (l.goalentity.team != l.enemy.team)
+ if(DIFF_TEAM(l.goalentity, l.enemy))
{
- dprint(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n"));
l.goalentity.isshielded = false;
}
if(l.enemy.classname == "onslaught_generator")
- {
- if(l.enemy.team == NUM_TEAM_1)
- l.goalentity.isgenneighbor_red = true;
- else if(l.enemy.team == NUM_TEAM_2)
- l.goalentity.isgenneighbor_blue = true;
- }
+ l.goalentity.isgenneighbor[l.enemy.team] = true;
else
- {
- if(l.enemy.team == NUM_TEAM_1)
- l.goalentity.iscpneighbor_red = true;
- else if(l.enemy.team == NUM_TEAM_2)
- l.goalentity.iscpneighbor_blue = true;
- }
+ l.goalentity.iscpneighbor[l.enemy.team] = true;
}
- l = l.chain;
}
- // now update the takedamage and alpha variables on generator shields
- l = findchain(classname, "onslaught_generator");
- while (l)
+ // now update the generators
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
{
if (l.isshielded)
{
- dprint(etos(l), " (generator) is shielded\n");
- l.enemy.alpha = 1;
+ ons_debug(strcat(etos(l), " (generator) is shielded\n"));
l.takedamage = DAMAGE_NO;
l.bot_attack = false;
}
else
{
- dprint(etos(l), " (generator) is not shielded\n");
- l.enemy.alpha = -1;
+ ons_debug(strcat(etos(l), " (generator) is not shielded\n"));
l.takedamage = DAMAGE_AIM;
l.bot_attack = true;
}
- l = l.chain;
+
+ ons_Generator_UpdateSprite(l);
}
// now update the takedamage and alpha variables on control point icons
- l = findchain(classname, "onslaught_controlpoint");
- while (l)
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
{
if (l.isshielded)
{
- dprint(etos(l), " (point) is shielded\n");
- l.enemy.alpha = 1;
+ ons_debug(strcat(etos(l), " (point) is shielded\n"));
if (l.goalentity)
{
l.goalentity.takedamage = DAMAGE_NO;
}
else
{
- dprint(etos(l), " (point) is not shielded\n");
- l.enemy.alpha = -1;
+ ons_debug(strcat(etos(l), " (point) is not shielded\n"));
if (l.goalentity)
{
l.goalentity.takedamage = DAMAGE_AIM;
l.goalentity.bot_attack = true;
}
}
- onslaught_controlpoint_updatesprite(l);
- l = l.chain;
+ ons_ControlPoint_UpdateSprite(l);
}
- // count generators owned by each team
- t1 = t2 = t3 = t4 = 0;
- l = findchain(classname, "onslaught_generator");
- while (l)
+ l = findchain(classname, "ons_captureshield");
+ while(l)
{
- if (l.iscaptured)
- {
- if (l.team == NUM_TEAM_1) t1 = 1;
- if (l.team == NUM_TEAM_2) t2 = 1;
- if (l.team == NUM_TEAM_3) t3 = 1;
- if (l.team == NUM_TEAM_4) t4 = 1;
- }
- onslaught_generator_updatesprite(l);
+ l.team = l.enemy.team;
+ l.colormap = l.enemy.colormap;
l = l.chain;
}
- // see if multiple teams remain (if not, it's game over)
- if (t1 + t2 + t3 + t4 < 2)
- dprint("--- game over ---\n");
- else
- dprint("--- done updating links ---\n");
}
-float onslaught_controlpoint_can_be_linked(entity cp, float t)
+
+// ===================
+// Main Link Functions
+// ===================
+
+bool ons_Link_Send(entity to, int sendflags)
{
- if(t == NUM_TEAM_1)
+ WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
+ WriteByte(MSG_ENTITY, sendflags);
+ if(sendflags & 1)
{
- if(cp.isgenneighbor_red)
- return 2;
- if(cp.iscpneighbor_red)
- return 1;
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
}
- else if(t == NUM_TEAM_2)
+ if(sendflags & 2)
{
- if(cp.isgenneighbor_blue)
- return 2;
- if(cp.iscpneighbor_blue)
- return 1;
+ WriteCoord(MSG_ENTITY, self.enemy.origin_x);
+ WriteCoord(MSG_ENTITY, self.enemy.origin_y);
+ WriteCoord(MSG_ENTITY, self.enemy.origin_z);
}
- return 0;
- /*
- entity e;
- // check to see if this player has a legitimate claim to capture this
- // control point - more specifically that there is a captured path of
- // points leading back to the team generator
- e = findchain(classname, "onslaught_link");
- while (e)
- {
- if (e.goalentity == cp)
- {
- dprint(etos(e), " (link) connects to ", etos(e.enemy), " (point)");
- if (e.enemy.islinked)
- {
- dprint(" which is linked");
- if (e.enemy.team == t)
+ if(sendflags & 4)
{
- dprint(" and has the correct team!\n");
- return 1;
- }
- else
- dprint(" but has the wrong team\n");
- }
- else
- dprint("\n");
+ WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
}
- else if (e.enemy == cp)
- {
- dprint(etos(e), " (link) connects to ", etos(e.goalentity), " (point)");
- if (e.goalentity.islinked)
- {
- dprint(" which is linked");
- if (e.goalentity.team == t)
+ return true;
+}
+
+void ons_Link_CheckUpdate()
+{
+ // TODO check if the two sides have moved (currently they won't move anyway)
+ float cc = 0, cc1 = 0, cc2 = 0;
+
+ if(self.goalentity.islinked || self.goalentity.iscaptured) { cc1 = (self.goalentity.team - 1) * 0x01; }
+ if(self.enemy.islinked || self.enemy.iscaptured) { cc2 = (self.enemy.team - 1) * 0x10; }
+
+ cc = cc1 + cc2;
+
+ if(cc != self.clientcolors)
{
- dprint(" and has a team!\n");
- return 1;
- }
- else
- dprint(" but has the wrong team\n");
- }
- else
- dprint("\n");
- }
- e = e.chain;
+ self.clientcolors = cc;
+ self.SendFlags |= 4;
}
+
+ self.nextthink = time;
+}
+
+void ons_DelayedLinkSetup()
+{
+ self.goalentity = find(world, targetname, self.target);
+ self.enemy = find(world, targetname, self.target2);
+ if(!self.goalentity) { objerror("can not find target\n"); }
+ if(!self.enemy) { objerror("can not find target2\n"); }
+
+ ons_debug(strcat(etos(self.goalentity), " linked with ", etos(self.enemy), "\n"));
+ self.SendFlags |= 3;
+ self.think = ons_Link_CheckUpdate;
+ self.nextthink = time;
+}
+
+
+// =============================
+// Main Control Point Functions
+// =============================
+
+int ons_ControlPoint_CanBeLinked(entity cp, int teamnumber)
+{
+ if(cp.isgenneighbor[teamnumber]) { return 2; }
+ if(cp.iscpneighbor[teamnumber]) { return 1; }
+
return 0;
- */
}
-float onslaught_controlpoint_attackable(entity cp, float t)
+int ons_ControlPoint_Attackable(entity cp, int teamnumber)
// -2: SAME TEAM, attackable by enemy!
// -1: SAME TEAM!
// 0: off limits
// 3: attack it (HIGH PRIO)
// 4: touch it (HIGH PRIO)
{
- float a;
+ int a;
if(cp.isshielded)
{
else if(cp.goalentity)
{
// if there's already an icon built, nothing happens
- if(cp.team == t)
+ if(cp.team == teamnumber)
{
- a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
if(a) // attackable by enemy?
return -2; // EMERGENCY!
return -1;
}
// we know it can be linked, so no need to check
// but...
- a = onslaught_controlpoint_can_be_linked(cp, t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
if(a == 2) // near our generator?
return 3; // EMERGENCY!
return 1;
else
{
// free point
- if(onslaught_controlpoint_can_be_linked(cp, t))
+ if(ons_ControlPoint_CanBeLinked(cp, teamnumber))
{
- a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber); // why was this here NUM_TEAM_1 + NUM_TEAM_2 - t
if(a == 2)
return 4; // GET THIS ONE NOW!
else
return 0;
}
-float overtime_msg_time;
-void onslaught_generator_think()
+void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
{
- float d;
- entity e;
- self.nextthink = ceil(time + 1);
- if (!gameover)
+ entity oself;
+
+ if(damage <= 0) { return; }
+
+ if (self.owner.isshielded)
{
- if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60)
- {
- if (!overtime_msg_time)
- {
- Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
- overtime_msg_time = time;
- }
- // self.max_health / 300 gives 5 minutes of overtime.
- // control points reduce the overtime duration.
- sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NORM);
- d = 1;
- e = findchain(classname, "onslaught_controlpoint");
- while (e)
+ // this is protected by a shield, so ignore the damage
+ if (time > self.pain_finished)
+ if (IS_PLAYER(attacker))
{
- if (e.team != self.team)
- if (e.islinked)
- d = d + 1;
- e = e.chain;
+ play2(attacker, "onslaught/damageblockedbyshield.wav");
+ self.pain_finished = time + 1;
+ attacker.typehitsound += 1; // play both sounds (shield is way too quiet)
}
- if(autocvar_g_campaign && autocvar__campaign_testrun)
- d = d * self.max_health;
- else
- d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
-
- Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
- }
- else if (overtime_msg_time)
- overtime_msg_time = 0;
-
- if(!self.isshielded && self.wait < time)
- {
- self.wait = time + 5;
- FOR_EACH_REALPLAYER(e)
- {
- if(SAME_TEAM(e, self))
- {
- Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED);
- soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE); // FIXME: Uniqe sound?
- }
- }
- }
+ return;
}
-}
-
-void onslaught_generator_ring_spawn(vector org)
-{
- modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25);
-}
-void onslaught_generator_ray_think()
-{
- self.nextthink = time + 0.05;
- if(self.count > 10)
+ if(IS_PLAYER(attacker))
+ if(time - ons_notification_time[self.team] > 10)
{
- self.think = SUB_Remove;
- return;
+ play2team(self.team, "onslaught/controlpoint_underattack.wav");
+ ons_notification_time[self.team] = time;
}
- if(self.count > 5)
- self.alpha -= 0.1;
+ self.health = self.health - damage;
+ if(self.owner.iscaptured)
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ else
+ WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / ONS_CP_THINKRATE));
+ self.pain_finished = time + 1;
+ // particles on every hit
+ pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
+ //sound on every hit
+ if (random() < 0.5)
+ sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
else
- self.alpha += 0.1;
+ sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
- self.scale += 0.2;
- self.count +=1;
-}
+ if (self.health < 0)
+ {
+ sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
-void onslaught_generator_ray_spawn(vector org)
-{
- entity e;
- e = spawn();
- setmodel(e, "models/onslaught/ons_ray.md3");
- setorigin(e, org);
- e.angles = randomvec() * 360;
- e.alpha = 0;
- e.scale = random() * 5 + 8;
- e.think = onslaught_generator_ray_think;
- e.nextthink = time + 0.05;
-}
+ PlayerScore_Add(attacker, SP_ONS_TAKES, 1);
+ PlayerScore_Add(attacker, SP_SCORE, 10);
-void onslaught_generator_shockwave_spawn(vector org)
-{
- shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5);
-}
+ self.owner.goalentity = world;
+ self.owner.islinked = false;
+ self.owner.iscaptured = false;
+ self.owner.team = 0;
+ self.owner.colormap = 1024;
-void onslaught_generator_damage_think()
-{
- if(self.owner.health < 0)
- {
- self.think = SUB_Remove;
- return;
+ WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
+
+ onslaught_updatelinks();
+
+ // Use targets now (somebody make sure this is in the right place..)
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
+
+ self.owner.waslinked = self.owner.islinked;
+ if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
+ setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad.md3");
+ //setsize(self, '-32 -32 0', '32 32 8');
+
+ remove(self);
}
- self.nextthink = time+0.1;
- // damaged fx (less probable the more damaged is the generator)
- if(random() < 0.9 - self.owner.health / self.owner.max_health)
- if(random() < 0.01)
- {
- Send_Effect("electro_ballexplode", self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
- sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
- }
- else
- Send_Effect("torch_small", self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
+ self.SendFlags |= CPSF_STATUS;
}
-void onslaught_generator_damage_spawn(entity gd_owner)
+void ons_ControlPoint_Icon_Think()
{
- entity e;
- e = spawn();
- e.owner = gd_owner;
- e.health = self.owner.health;
- setorigin(e, gd_owner.origin);
- e.think = onslaught_generator_damage_think;
- e.nextthink = time+1;
-}
+ entity oself;
+ self.nextthink = time + ONS_CP_THINKRATE;
-void onslaught_generator_deaththink()
-{
- vector org;
- float i;
+ if(autocvar_g_onslaught_cp_proxydecap)
+ {
+ int _enemy_count = 0;
+ int _friendly_count = 0;
+ float _dist;
+ entity _player;
+
+ FOR_EACH_PLAYER(_player)
+ {
+ if(!_player.deadflag)
+ {
+ _dist = vlen(_player.origin - self.origin);
+ if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
+ {
+ if(SAME_TEAM(_player, self))
+ ++_friendly_count;
+ else
+ ++_enemy_count;
+ }
+ }
+ }
- if (!self.count)
- self.count = 40;
+ _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
+ _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
- // White shockwave
- if(self.count==40||self.count==20)
- {
- onslaught_generator_ring_spawn(self.origin);
- sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
- }
+ self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
+ self.SendFlags |= CPSF_STATUS;
+ if(self.health <= 0)
+ {
+ ons_ControlPoint_Icon_Damage(self, self, 1, 0, self.origin, '0 0 0');
+ return;
+ }
+ }
- // Throw some gibs
- if(random() < 0.3)
+ if (time > self.pain_finished + 5)
{
- i = random();
- if(i < 0.3)
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, true);
- else if(i > 0.7)
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, true);
- else
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, true);
+ if(self.health < self.max_health)
+ {
+ self.health = self.health + self.count;
+ if (self.health >= self.max_health)
+ self.health = self.max_health;
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ }
}
- // Spawn fire balls
- for(i=0;i < 10;++i)
+ if(self.owner.islinked != self.owner.waslinked)
{
- org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
- Send_Effect("onslaught_generator_gib_explode", org, '0 0 0', 1);
- }
+ // unteam the spawnpoint if needed
+ int t = self.owner.team;
+ if(!self.owner.islinked)
+ self.owner.team = 0;
- // Short explosion sound + small explosion
- if(random() < 0.25)
- {
- te_explosion(self.origin);
- sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
- }
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
- // Particles
- org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
- Send_Effect("onslaught_generator_smallexplosion", org, '0 0 0', 1);
+ self.owner.team = t;
- // rays
- if(random() > 0.25 )
- {
- onslaught_generator_ray_spawn(self.origin);
+ self.owner.waslinked = self.owner.islinked;
}
- // Final explosion
- if(self.count==1)
+ // damaged fx
+ if(random() < 0.6 - self.health / self.max_health)
{
- org = self.origin;
- te_explosion(org);
- onslaught_generator_shockwave_spawn(org);
- Send_Effect("onslaught_generator_finalexplosion", org, '0 0 0', 1);
- sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- }
- else
- self.nextthink = time + 0.05;
+ Send_Effect("electricity_sparks", self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
- self.count = self.count - 1;
+ if(random() > 0.8)
+ sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
+ else if (random() > 0.5)
+ sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
+ }
}
-void onslaught_generator_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void ons_ControlPoint_Icon_BuildThink()
{
- float i;
- if (damage <= 0)
- return;
- if(warmup_stage)
+ entity oself;
+ int a;
+
+ self.nextthink = time + ONS_CP_THINKRATE;
+
+ // only do this if there is power
+ a = ons_ControlPoint_CanBeLinked(self.owner, self.owner.team);
+ if(!a)
return;
- if (attacker != self)
+
+ self.health = self.health + self.count;
+
+ self.SendFlags |= CPSF_STATUS;
+
+ if (self.health >= self.max_health)
{
- if (self.isshielded)
- {
- // this is protected by a shield, so ignore the damage
- if (time > self.pain_finished)
- if (IS_PLAYER(attacker))
- {
- play2(attacker, "onslaught/damageblockedbyshield.wav");
- self.pain_finished = time + 1;
- }
- return;
- }
- if (time > self.pain_finished)
- {
- self.pain_finished = time + 10;
- bprint(Team_ColoredFullName(self.team), " generator under attack!\n");
- play2team(self.team, "onslaught/generator_underattack.wav");
- }
- }
- self.health = self.health - damage;
- WaypointSprite_UpdateHealth(self.sprite, self.health);
- // choose an animation frame based on health
- self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
- // see if the generator is still functional, or dying
- if (self.health > 0)
- {
-#ifdef ONSLAUGHT_SPAM
- float h, lh;
- lh = ceil(self.lasthealth / 100) * 100;
- h = ceil(self.health / 100) * 100;
- if(lh != h)
- bprint(Team_ColoredFullName(self.team), " generator has less than ", ftos(h), " health remaining\n");
-#endif
- self.lasthealth = self.health;
- }
- else if (!warmup_stage)
- {
- if (attacker == self)
- bprint(Team_ColoredFullName(self.team), " generator spontaneously exploded due to overtime!\n");
- else
+ self.health = self.max_health;
+ self.count = autocvar_g_onslaught_cp_regen * ONS_CP_THINKRATE; // slow repair rate from now on
+ self.think = ons_ControlPoint_Icon_Think;
+ sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
+ self.owner.iscaptured = true;
+ self.solid = SOLID_BBOX;
+
+ Send_Effect(sprintf("%s_cap", Static_Team_ColorName_Lower(self.owner.team)), self.owner.origin, '0 0 0', 1);
+
+ WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+
+ if(IS_PLAYER(self.owner.ons_toucher))
{
- string t;
- t = Team_ColoredFullName(attacker.team);
- bprint(Team_ColoredFullName(self.team), " generator destroyed by ", t, "!\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ONSLAUGHT_CAPTURE, self.owner.ons_toucher.netname, self.owner.message);
+ Send_Notification(NOTIF_ALL_EXCEPT, self.owner.ons_toucher, MSG_CENTER, APP_TEAM_ENT_4(self.owner.ons_toucher, CENTER_ONS_CAPTURE_), self.owner.message);
+ Send_Notification(NOTIF_ONE, self.owner.ons_toucher, MSG_CENTER, CENTER_ONS_CAPTURE, self.owner.message);
+ PlayerScore_Add(self.owner.ons_toucher, SP_ONS_CAPS, 1);
+ PlayerTeamScore_AddScore(self.owner.ons_toucher, 10);
}
- self.iscaptured = false;
- self.islinked = false;
- self.isshielded = false;
- self.takedamage = DAMAGE_NO; // can't be hurt anymore
- self.event_damage = func_null; // won't do anything if hurt
- self.count = 0; // reset counter
- self.think = onslaught_generator_deaththink; // explosion sequence
- self.nextthink = time; // start exploding immediately
- self.think(); // do the first explosion now
- WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ self.owner.ons_toucher = world;
onslaught_updatelinks();
- }
- if(self.health <= 0)
- setmodel(self, "models/onslaught/generator_dead.md3");
- else if(self.health < self.max_health * 0.10)
- setmodel(self, "models/onslaught/generator_dmg9.md3");
- else if(self.health < self.max_health * 0.20)
- setmodel(self, "models/onslaught/generator_dmg8.md3");
- else if(self.health < self.max_health * 0.30)
- setmodel(self, "models/onslaught/generator_dmg7.md3");
- else if(self.health < self.max_health * 0.40)
- setmodel(self, "models/onslaught/generator_dmg6.md3");
- else if(self.health < self.max_health * 0.50)
- setmodel(self, "models/onslaught/generator_dmg5.md3");
- else if(self.health < self.max_health * 0.60)
- setmodel(self, "models/onslaught/generator_dmg4.md3");
- else if(self.health < self.max_health * 0.70)
- setmodel(self, "models/onslaught/generator_dmg3.md3");
- else if(self.health < self.max_health * 0.80)
- setmodel(self, "models/onslaught/generator_dmg2.md3");
- else if(self.health < self.max_health * 0.90)
- setmodel(self, "models/onslaught/generator_dmg1.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
-
- // Throw some flaming gibs on damage, more damage = more chance for gib
- if(random() < damage/220)
- {
- sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- i = random();
- if(i < 0.3)
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, true);
- else if(i > 0.7)
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib2.md3", 5, true);
- else
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib3.md3", 5, true);
- }
- else
- {
- // particles on every hit
- Send_Effect("sparks", hitloc, force * -1, 1);
+ // Use targets now (somebody make sure this is in the right place..)
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
- //sound on every hit
- if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
- else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
+ self.SendFlags |= CPSF_SETUP;
}
+ if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
+ setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad2.md3");
- //throw some gibs on damage
- if(random() < damage/200+0.2)
- if(random() < 0.5)
- ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, false);
+ if(random() < 0.9 - self.health / self.max_health)
+ Send_Effect("rage", self.origin + 10 * randomvec(), '0 0 -1', 1);
}
-// update links after a delay
-void onslaught_generator_delayed()
+void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
{
- onslaught_updatelinks();
- // now begin normal thinking
- self.think = onslaught_generator_think;
- self.nextthink = time;
-}
+ entity e = spawn();
-string onslaught_generator_waypointsprite_for_team(entity e, float t)
-{
- if(t == e.team)
- {
- if(e.team == NUM_TEAM_1)
- return "ons-gen-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-gen-blue";
- }
- if(e.isshielded)
- return "ons-gen-shielded";
- if(e.team == NUM_TEAM_1)
- return "ons-gen-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-gen-blue";
- return "";
-}
+ setsize(e, CPICON_MIN, CPICON_MAX);
+ setorigin(e, cp.origin + CPICON_OFFSET);
-void onslaught_generator_updatesprite(entity e)
-{
- string s1, s2, s3;
- s1 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_1);
- s2 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_2);
- s3 = onslaught_generator_waypointsprite_for_team(e, -1);
- WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+ e.classname = "onslaught_controlpoint_icon";
+ e.owner = cp;
+ e.max_health = autocvar_g_onslaught_cp_health;
+ e.health = autocvar_g_onslaught_cp_buildhealth;
+ e.solid = SOLID_NOT;
+ e.takedamage = DAMAGE_AIM;
+ e.bot_attack = true;
+ e.event_damage = ons_ControlPoint_Icon_Damage;
+ e.team = player.team;
+ e.colormap = 1024 + (e.team - 1) * 17;
+ e.count = (e.max_health - e.health) * ONS_CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
- if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
- {
- e.lastteam = e.team + 2;
- e.lastshielded = e.isshielded;
- if(e.lastshielded)
- {
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, false));
- else
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
- }
- else
- {
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, false));
- else
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
- }
- WaypointSprite_Ping(e.sprite);
- }
+ sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
+
+ cp.goalentity = e;
+ cp.team = e.team;
+ cp.colormap = e.colormap;
+
+ Send_Effect(sprintf("%sflag_touch", Static_Team_ColorName_Lower(player.team)), e.origin, '0 0 0', 1);
+
+ WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / ONS_CP_THINKRATE));
+ WaypointSprite_UpdateRule(cp.sprite,cp.team,SPRITERULE_TEAMPLAY);
+ cp.sprite.SendFlags |= 16;
+
+ onslaught_controlpoint_icon_link(e, ons_ControlPoint_Icon_BuildThink);
}
-string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
+string ons_ControlPoint_Waypoint(entity e)
{
- float a;
- if(t != -1)
+ if(e.team)
{
- a = onslaught_controlpoint_attackable(e, t);
- if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-atck-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-atck-blue";
- else
- return "ons-cp-atck-neut";
- }
- else if(a == -2) // DEFEND THIS ONE NOW
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-dfnd-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-dfnd-blue";
- }
- else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-blue";
- }
- else if(a == 2) // touch it
- return "ons-cp-neut";
+ int a = ons_ControlPoint_Attackable(e, e.team);
+
+ if(a == -2) { return "ons-cp-dfnd"; } // defend now
+ if(a == -1 || a == 1 || a == 2) { return "ons-cp"; } // touch
+ if(a == 3 || a == 4) { return "ons-cp-atck"; } // attack
}
else
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-blue";
- else
- return "ons-cp-neut";
- }
+ return "ons-cp";
+
return "";
}
-void onslaught_controlpoint_updatesprite(entity e)
+void ons_ControlPoint_UpdateSprite(entity e)
{
- string s1, s2, s3;
- s1 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_1);
- s2 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_2);
- s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
- WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+ string s1;
+ s1 = ons_ControlPoint_Waypoint(e);
+ WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
- float sh;
- sh = !(onslaught_controlpoint_can_be_linked(e, NUM_TEAM_1) || onslaught_controlpoint_can_be_linked(e, NUM_TEAM_2));
+ bool sh;
+ sh = !(ons_ControlPoint_CanBeLinked(e, NUM_TEAM_1) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_2) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_3) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_4));
if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
{
}
if(e.lastshielded)
{
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
+ if(e.team)
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, 0.5 * colormapPaletteColor(e.team - 1, false));
else
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
}
else
{
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
+ if(e.team)
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, false));
else
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
}
}
-void onslaught_generator_reset()
+void ons_ControlPoint_Touch()
{
- self.team = self.team_saved;
- self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
- self.takedamage = DAMAGE_AIM;
- self.bot_attack = true;
- self.iscaptured = true;
- self.islinked = true;
- self.isshielded = true;
- self.enemy.solid = SOLID_NOT;
- self.think = onslaught_generator_delayed;
- self.nextthink = time + 0.2;
- setmodel(self, "models/onslaught/generator.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
+ entity toucher = other;
+ int attackable;
+
+ if(IS_VEHICLE(toucher) && toucher.owner)
+ if(autocvar_g_onslaught_allow_vehicle_touch)
+ toucher = toucher.owner;
+ else
+ return;
+
+ if(!IS_PLAYER(toucher)) { return; }
+ if(toucher.frozen) { return; }
+ if(toucher.deadflag != DEAD_NO) { return; }
- if(!self.noalign)
+ if ( SAME_TEAM(self,toucher) )
+ if ( self.iscaptured )
{
- setorigin(self, self.origin + '0 0 20');
- droptofloor();
+ if(time <= toucher.teleport_antispam)
+ Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT_ANTISPAM, rint(toucher.teleport_antispam - time));
+ else
+ Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT);
}
- WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.sprite, self.health);
-}
+ attackable = ons_ControlPoint_Attackable(self, toucher.team);
+ if(attackable != 2 && attackable != 4)
+ return;
+ // we've verified that this player has a legitimate claim to this point,
+ // so start building the captured point icon (which only captures this
+ // point if it successfully builds without being destroyed first)
+ ons_ControlPoint_Icon_Spawn(self, toucher);
-/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
- Base generator.
+ self.ons_toucher = toucher;
- spawnfunc_onslaught_link entities can target this.
+ onslaught_updatelinks();
+}
-keys:
-"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
- */
-void spawnfunc_onslaught_generator()
+void ons_ControlPoint_Think()
{
- if (!g_onslaught)
- {
- remove(self);
- return;
- }
-
- //entity e;
- precache_model("models/onslaught/generator.md3");
- precache_model("models/onslaught/generator_shield.md3");
- precache_model("models/onslaught/generator_dmg1.md3");
- precache_model("models/onslaught/generator_dmg2.md3");
- precache_model("models/onslaught/generator_dmg3.md3");
- precache_model("models/onslaught/generator_dmg4.md3");
- precache_model("models/onslaught/generator_dmg5.md3");
- precache_model("models/onslaught/generator_dmg6.md3");
- precache_model("models/onslaught/generator_dmg7.md3");
- precache_model("models/onslaught/generator_dmg8.md3");
- precache_model("models/onslaught/generator_dmg9.md3");
- precache_model("models/onslaught/generator_dead.md3");
- precache_model("models/onslaught/shockwave.md3");
- precache_model("models/onslaught/shockwavetransring.md3");
- precache_model("models/onslaught/gen_gib1.md3");
- precache_model("models/onslaught/gen_gib2.md3");
- precache_model("models/onslaught/gen_gib3.md3");
- precache_model("models/onslaught/ons_ray.md3");
- precache_sound("onslaught/generator_decay.wav");
- precache_sound("weapons/grenade_impact.wav");
- precache_sound("weapons/rocket_impact.wav");
- precache_sound("onslaught/generator_underattack.wav");
- precache_sound("onslaught/shockwave.wav");
- precache_sound("onslaught/ons_hit1.wav");
- precache_sound("onslaught/ons_hit2.wav");
- precache_sound("onslaught/electricity_explode.wav");
- if (!self.team)
- objerror("team must be set");
-
- if(self.team == NUM_TEAM_1)
- ons_red_generator = self;
+ self.nextthink = time + ONS_CP_THINKRATE;
+ CSQCMODEL_AUTOUPDATE();
+}
- if(self.team == NUM_TEAM_2)
- ons_blue_generator = self;
+void ons_ControlPoint_Reset()
+{
+ if(self.goalentity)
+ remove(self.goalentity);
- self.team_saved = self.team;
- self.colormap = 1024 + (self.team - 1) * 17;
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_NONE;
- self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
- setmodel(self, "models/onslaught/generator.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
- setorigin(self, self.origin);
- self.takedamage = DAMAGE_AIM;
- self.bot_attack = true;
- self.event_damage = onslaught_generator_damage;
- self.iscaptured = true;
- self.islinked = true;
+ self.goalentity = world;
+ self.team = 0;
+ self.colormap = 1024;
+ self.iscaptured = false;
+ self.islinked = false;
self.isshielded = true;
- // helper entity that create fx when generator is damaged
- onslaught_generator_damage_spawn(self);
- // spawn shield model which indicates whether this can be damaged
- self.enemy = spawn();
- setattachment(self.enemy , self, "");
- self.enemy.classname = "onslaught_generator_shield";
- self.enemy.solid = SOLID_NOT;
- self.enemy.movetype = MOVETYPE_NONE;
- self.enemy.effects = EF_ADDITIVE;
- setmodel(self.enemy, "models/onslaught/generator_shield.md3");
- //setorigin(e, self.origin);
- self.enemy.colormap = self.colormap;
- self.enemy.team = self.team;
- //self.think = onslaught_generator_delayed;
- //self.nextthink = time + 0.2;
- InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST);
-
- WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
- WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
- WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.sprite, self.health);
+ self.think = ons_ControlPoint_Think;
+ self.ons_toucher = world;
+ self.nextthink = time + ONS_CP_THINKRATE;
+ setmodel_fixsize(self, "models/onslaught/controlpoint_pad.md3");
- waypoint_spawnforitem(self);
+ WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
- self.reset = onslaught_generator_reset;
+ activator = self;
+ SUB_UseTargets(); // to reset the structures, playerspawns etc.
+
+ CSQCMODEL_AUTOUPDATE();
}
-.float waslinked;
-.float cp_bob_spd;
-.vector cp_origin, cp_bob_origin, cp_bob_dmg;
+void ons_DelayedControlPoint_Setup(void)
+{
+ onslaught_updatelinks();
+
+ // captureshield setup
+ ons_CaptureShield_Spawn(self, false);
-float ons_notification_time_team1;
-float ons_notification_time_team2;
+ CSQCMODEL_AUTOINIT();
+}
-void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void ons_ControlPoint_Setup(entity cp)
{
- entity oself;
- float nag;
+ // declarations
+ self = cp; // for later usage with droptofloor()
+
+ // main setup
+ cp.ons_worldcpnext = ons_worldcplist; // link control point into ons_worldcplist
+ ons_worldcplist = cp;
+
+ cp.netname = "Control point";
+ cp.team = 0;
+ cp.solid = SOLID_BBOX;
+ cp.movetype = MOVETYPE_NONE;
+ cp.touch = ons_ControlPoint_Touch;
+ cp.think = ons_ControlPoint_Think;
+ cp.nextthink = time + ONS_CP_THINKRATE;
+ cp.reset = ons_ControlPoint_Reset;
+ cp.colormap = 1024;
+ cp.iscaptured = false;
+ cp.islinked = false;
+ cp.isshielded = true;
+
+ if(cp.message == "") { cp.message = "a"; }
+
+ // precache - TODO: clean up!
+ precache_model("models/onslaught/controlpoint_pad.md3");
+ precache_model("models/onslaught/controlpoint_pad2.md3");
+ precache_model("models/onslaught/controlpoint_shield.md3");
+ precache_model("models/onslaught/controlpoint_icon.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib1.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib2.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib4.md3");
+ precache_sound("onslaught/controlpoint_build.wav");
+ precache_sound("onslaught/controlpoint_built.wav");
+ precache_sound("weapons/grenade_impact.wav");
+ precache_sound("onslaught/damageblockedbyshield.wav");
+ precache_sound("onslaught/controlpoint_underattack.wav");
+ precache_sound("onslaught/ons_spark1.wav");
+ precache_sound("onslaught/ons_spark2.wav");
- if (damage <= 0)
- return;
- if (self.owner.isshielded)
+ // appearence
+ setmodel_fixsize(cp, "models/onslaught/controlpoint_pad.md3");
+
+ // control point placement
+ if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
{
- // this is protected by a shield, so ignore the damage
- if (time > self.pain_finished)
- if (IS_PLAYER(attacker))
- {
- play2(attacker, "onslaught/damageblockedbyshield.wav");
- self.pain_finished = time + 1;
- }
- return;
+ cp.noalign = true;
+ cp.movetype = MOVETYPE_NONE;
+ }
+ else // drop to floor, automatically find a platform and set that as spawn origin
+ {
+ setorigin(cp, cp.origin + '0 0 20');
+ cp.noalign = false;
+ self = cp;
+ droptofloor();
+ cp.movetype = MOVETYPE_TOSS;
}
- if (IS_PLAYER(attacker))
+ // waypointsprites
+ WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+ WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
+
+ InitializeEntity(cp, ons_DelayedControlPoint_Setup, INITPRIO_SETLOCATION);
+}
+
+
+// =========================
+// Main Generator Functions
+// =========================
+
+string ons_Generator_Waypoint(entity e)
+{
+ if(e.isshielded)
+ return "ons-gen-shielded";
+ return "ons-gen";
+}
+
+void ons_Generator_UpdateSprite(entity e)
+{
+ string s1 = ons_Generator_Waypoint(e);
+ WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
+
+ if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
{
- nag = false;
- if(self.team == NUM_TEAM_1)
+ e.lastteam = e.team + 2;
+ e.lastshielded = e.isshielded;
+ if(e.lastshielded)
{
- if(time - ons_notification_time_team1 > 10)
- {
- nag = true;
- ons_notification_time_team1 = time;
- }
+ if(e.team)
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, false));
+ else
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
}
- else if(self.team == NUM_TEAM_2)
+ else
{
- if(time - ons_notification_time_team2 > 10)
- {
- nag = true;
- ons_notification_time_team2 = time;
- }
+ if(e.team)
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, false));
+ else
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
}
- else
- nag = true;
-
- if(nag)
- play2team(self.team, "onslaught/controlpoint_underattack.wav");
+ WaypointSprite_Ping(e.sprite);
}
+}
- self.health = self.health - damage;
- if(self.owner.iscaptured)
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
- else
- WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / sys_frametime));
- self.pain_finished = time + 1;
- self.punchangle = (2 * randomvec() - '1 1 1') * 45;
- self.cp_bob_dmg_z = (2 * random() - 1) * 15;
- // colormod flash when shot
- self.colormod = '2 2 2';
- // particles on every hit
- Send_Effect("sparks", hitloc, force*-1, 1);
- //sound on every hit
- if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
- else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
+void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+ if(damage <= 0) { return; }
+ if(warmup_stage || gameover) { return; }
+ if(!round_handler_IsRoundStarted()) { return; }
- if (self.health < 0)
+ if (attacker != self)
{
- sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
- Send_Effect("rocket_explode", self.origin, '0 0 0', 1);
+ if (self.isshielded)
+ {
+ // this is protected by a shield, so ignore the damage
+ if (time > self.pain_finished)
+ if (IS_PLAYER(attacker))
+ {
+ play2(attacker, "onslaught/damageblockedbyshield.wav");
+ attacker.typehitsound += 1;
+ self.pain_finished = time + 1;
+ }
+ return;
+ }
+ if (time > self.pain_finished)
{
- string t;
- t = Team_ColoredFullName(attacker.team);
- bprint(Team_ColoredFullName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 25, "models/onslaught/controlpoint_icon_gib1.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
+ self.pain_finished = time + 10;
+ entity head;
+ FOR_EACH_REALPLAYER(head) if(SAME_TEAM(head, self)) { Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_GENERATOR_UNDERATTACK); }
+ play2team(self.team, "onslaught/generator_underattack.wav");
}
- self.owner.goalentity = world;
- self.owner.islinked = false;
- self.owner.iscaptured = false;
- self.owner.team = 0;
- self.owner.colormap = 1024;
+ }
+ self.health = self.health - damage;
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+ // choose an animation frame based on health
+ self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
+ // see if the generator is still functional, or dying
+ if (self.health > 0)
+ {
+ self.lasthealth = self.health;
+ }
+ else
+ {
+ if (attacker == self)
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_));
+ else
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_));
+ PlayerScore_Add(attacker, SP_SCORE, 100);
+ }
+ self.iscaptured = false;
+ self.islinked = false;
+ self.isshielded = false;
+ self.takedamage = DAMAGE_NO; // can't be hurt anymore
+ self.event_damage = func_null; // won't do anything if hurt
+ self.count = 0; // reset counter
+ self.think = func_null;
+ self.nextthink = 0;
+ //self.think(); // do the first explosion now
- WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
+ WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ WaypointSprite_Ping(self.sprite);
+ //WaypointSprite_Kill(self.sprite); // can't do this yet, code too poor
onslaught_updatelinks();
+ }
- // Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
-
-
- self.owner.waslinked = self.owner.islinked;
- if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
- setmodel(self.owner, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
+ // Throw some flaming gibs on damage, more damage = more chance for gib
+ if(random() < damage/220)
+ {
+ sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ }
+ else
+ {
+ // particles on every hit
+ Send_Effect("sparks", hitloc, force * -1, 1);
- remove(self);
+ //sound on every hit
+ if (random() < 0.5)
+ sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
+ else
+ sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
}
+
+ self.SendFlags |= GSF_STATUS;
}
-void onslaught_controlpoint_icon_think()
+void ons_GeneratorThink()
{
- entity oself;
- self.nextthink = time + sys_frametime;
-
- if(autocvar_g_onslaught_cp_proxydecap)
+ entity e;
+ self.nextthink = time + GEN_THINKRATE;
+ if (!gameover)
{
- float _enemy_count = 0;
- float _friendly_count = 0;
- float _dist;
- entity _player;
-
- FOR_EACH_PLAYER(_player)
+ if(!self.isshielded && self.wait < time)
{
- if(!_player.deadflag)
+ self.wait = time + 5;
+ FOR_EACH_REALPLAYER(e)
{
- _dist = vlen(_player.origin - self.origin);
- if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
- {
- if(_player.team == self.team)
- ++_friendly_count;
- else
- ++_enemy_count;
+ if(SAME_TEAM(e, self))
+ {
+ Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
+ soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
}
+ else
+ Send_Notification(NOTIF_ONE, e, MSG_CENTER, APP_TEAM_NUM_4(self.team, CENTER_ONS_NOTSHIELDED_));
}
}
+ }
+}
- _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
- _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
+void ons_GeneratorReset()
+{
+ self.team = self.team_saved;
+ self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
+ self.takedamage = DAMAGE_AIM;
+ self.bot_attack = true;
+ self.iscaptured = true;
+ self.islinked = true;
+ self.isshielded = true;
+ self.event_damage = ons_GeneratorDamage;
+ self.think = ons_GeneratorThink;
+ self.nextthink = time + GEN_THINKRATE;
- self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
- if(self.health <= 0)
- {
- onslaught_controlpoint_icon_damage(self, self, 1, 0, self.origin, '0 0 0');
- return;
- }
- }
+ Net_LinkEntity(self, false, 0, generator_send);
- if (time > self.pain_finished + 5)
+ self.SendFlags = GSF_SETUP; // just incase
+ self.SendFlags |= GSF_STATUS;
+
+ WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+ WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
+
+ onslaught_updatelinks();
+}
+
+void ons_DelayedGeneratorSetup()
+{
+ // bot waypoints
+ waypoint_spawnforitem_force(self, self.origin);
+ self.nearestwaypointtimeout = 0; // activate waypointing again
+ self.bot_basewaypoint = self.nearestwaypoint;
+
+ // captureshield setup
+ ons_CaptureShield_Spawn(self, true);
+
+ onslaught_updatelinks();
+
+ Net_LinkEntity(self, false, 0, generator_send);
+}
+
+
+void onslaught_generator_touch()
+{
+ if ( IS_PLAYER(other) )
+ if ( SAME_TEAM(self,other) )
+ if ( self.iscaptured )
{
- if(self.health < self.max_health)
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_TELEPORT);
+ }
+}
+
+void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
+{
+ // declarations
+ int teamnumber = gen.team;
+ self = gen; // for later usage with droptofloor()
+
+ // main setup
+ gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
+ ons_worldgeneratorlist = gen;
+
+ gen.netname = sprintf("%s generator", Team_ColoredFullName(teamnumber));
+ gen.classname = "onslaught_generator";
+ gen.solid = SOLID_BBOX;
+ gen.team_saved = teamnumber;
+ gen.movetype = MOVETYPE_NONE;
+ gen.lasthealth = gen.max_health = gen.health = autocvar_g_onslaught_gen_health;
+ gen.takedamage = DAMAGE_AIM;
+ gen.bot_attack = true;
+ gen.event_damage = ons_GeneratorDamage;
+ gen.reset = ons_GeneratorReset;
+ gen.think = ons_GeneratorThink;
+ gen.nextthink = time + GEN_THINKRATE;
+ gen.iscaptured = true;
+ gen.islinked = true;
+ gen.isshielded = true;
+ gen.touch = onslaught_generator_touch;
+
+ // precache - TODO: clean up!
+ precache_model("models/onslaught/generator_shield.md3");
+ precache_model("models/onslaught/gen_gib1.md3");
+ precache_model("models/onslaught/gen_gib2.md3");
+ precache_model("models/onslaught/gen_gib3.md3");
+ precache_sound("onslaught/generator_decay.wav");
+ precache_sound("weapons/grenade_impact.wav");
+ precache_sound("weapons/rocket_impact.wav");
+ precache_sound("onslaught/generator_underattack.wav");
+ precache_sound("onslaught/shockwave.wav");
+ precache_sound("onslaught/ons_hit1.wav");
+ precache_sound("onslaught/ons_hit2.wav");
+ precache_sound("onslaught/generator_underattack.wav");
+
+ // appearence
+ // model handled by CSQC
+ setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
+ setorigin(gen, (gen.origin + CPGEN_SPAWN_OFFSET));
+ gen.colormap = 1024 + (teamnumber - 1) * 17;
+
+ // generator placement
+ self = gen;
+ droptofloor();
+
+ // waypointsprites
+ WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+ WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
+ WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+
+ InitializeEntity(gen, ons_DelayedGeneratorSetup, INITPRIO_SETLOCATION);
+}
+
+
+// ===============
+// Round Handler
+// ===============
+
+int total_generators;
+void Onslaught_count_generators()
+{
+ entity e;
+ total_generators = redowned = blueowned = yellowowned = pinkowned = 0;
+ for(e = ons_worldgeneratorlist; e; e = e.ons_worldgeneratornext)
+ {
+ ++total_generators;
+ redowned += (e.team == NUM_TEAM_1 && e.health > 0);
+ blueowned += (e.team == NUM_TEAM_2 && e.health > 0);
+ yellowowned += (e.team == NUM_TEAM_3 && e.health > 0);
+ pinkowned += (e.team == NUM_TEAM_4 && e.health > 0);
+ }
+}
+
+int Onslaught_GetWinnerTeam()
+{
+ int winner_team = 0;
+ if(redowned > 0)
+ winner_team = NUM_TEAM_1;
+ if(blueowned > 0)
+ {
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_2;
+ }
+ if(yellowowned > 0)
+ {
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_3;
+ }
+ if(pinkowned > 0)
+ {
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_4;
+ }
+ if(winner_team)
+ return winner_team;
+ return -1; // no generators left?
+}
+
+#define ONS_OWNED_GENERATORS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0))
+#define ONS_OWNED_GENERATORS_OK() (ONS_OWNED_GENERATORS() > 1)
+bool Onslaught_CheckWinner()
+{
+ entity e;
+
+ if ((autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) || (round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0))
+ {
+ ons_stalemate = true;
+
+ if (!wpforenemy_announced)
{
- self.health = self.health + self.count;
- if (self.health >= self.max_health)
- self.health = self.max_health;
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
+ sound(world, CH_INFO, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NONE);
+
+ wpforenemy_announced = true;
+ }
+
+ entity tmp_entity; // temporary entity
+ float d;
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext) if(time >= tmp_entity.ons_overtime_damagedelay)
+ {
+ // tmp_entity.max_health / 300 gives 5 minutes of overtime.
+ // control points reduce the overtime duration.
+ d = 1;
+ for(e = ons_worldcplist; e; e = e.ons_worldcpnext)
+ {
+ if(DIFF_TEAM(e, tmp_entity))
+ if(e.islinked)
+ d = d + 1;
+ }
+
+ if(autocvar_g_campaign && autocvar__campaign_testrun)
+ d = d * tmp_entity.max_health;
+ else
+ d = d * tmp_entity.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
+
+ Damage(tmp_entity, tmp_entity, tmp_entity, d, DEATH_HURTTRIGGER, tmp_entity.origin, '0 0 0');
+
+ tmp_entity.sprite.SendFlags |= 16;
+
+ tmp_entity.ons_overtime_damagedelay = time + 1;
}
}
- if (self.health < self.max_health * 0.25)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
- else if (self.health < self.max_health * 0.50)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
- else if (self.health < self.max_health * 0.75)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
- else if (self.health < self.max_health * 0.90)
- setmodel(self, "models/onslaught/controlpoint_icon.md3");
- // colormod flash when shot
- self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+ else { wpforenemy_announced = false; ons_stalemate = false; }
- if(self.owner.islinked != self.owner.waslinked)
+ Onslaught_count_generators();
+
+ if(ONS_OWNED_GENERATORS_OK())
+ return 0;
+
+ int winner_team = Onslaught_GetWinnerTeam();
+
+ if(winner_team > 0)
{
- // unteam the spawnpoint if needed
- float t;
- t = self.owner.team;
- if(!self.owner.islinked)
- self.owner.team = 0;
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner_team, CENTER_ROUND_TEAM_WIN_));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner_team, INFO_ROUND_TEAM_WIN_));
+ TeamScore_AddToTeam(winner_team, ST_ONS_CAPS, +1);
+ }
+ else if(winner_team == -1)
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED);
+ }
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
+ ons_stalemate = false;
- self.owner.team = t;
+ play2all(sprintf("ctf/%s_capture.wav", Static_Team_ColorName_Lower(winner_team)));
- self.owner.waslinked = self.owner.islinked;
+ round_handler_Init(7, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
+
+ FOR_EACH_PLAYER(e)
+ {
+ e.ons_roundlost = true;
+ e.player_blocked = true;
+
+ nades_Clear(e);
+ }
+
+ return 1;
+}
+
+bool Onslaught_CheckPlayers()
+{
+ return 1;
+}
+
+void Onslaught_RoundStart()
+{
+ entity tmp_entity;
+ FOR_EACH_PLAYER(tmp_entity) { tmp_entity.player_blocked = false; }
+
+ for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
+ tmp_entity.sprite.SendFlags |= 16;
+
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
+ tmp_entity.sprite.SendFlags |= 16;
+}
+
+
+// ================
+// Bot player logic
+// ================
+
+// NOTE: LEGACY CODE, needs to be re-written!
+
+void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
+{
+ entity head;
+ float t, c;
+ int i;
+ bool needarmor = false, needweapons = false;
+
+ // Needs armor/health?
+ if(self.health<100)
+ needarmor = true;
+
+ // Needs weapons?
+ c = 0;
+ for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
+ {
+ // Find weapon
+ if(self.weapons & WepSet_FromWeapon(i))
+ if(++c>=4)
+ break;
+ }
+
+ if(c<4)
+ needweapons = true;
+
+ if(!needweapons && !needarmor)
+ return;
+
+ ons_debug(strcat(self.netname, " needs weapons ", ftos(needweapons) , "\n"));
+ ons_debug(strcat(self.netname, " needs armor ", ftos(needarmor) , "\n"));
+
+ // See what is around
+ head = findchainfloat(bot_pickup, true);
+ while (head)
+ {
+ // gather health and armor only
+ if (head.solid)
+ if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
+ if (vlen(head.origin - org) < sradius)
+ {
+ t = head.bot_pickupevalfunc(self, head);
+ if (t > 0)
+ navigation_routerating(head, t * ratingscale, 500);
+ }
+ head = head.chain;
}
+}
+
+void havocbot_role_ons_setrole(entity bot, int role)
+{
+ ons_debug(strcat(bot.netname," switched to "));
+ switch(role)
+ {
+ case HAVOCBOT_ONS_ROLE_DEFENSE:
+ ons_debug("defense");
+ bot.havocbot_role = havocbot_role_ons_defense;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
+ bot.havocbot_role_timeout = 0;
+ break;
+ case HAVOCBOT_ONS_ROLE_ASSISTANT:
+ ons_debug("assistant");
+ bot.havocbot_role = havocbot_role_ons_assistant;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
+ bot.havocbot_role_timeout = 0;
+ break;
+ case HAVOCBOT_ONS_ROLE_OFFENSE:
+ ons_debug("offense");
+ bot.havocbot_role = havocbot_role_ons_offense;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
+ bot.havocbot_role_timeout = 0;
+ break;
+ }
+ ons_debug("\n");
+}
+
+int havocbot_ons_teamcount(entity bot, int role)
+{
+ int c = 0;
+ entity head;
+
+ FOR_EACH_PLAYER(head)
+ if(SAME_TEAM(head, self))
+ if(head.havocbot_role_flags & role)
+ ++c;
+
+ return c;
+}
- if (self.punchangle.x > 0)
+void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
+{
+ entity cp, cp1, cp2, best, pl, wp;
+ float radius, bestvalue;
+ int c;
+ bool found;
+
+ // Filter control points
+ for(cp2 = ons_worldcplist; cp2; cp2 = cp2.ons_worldcpnext)
{
- self.punchangle_x = self.punchangle.x - 60 * sys_frametime;
- if (self.punchangle.x < 0)
- self.punchangle_x = 0;
+ cp2.wpcost = c = 0;
+ cp2.wpconsidered = false;
+
+ if(cp2.isshielded)
+ continue;
+
+ // Ignore owned controlpoints
+ if(!(cp2.isgenneighbor[self.team] || cp2.iscpneighbor[self.team]))
+ continue;
+
+ // Count team mates interested in this control point
+ // (easier and cleaner than keeping counters per cp and teams)
+ FOR_EACH_PLAYER(pl)
+ if(SAME_TEAM(pl, self))
+ if(pl.havocbot_role_flags & HAVOCBOT_ONS_ROLE_OFFENSE)
+ if(pl.havocbot_ons_target==cp2)
+ ++c;
+
+ // NOTE: probably decrease the cost of attackable control points
+ cp2.wpcost = c;
+ cp2.wpconsidered = true;
}
- else if (self.punchangle.x < 0)
+
+ // We'll consider only the best case
+ bestvalue = 99999999999;
+ cp = world;
+ for(cp1 = ons_worldcplist; cp1; cp1 = cp1.ons_worldcpnext)
{
- self.punchangle_x = self.punchangle.x + 60 * sys_frametime;
- if (self.punchangle.x > 0)
- self.punchangle_x = 0;
+ if (!cp1.wpconsidered)
+ continue;
+
+ if(cp1.wpcost<bestvalue)
+ {
+ bestvalue = cp1.wpcost;
+ cp = cp1;
+ self.havocbot_ons_target = cp1;
+ }
}
- if (self.punchangle.y > 0)
+ if (!cp)
+ return;
+
+ ons_debug(strcat(self.netname, " chose cp ranked ", ftos(bestvalue), "\n"));
+
+ if(cp.goalentity)
{
- self.punchangle_y = self.punchangle.y - 60 * sys_frametime;
- if (self.punchangle.y < 0)
- self.punchangle_y = 0;
+ // Should be attacked
+ // Rate waypoints near it
+ found = false;
+ best = world;
+ bestvalue = 99999999999;
+ for(radius=0; radius<1000 && !found; radius+=500)
+ {
+ for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
+ {
+ if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
+ if(wp.classname=="waypoint")
+ if(checkpvs(wp.origin,cp))
+ {
+ found = true;
+ if(wp.cnt<bestvalue)
+ {
+ best = wp;
+ bestvalue = wp.cnt;
+ }
+ }
+ }
+ }
+
+ if(best)
+ {
+ navigation_routerating(best, ratingscale, 10000);
+ best.cnt += 1;
+
+ self.havocbot_attack_time = 0;
+ if(checkpvs(self.view_ofs,cp))
+ if(checkpvs(self.view_ofs,best))
+ self.havocbot_attack_time = time + 2;
+ }
+ else
+ {
+ navigation_routerating(cp, ratingscale, 10000);
+ }
+ ons_debug(strcat(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n"));
}
- else if (self.punchangle.y < 0)
+ else
{
- self.punchangle_y = self.punchangle.y + 60 * sys_frametime;
- if (self.punchangle.y > 0)
- self.punchangle_y = 0;
+ // Should be touched
+ ons_debug(strcat(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n"));
+ found = false;
+
+ // Look for auto generated waypoint
+ if (!bot_waypoints_for_items)
+ for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
+ {
+ if(wp.classname=="waypoint")
+ {
+ navigation_routerating(wp, ratingscale, 10000);
+ found = true;
+ }
+ }
+
+ // Nothing found, rate the controlpoint itself
+ if (!found)
+ navigation_routerating(cp, ratingscale, 10000);
}
+}
- if (self.punchangle.z > 0)
+bool havocbot_goalrating_ons_generator_attack(float ratingscale)
+{
+ entity g, wp, bestwp;
+ bool found;
+ int best;
+
+ for(g = ons_worldgeneratorlist; g; g = g.ons_worldgeneratornext)
{
- self.punchangle_z = self.punchangle.z - 60 * sys_frametime;
- if (self.punchangle.z < 0)
- self.punchangle_z = 0;
+ if(SAME_TEAM(g, self) || g.isshielded)
+ continue;
+
+ // Should be attacked
+ // Rate waypoints near it
+ found = false;
+ bestwp = world;
+ best = 99999999999;
+
+ for(wp=findradius(g.origin,400); wp; wp=wp.chain)
+ {
+ if(wp.classname=="waypoint")
+ if(checkpvs(wp.origin,g))
+ {
+ found = true;
+ if(wp.cnt<best)
+ {
+ bestwp = wp;
+ best = wp.cnt;
+ }
+ }
+ }
+
+ if(bestwp)
+ {
+ ons_debug("waypoints found around generator\n");
+ navigation_routerating(bestwp, ratingscale, 10000);
+ bestwp.cnt += 1;
+
+ self.havocbot_attack_time = 0;
+ if(checkpvs(self.view_ofs,g))
+ if(checkpvs(self.view_ofs,bestwp))
+ self.havocbot_attack_time = time + 5;
+
+ return true;
+ }
+ else
+ {
+ ons_debug("generator found without waypoints around\n");
+ // if there aren't waypoints near the generator go straight to it
+ navigation_routerating(g, ratingscale, 10000);
+ self.havocbot_attack_time = 0;
+ return true;
+ }
}
- else if (self.punchangle.z < 0)
+ return false;
+}
+
+void havocbot_role_ons_offense()
+{
+ if(self.deadflag != DEAD_NO)
{
- self.punchangle_z = self.punchangle.z + 60 * sys_frametime;
- if (self.punchangle.z > 0)
- self.punchangle_z = 0;
+ self.havocbot_attack_time = 0;
+ havocbot_ons_reset_role(self);
+ return;
}
- self.angles_x = self.punchangle.x;
- self.angles_y = self.punchangle.y + self.mangle.y;
- self.angles_z = self.punchangle.z;
- self.mangle_y = self.mangle.y + 45 * sys_frametime;
+ // Set the role timeout if necessary
+ if (!self.havocbot_role_timeout)
+ self.havocbot_role_timeout = time + 120;
- self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
- self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime;
- if(self.cp_bob_dmg.z > 0)
- self.cp_bob_dmg_z = self.cp_bob_dmg.z - 3 * sys_frametime;
- else
- self.cp_bob_dmg_z = 0;
- setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
+ if (time > self.havocbot_role_timeout)
+ {
+ havocbot_ons_reset_role(self);
+ return;
+ }
- // damaged fx
- if(random() < 0.6 - self.health / self.max_health)
+ if(self.havocbot_attack_time>time)
+ return;
+
+ if (self.bot_strategytime < time)
{
- Send_Effect("electricity_sparks", self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
+ navigation_goalrating_start();
+ havocbot_goalrating_enemyplayers(20000, self.origin, 650);
+ if(!havocbot_goalrating_ons_generator_attack(20000))
+ havocbot_goalrating_ons_controlpoints_attack(20000);
+ havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
+ navigation_goalrating_end();
- if(random() > 0.8)
- sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
- else if (random() > 0.5)
- sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
+ self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+ }
+}
+
+void havocbot_role_ons_assistant()
+{
+ havocbot_ons_reset_role(self);
+}
+
+void havocbot_role_ons_defense()
+{
+ havocbot_ons_reset_role(self);
+}
+
+void havocbot_ons_reset_role(entity bot)
+{
+ entity head;
+ int c = 0;
+
+ if(self.deadflag != DEAD_NO)
+ return;
+
+ bot.havocbot_ons_target = world;
+
+ // TODO: Defend control points or generator if necessary
+
+ // if there is only me on the team switch to offense
+ c = 0;
+ FOR_EACH_PLAYER(head)
+ if(SAME_TEAM(head, self))
+ ++c;
+
+ if(c==1)
+ {
+ havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
+ return;
+ }
+
+ havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
+}
+
+
+/*
+ * Find control point or generator owned by the same team self which is nearest to pos
+ * if max_dist is positive, only control points within this range will be considered
+ */
+entity ons_Nearest_ControlPoint(vector pos, float max_dist)
+{
+ entity tmp_entity, closest_target = world;
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ if(max_dist <= 0 || vlen(tmp_entity.origin - pos) <= max_dist)
+ if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
+ closest_target = tmp_entity;
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(max_dist <= 0 || vlen(tmp_entity.origin - pos) < max_dist)
+ if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
+ closest_target = tmp_entity;
+ tmp_entity = tmp_entity.chain;
+ }
+
+ return closest_target;
+}
+
+/*
+ * Find control point or generator owned by the same team self which is nearest to pos
+ * if max_dist is positive, only control points within this range will be considered
+ * This function only check distances on the XY plane, disregarding Z
+ */
+entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
+{
+ entity tmp_entity, closest_target = world;
+ vector delta;
+ float smallest_distance = 0, distance;
+
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ while(tmp_entity)
+ {
+ delta = tmp_entity.origin - pos;
+ delta_z = 0;
+ distance = vlen(delta);
+
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ if(max_dist <= 0 || distance <= max_dist)
+ if(closest_target == world || distance <= smallest_distance )
+ {
+ closest_target = tmp_entity;
+ smallest_distance = distance;
+ }
+
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ delta = tmp_entity.origin - pos;
+ delta_z = 0;
+ distance = vlen(delta);
+
+ if(SAME_TEAM(tmp_entity, self))
+ if(max_dist <= 0 || distance <= max_dist)
+ if(closest_target == world || distance <= smallest_distance )
+ {
+ closest_target = tmp_entity;
+ smallest_distance = distance;
+ }
+
+ tmp_entity = tmp_entity.chain;
+ }
+
+ return closest_target;
+}
+/**
+ * find the number of control points and generators in the same team as self
+ */
+int ons_Count_SelfControlPoints()
+{
+ entity tmp_entity;
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ int n = 0;
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ n++;
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ n++;
+ tmp_entity = tmp_entity.chain;
+ }
+ return n;
+}
+
+/**
+ * Teleport player to a random position near tele_target
+ * if tele_effects is true, teleport sound+particles are created
+ * return false on failure
+ */
+bool ons_Teleport(entity player, entity tele_target, float range, bool tele_effects)
+{
+ if ( !tele_target )
+ return false;
+
+ int i;
+ vector loc;
+ float theta;
+ for(i = 0; i < 16; ++i)
+ {
+ theta = random() * 2 * M_PI;
+ loc_y = sin(theta);
+ loc_x = cos(theta);
+ loc_z = 0;
+ loc *= random() * range;
+
+ loc += tele_target.origin + '0 0 128';
+
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, player);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(tele_target.origin, loc, MOVE_NOMONSTERS, tele_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ if ( tele_effects )
+ {
+ Send_Effect("teleport", player.origin, '0 0 0', 1);
+ sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+ }
+ setorigin(player, loc);
+ player.angles = '0 1 0' * ( theta * RAD2DEG + 180 );
+ makevectors(player.angles);
+ player.fixangle = true;
+ player.teleport_antispam = time + autocvar_g_onslaught_teleport_wait;
+
+ if ( tele_effects )
+ Send_Effect("teleport", player.origin + v_forward * 32, '0 0 0', 1);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// ==============
+// Hook Functions
+// ==============
+
+MUTATOR_HOOKFUNCTION(ons_ResetMap)
+{
+ FOR_EACH_PLAYER(self)
+ {
+ self.ons_roundlost = false;
+ self.ons_deathloc = '0 0 0';
+ PutClientInServer();
+ }
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(ons_RemovePlayer)
+{
+ self.ons_deathloc = '0 0 0';
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
+{
+ if(!round_handler_IsRoundStarted())
+ {
+ self.player_blocked = true;
+ return false;
+ }
+
+ entity l;
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+
+ if(ons_stalemate) { Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT); }
+
+ if ( autocvar_g_onslaught_spawn_choose )
+ if ( self.ons_spawn_by )
+ if ( ons_Teleport(self,self.ons_spawn_by,autocvar_g_onslaught_teleport_radius,false) )
+ {
+ self.ons_spawn_by = world;
+ return false;
+ }
+
+ if(autocvar_g_onslaught_spawn_at_controlpoints)
+ if(random() <= autocvar_g_onslaught_spawn_at_controlpoints_chance)
+ {
+ float random_target = autocvar_g_onslaught_spawn_at_controlpoints_random;
+ entity tmp_entity, closest_target = world;
+ vector spawn_loc = self.ons_deathloc;
+
+ // new joining player or round reset, don't bother checking
+ if(spawn_loc == '0 0 0') { return false; }
+
+ if(random_target) { RandomSelection_Init(); }
+
+ for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(random_target)
+ RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
+ else if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
+ closest_target = tmp_entity;
+ }
+
+ if(random_target) { closest_target = RandomSelection_chosen_ent; }
+
+ if(closest_target)
+ {
+ float i;
+ vector loc;
+ for(i = 0; i < 10; ++i)
+ {
+ loc = closest_target.origin + '0 0 96';
+ loc += ('0 1 0' * random()) * 128;
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ setorigin(self, loc);
+ self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ if(autocvar_g_onslaught_spawn_at_generator)
+ if(random() <= autocvar_g_onslaught_spawn_at_generator_chance)
+ {
+ float random_target = autocvar_g_onslaught_spawn_at_generator_random;
+ entity tmp_entity, closest_target = world;
+ vector spawn_loc = self.ons_deathloc;
+
+ // new joining player or round reset, don't bother checking
+ if(spawn_loc == '0 0 0') { return false; }
+
+ if(random_target) { RandomSelection_Init(); }
+
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
+ {
+ if(random_target)
+ RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
+ else
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
+ closest_target = tmp_entity;
+ }
+ }
+
+ if(random_target) { closest_target = RandomSelection_chosen_ent; }
+
+ if(closest_target)
+ {
+ float i;
+ vector loc;
+ for(i = 0; i < 10; ++i)
+ {
+ loc = closest_target.origin + '0 0 128';
+ loc += ('0 1 0' * random()) * 256;
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ setorigin(self, loc);
+ self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(ons_PlayerDies)
+{
+ frag_target.ons_deathloc = frag_target.origin;
+ entity l;
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+
+ if ( autocvar_g_onslaught_spawn_choose )
+ if ( ons_Count_SelfControlPoints() > 1 )
+ stuffcmd(self, "qc_cmd_cl hud clickradar\n");
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(ons_MonsterThink)
+{
+ entity e = find(world, targetname, self.target);
+ if (e != world)
+ self.team = e.team;
+
+ return false;
+}
+
+void ons_MonsterSpawn_Delayed()
+{
+ entity e, own = self.owner;
+
+ if(!own) { remove(self); return; }
+
+ if(own.targetname)
+ {
+ e = find(world, target, own.targetname);
+ if(e != world)
+ {
+ own.team = e.team;
+
+ activator = e;
+ own.use();
+ }
}
+
+ remove(self);
}
-void onslaught_controlpoint_icon_buildthink()
+MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
{
- entity oself;
- float a;
+ entity e = spawn();
+ e.owner = self;
+ InitializeEntity(e, ons_MonsterSpawn_Delayed, INITPRIO_FINDTARGET);
- self.nextthink = time + sys_frametime;
+ return false;
+}
- // only do this if there is power
- a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
- if(!a)
- return;
+void ons_TurretSpawn_Delayed()
+{
+ entity e, own = self.owner;
- self.health = self.health + self.count;
+ if(!own) { remove(self); return; }
- if (self.health >= self.max_health)
+ if(own.targetname)
{
- self.health = self.max_health;
- self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on
- self.think = onslaught_controlpoint_icon_think;
- sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
- bprint(Team_ColoredFullName(self.team), " captured ", self.owner.message, " control point\n");
- self.owner.iscaptured = true;
-
- WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
-
- onslaught_updatelinks();
+ e = find(world, target, own.targetname);
+ if(e != world)
+ {
+ own.team = e.team;
+ own.active = ACTIVE_NOT;
- // Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
- self.cp_origin = self.origin;
- self.cp_bob_origin = '0 0 0.1';
- self.cp_bob_spd = 0;
+ activator = e;
+ own.use();
+ }
}
- self.alpha = self.health / self.max_health;
- // colormod flash when shot
- self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
- if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
- setmodel(self.owner, "models/onslaught/controlpoint_pad2.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
- if(random() < 0.9 - self.health / self.max_health)
- Send_Effect("rage", self.origin + 10 * randomvec(), '0 0 -1', 1);
+ remove(self);
}
-void onslaught_controlpoint_touch()
+MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
{
- entity e;
- float a;
- if (!IS_PLAYER(other))
- return;
- a = onslaught_controlpoint_attackable(self, other.team);
- if(a != 2 && a != 4)
- return;
- // we've verified that this player has a legitimate claim to this point,
- // so start building the captured point icon (which only captures this
- // point if it successfully builds without being destroyed first)
- self.goalentity = e = spawn();
- e.classname = "onslaught_controlpoint_icon";
+ entity e = spawn();
e.owner = self;
- e.max_health = autocvar_g_onslaught_cp_health;
- e.health = autocvar_g_onslaught_cp_buildhealth;
- e.solid = SOLID_BBOX;
- e.movetype = MOVETYPE_NONE;
- setmodel(e, "models/onslaught/controlpoint_icon.md3");
- setsize(e, '-32 -32 -32', '32 32 32');
- setorigin(e, self.origin + '0 0 96');
- e.takedamage = DAMAGE_AIM;
- e.bot_attack = true;
- e.event_damage = onslaught_controlpoint_icon_damage;
- e.team = other.team;
- e.colormap = 1024 + (e.team - 1) * 17;
- e.think = onslaught_controlpoint_icon_buildthink;
- e.nextthink = time + sys_frametime;
- e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
- sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
- self.team = e.team;
- self.colormap = e.colormap;
- WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
- onslaught_updatelinks();
+ InitializeEntity(e, ons_TurretSpawn_Delayed, INITPRIO_FINDTARGET);
+
+ return false;
}
-void onslaught_controlpoint_think()
+MUTATOR_HOOKFUNCTION(ons_BotRoles)
{
- self.nextthink = time;
- CSQCMODEL_AUTOUPDATE();
+ havocbot_ons_reset_role(self);
+ return true;
}
-void onslaught_controlpoint_reset()
+MUTATOR_HOOKFUNCTION(ons_GetTeamCount)
{
- if(self.goalentity && self.goalentity != world)
- remove(self.goalentity);
- self.goalentity = world;
- self.team = 0;
- self.colormap = 1024;
- self.iscaptured = false;
- self.islinked = false;
- self.isshielded = true;
- self.enemy.solid = SOLID_NOT;
- self.enemy.colormap = self.colormap;
- self.think = onslaught_controlpoint_think;
- self.enemy.think = func_null;
- self.nextthink = time; // don't like func_null :P
- setmodel(self, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
-
- WaypointSprite_UpdateMaxHealth(self.sprite, 0);
-
- onslaught_updatelinks();
-
- activator = self;
- SUB_UseTargets(); // to reset the structures, playerspawns etc.
+ // onslaught is special
+ entity tmp_entity;
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
+ {
+ switch(tmp_entity.team)
+ {
+ case NUM_TEAM_1: c1 = 0; break;
+ case NUM_TEAM_2: c2 = 0; break;
+ case NUM_TEAM_3: c3 = 0; break;
+ case NUM_TEAM_4: c4 = 0; break;
+ }
+ }
- CSQCMODEL_AUTOUPDATE();
+ return true;
}
-/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
- Control point. Be sure to give this enough clearance so that the shootable part has room to exist
-
- This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
-
-keys:
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
-"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
-"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
- */
+MUTATOR_HOOKFUNCTION(ons_SpectateCopy)
+{
+ self.ons_roundlost = other.ons_roundlost; // make spectators see it too
+ return false;
+}
-void spawnfunc_onslaught_controlpoint()
+MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
{
- //entity e;
- if (!g_onslaught)
- {
- remove(self);
- return;
- }
- precache_model("models/onslaught/controlpoint_pad.md3");
- precache_model("models/onslaught/controlpoint_pad2.md3");
- precache_model("models/onslaught/controlpoint_shield.md3");
- precache_model("models/onslaught/controlpoint_icon.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
- precache_model("models/onslaught/controlpoint_icon_gib1.md3");
- precache_model("models/onslaught/controlpoint_icon_gib2.md3");
- precache_model("models/onslaught/controlpoint_icon_gib4.md3");
- precache_sound("onslaught/controlpoint_build.wav");
- precache_sound("onslaught/controlpoint_built.wav");
- precache_sound("weapons/grenade_impact.wav");
- precache_sound("onslaught/damageblockedbyshield.wav");
- precache_sound("onslaught/controlpoint_underattack.wav");
- precache_sound("onslaught/ons_spark1.wav");
- precache_sound("onslaught/ons_spark2.wav");
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return false;
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_NONE;
- setmodel(self, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
- if(!self.noalign)
+ if ( cmd_name == "ons_spawn" )
{
- setorigin(self, self.origin + '0 0 20');
- droptofloor();
- }
- self.touch = onslaught_controlpoint_touch;
- self.team = 0;
- self.colormap = 1024;
- self.iscaptured = false;
- self.islinked = false;
- self.isshielded = true;
+ vector pos = self.origin;
+ if(cmd_argc > 1)
+ pos_x = stof(argv(1));
+ if(cmd_argc > 2)
+ pos_y = stof(argv(2));
+ if(cmd_argc > 3)
+ pos_z = stof(argv(3));
- // spawn shield model which indicates whether this can be damaged
- self.enemy = spawn();
- self.enemy.classname = "onslaught_controlpoint_shield";
- self.enemy.solid = SOLID_NOT;
- self.enemy.movetype = MOVETYPE_NONE;
- self.enemy.effects = EF_ADDITIVE;
- setmodel(self.enemy , "models/onslaught/controlpoint_shield.md3");
+ if ( IS_PLAYER(self) )
+ {
+ if ( !self.frozen )
+ {
+ entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
- setattachment(self.enemy , self, "");
- //setsize(e, '-32 -32 0', '32 32 128');
+ if ( !source_point && self.health > 0 )
+ {
+ sprint(self, "\nYou need to be next to a control point\n");
+ return 1;
+ }
- //setorigin(e, self.origin);
- self.enemy.colormap = self.colormap;
- waypoint_spawnforitem(self);
+ entity closest_target = ons_Nearest_ControlPoint_2D(pos, autocvar_g_onslaught_click_radius);
- self.think = onslaught_controlpoint_think;
- self.nextthink = time;
+ if ( closest_target == world )
+ {
+ sprint(self, "\nNo control point found\n");
+ return 1;
+ }
- WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
- WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
+ if ( self.health <= 0 )
+ {
+ self.ons_spawn_by = closest_target;
+ self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
+ }
+ else
+ {
+ if ( source_point == closest_target )
+ {
+ sprint(self, "\nTeleporting to the same point\n");
+ return 1;
+ }
- onslaught_updatelinks();
+ if ( !ons_Teleport(self,closest_target,autocvar_g_onslaught_teleport_radius,true) )
+ sprint(self, "\nUnable to teleport there\n");
+ }
- self.reset = onslaught_controlpoint_reset;
+ return 1;
+ }
- CSQCMODEL_AUTOINIT();
-}
+ sprint(self, "\nNo teleportation for you\n");
+ }
-float onslaught_link_send(entity to, float sendflags)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
- WriteByte(MSG_ENTITY, sendflags);
- if(sendflags & 1)
- {
- WriteCoord(MSG_ENTITY, self.goalentity.origin.x);
- WriteCoord(MSG_ENTITY, self.goalentity.origin.y);
- WriteCoord(MSG_ENTITY, self.goalentity.origin.z);
- }
- if(sendflags & 2)
- {
- WriteCoord(MSG_ENTITY, self.enemy.origin.x);
- WriteCoord(MSG_ENTITY, self.enemy.origin.y);
- WriteCoord(MSG_ENTITY, self.enemy.origin.z);
- }
- if(sendflags & 4)
- {
- WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
+ return 1;
}
- return true;
+ return 0;
}
-void onslaught_link_checkupdate()
+MUTATOR_HOOKFUNCTION(ons_PlayerUseKey)
{
- // TODO check if the two sides have moved (currently they won't move anyway)
- float redpower, bluepower;
-
- redpower = bluepower = 0;
- if(self.goalentity.islinked)
- {
- if(self.goalentity.team == NUM_TEAM_1)
- redpower = 1;
- else if(self.goalentity.team == NUM_TEAM_2)
- bluepower = 1;
- }
- if(self.enemy.islinked)
- {
- if(self.enemy.team == NUM_TEAM_1)
- redpower = 2;
- else if(self.enemy.team == NUM_TEAM_2)
- bluepower = 2;
- }
-
- float cc;
- if(redpower == 1 && bluepower == 2)
- cc = (NUM_TEAM_1 - 1) * 0x01 + (NUM_TEAM_2 - 1) * 0x10;
- else if(redpower == 2 && bluepower == 1)
- cc = (NUM_TEAM_1 - 1) * 0x10 + (NUM_TEAM_2 - 1) * 0x01;
- else if(redpower)
- cc = (NUM_TEAM_1 - 1) * 0x11;
- else if(bluepower)
- cc = (NUM_TEAM_2 - 1) * 0x11;
- else
- cc = 0;
-
- //print(etos(self), " rp=", ftos(redpower), " bp=", ftos(bluepower), " ");
- //print("cc=", ftos(cc), "\n");
+ if(MUTATOR_RETURNVALUE || gameover) { return false; }
- if(cc != self.clientcolors)
+ if((time > self.teleport_antispam) && (self.deadflag == DEAD_NO) && !self.vehicle)
{
- self.clientcolors = cc;
- self.SendFlags |= 4;
+ entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
+ if ( source_point )
+ {
+ stuffcmd(self, "qc_cmd_cl hud clickradar\n");
+ return true;
+ }
}
- self.nextthink = time;
+ return false;
}
-void onslaught_link_delayed()
+MUTATOR_HOOKFUNCTION(ons_PlayHitsound)
{
- self.goalentity = find(world, targetname, self.target);
- self.enemy = find(world, targetname, self.target2);
- if (!self.goalentity)
- objerror("can not find target\n");
- if (!self.enemy)
- objerror("can not find target2\n");
- dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
- self.SendFlags |= 3;
- self.think = onslaught_link_checkupdate;
- self.nextthink = time;
+ return (frag_victim.classname == "onslaught_generator" && !frag_victim.isshielded)
+ || (frag_victim.classname == "onslaught_controlpoint_icon" && !frag_victim.owner.isshielded);
}
+// ==========
+// Spawnfuncs
+// ==========
+
/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
Link between control points.
*/
void spawnfunc_onslaught_link()
{
- if (!g_onslaught)
- {
- remove(self);
- return;
- }
+ if(!g_onslaught) { remove(self); return; }
+
if (self.target == "" || self.target2 == "")
objerror("target and target2 must be set\n");
- InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
- Net_LinkEntity(self, false, 0, onslaught_link_send);
-}
-MUTATOR_HOOKFUNCTION(ons_BuildMutatorsString)
-{
- ret_string = strcat(ret_string, ":ONS");
- return 0;
-}
+ self.ons_worldlinknext = ons_worldlinklist; // link into ons_worldlinklist
+ ons_worldlinklist = self;
-MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
-{
- ret_string = strcat(ret_string, ", Onslaught");
- return 0;
+ InitializeEntity(self, ons_DelayedLinkSetup, INITPRIO_FINDTARGET);
+ Net_LinkEntity(self, false, 0, ons_Link_Send);
}
-MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
-{
-
- /*
- float _neer_home = (random() > 0.5 ? true : false);
+/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
+ Control point. Be sure to give this enough clearance so that the shootable part has room to exist
- RandomSelection_Init();
+ This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
- if(self.team == NUM_TEAM_1)
- RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
+keys:
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
+"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
+ */
- if(self.team == NUM_TEAM_2)
- RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
+void spawnfunc_onslaught_controlpoint()
+{
+ if(!g_onslaught) { remove(self); return; }
- entity _cp = findchain(classname, "onslaught_controlpoint"):
- while _cp;
- {
- if(_cp.team == self.team)
- RandomSelection_Add(_cp, 0, string_null, 1, 1);
+ ons_ControlPoint_Setup(self);
+}
- _cp = _cp.chain;
- }
+/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
+ Base generator.
- if(RandomSelection_chosen_ent)
- {
- self.tur_head = RandomSelection_chosen_ent;
- spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND;
- }
- else if(self.team == spawn_spot.team)
- spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
+ spawnfunc_onslaught_link entities can target this.
- */
+keys:
+"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+ */
+void spawnfunc_onslaught_generator()
+{
+ if(!g_onslaught) { remove(self); return; }
+ if(!self.team) { objerror("team must be set"); }
- return 0;
+ ons_GeneratorSetup(self);
}
-MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
+// scoreboard setup
+void ons_ScoreRules()
{
- if(!autocvar_g_onslaught_spawn_at_controlpoints)
- return 0;
-
- if(random() < 0.5) // 50/50 chane to use default spawnsystem.
- return 0;
-
- float _close_to_home = ((random() > 0.5) ? true : false);
- entity _best = world, _trg_gen = world;
- float _score, _best_score = MAX_SHOT_DISTANCE;
-
- RandomSelection_Init();
-
- if(self.team == NUM_TEAM_1)
- {
- if(!_close_to_home)
- _trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
- }
-
- if(self.team == NUM_TEAM_2)
- {
- if(_close_to_home)
- _trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
- }
-
- entity _cp = findchain(classname, "onslaught_controlpoint");
- while(_cp)
- {
- if(_cp.team == self.team)
- {
- _score = vlen(_trg_gen.origin - _cp.origin);
- if(_score < _best_score)
- {
- _best = _cp;
- _best_score = _score;
- }
- }
- _cp = _cp.chain;
- }
-
- vector _loc;
- float i;
- if(_best)
- {
- for(i = 0; i < 10; ++i)
- {
- _loc = _best.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
- tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
- if(trace_fraction == 1.0 && !trace_startsolid)
- {
- setorigin(self, _loc);
- self.angles = normalize(_loc - _best.origin) * RAD2DEG;
- return 0;
- }
- }
- }
- else
- {
- if(!autocvar_g_onslaught_spawn_at_generator)
- return 0;
-
- _trg_gen = ((self.team == NUM_TEAM_1) ? ons_red_generator : ons_blue_generator);
-
- for(i = 0; i < 10; ++i)
- {
- _loc = _trg_gen.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
- tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
- if(trace_fraction == 1.0 && !trace_startsolid)
- {
- setorigin(self, _loc);
- self.angles = normalize(_loc - _trg_gen.origin) * RAD2DEG;
- return 0;
- }
- }
- }
-
- return 0;
+ CheckAllowedTeams(world);
+ ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), SFL_SORT_PRIO_PRIMARY, 0, true);
+ ScoreInfo_SetLabel_TeamScore (ST_ONS_CAPS, "destroyed", SFL_SORT_PRIO_PRIMARY);
+ ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS, "caps", SFL_SORT_PRIO_SECONDARY);
+ ScoreInfo_SetLabel_PlayerScore(SP_ONS_TAKES, "takes", 0);
+ ScoreRules_basics_end();
}
-MUTATOR_HOOKFUNCTION(ons_MonsterThink)
+void ons_DelayedInit() // Do this check with a delay so we can wait for teams to be set up
{
- entity e = find(world, targetname, self.target);
- if (e != world)
- self.team = e.team;
+ ons_ScoreRules();
- return false;
+ round_handler_Spawn(Onslaught_CheckPlayers, Onslaught_CheckWinner, Onslaught_RoundStart);
+ round_handler_Init(5, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
}
-MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
+void ons_Initialize()
{
- entity e, ee = world;
+ precache_sound("ctf/red_capture.wav");
+ precache_sound("ctf/blue_capture.wav");
+ precache_sound("ctf/yellow_capture.wav");
+ precache_sound("ctf/pink_capture.wav");
- if(self.targetname)
- {
- e = find(world,target,self.targetname);
- if(e != world)
- {
- self.team = e.team;
- ee = e;
- }
- }
+ ons_captureshield_force = autocvar_g_onslaught_shield_force;
- if(ee)
- {
- activator = ee;
- self.use();
- }
+ addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
- return false;
+ InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
}
MUTATOR_DEFINITION(gamemode_onslaught)
{
- MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
- MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
+ MUTATOR_HOOK(reset_map_global, ons_ResetMap, CBC_ORDER_ANY);
+ MUTATOR_HOOK(MakePlayerObserver, ons_RemovePlayer, CBC_ORDER_ANY);
+ MUTATOR_HOOK(ClientDisconnect, ons_RemovePlayer, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerDies, ons_PlayerDies, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterMove, ons_MonsterThink, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterSpawn, ons_MonsterSpawn, CBC_ORDER_ANY);
- //MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
+ MUTATOR_HOOK(TurretSpawn, ons_TurretSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(HavocBot_ChooseRole, ons_BotRoles, CBC_ORDER_ANY);
+ MUTATOR_HOOK(GetTeamCount, ons_GetTeamCount, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SpectateCopy, ons_SpectateCopy, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SV_ParseClientCommand, ons_SV_ParseClientCommand, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerUseKey, ons_PlayerUseKey, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayHitsound, ons_PlayHitsound, CBC_ORDER_ANY);
MUTATOR_ONADD
{
if(time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
+ ons_Initialize();
+ }
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ons_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
}
MUTATOR_ONREMOVE
return -1;
}
- return 0;
+ return false;
}
--- /dev/null
+// these are needed since mutators are compiled last
+
+#ifdef SVQC
+
+.entity ons_toucher; // player who touched the control point
+
+// control point / generator constants
+const float ONS_CP_THINKRATE = 0.2;
+const float GEN_THINKRATE = 1;
+#define CPGEN_SPAWN_OFFSET ('0 0 1' * (PL_MAX_CONST.z - 13))
+const vector CPGEN_WAYPOINT_OFFSET = ('0 0 128');
+const vector CPICON_OFFSET = ('0 0 96');
+
+// list of generators on the map
+entity ons_worldgeneratorlist;
+.entity ons_worldgeneratornext;
+.entity ons_stalegeneratornext;
+
+// list of control points on the map
+entity ons_worldcplist;
+.entity ons_worldcpnext;
+.entity ons_stalecpnext;
+
+// list of links on the map
+entity ons_worldlinklist;
+.entity ons_worldlinknext;
+.entity ons_stalelinknext;
+
+// definitions
+.entity sprite;
+.string target2;
+.int iscaptured;
+.int islinked;
+.int isshielded;
+.float lasthealth;
+.int lastteam;
+.int lastshielded;
+.int lastcaptured;
+
+.bool waslinked;
+
+bool ons_stalemate;
+
+.float teleport_antispam;
+
+.bool ons_roundlost;
+
+// waypoint sprites
+.entity bot_basewaypoint; // generator waypointsprite
+
+.bool isgenneighbor[17];
+.bool iscpneighbor[17];
+float ons_notification_time[17];
+
+.float ons_overtime_damagedelay;
+
+.vector ons_deathloc;
+
+.entity ons_spawn_by;
+
+// declarations for functions used outside gamemode_onslaught.qc
+void ons_Generator_UpdateSprite(entity e);
+void ons_ControlPoint_UpdateSprite(entity e);
+bool ons_ControlPoint_Attackable(entity cp, int teamnumber);
+
+// CaptureShield: Prevent capturing or destroying control point/generator if it is not available yet
+float ons_captureshield_force; // push force of the shield
+
+// bot player logic
+const int HAVOCBOT_ONS_ROLE_NONE = 0;
+const int HAVOCBOT_ONS_ROLE_DEFENSE = 2;
+const int HAVOCBOT_ONS_ROLE_ASSISTANT = 4;
+const int HAVOCBOT_ONS_ROLE_OFFENSE = 8;
+
+.entity havocbot_ons_target;
+
+.int havocbot_role_flags;
+.float havocbot_attack_time;
+
+void havocbot_role_ons_defense();
+void havocbot_role_ons_offense();
+void havocbot_role_ons_assistant();
+
+void havocbot_ons_reset_role(entity bot);
+void havocbot_goalrating_items(float ratingscale, vector org, float sradius);
+void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius);
+
+// score rule declarations
+const int ST_ONS_CAPS = 1;
+const int SP_ONS_CAPS = 4;
+const int SP_ONS_TAKES = 6;
+
+#endif
#include "../../common/notifications.qh"
#include "../../common/deathtypes.qh"
#include "mutators_include.qh"
- #include "../tturrets/include/turrets_early.qh"
- #include "../../common/vehicles/sv_vehicles.qh"
+ #include "../../common/turrets/sv_turrets.qh"
+ #include "../../common/vehicles/all.qh"
#include "../campaign.qh"
#include "../../common/campaign_common.qh"
#include "../../common/mapinfo.qh"
#include "../round_handler.qh"
#include "../item_key.qh"
#include "../pathlib/pathlib.qh"
- #include "../tturrets/include/turrets.qh"
+ #include "../../common/vehicles/all.qh"
#endif
#include "../../common/mutators/base.qh"
#include "gamemode_invasion.qh"
#include "gamemode_race.qh"
#include "gamemode_cts.qh"
+#include "gamemode_onslaught.qh"
#include "mutator_dodging.qh"
#include "mutator_overkill.qh"
cl_client.qc
cl_impulse.qc
cl_player.qc
+controlpoint.qc
csqceffects.qc
ent_cs.qc
g_casings.qc
g_tetris.qc
g_violence.qc
g_world.qc
+generator.qc
ipban.qc
item_key.qc
mapvoting.qc
bot/havocbot/havocbot.qc
bot/havocbot/role_keyhunt.qc
-bot/havocbot/role_onslaught.qc
bot/havocbot/roles.qc
command/all.qc
../common/campaign_setup.qc
../common/effects.qc
../common/mapinfo.qc
-../common/monsters/all.qc
../common/monsters/spawn.qc
../common/monsters/sv_monsters.qc
../common/movetypes/include.qc
../common/triggers/include.qc
../common/urllib.qc
../common/util.qc
-../common/vehicles/vehicles_include.qc
../common/items/all.qc
+../common/monsters/all.qc
+../common/mutators/all.qc
+../common/vehicles/all.qc
+../common/weapons/all.qc // TODO
+../common/turrets/sv_turrets.qc
+../common/turrets/config.qc
+../common/turrets/util.qc
+../common/turrets/turrets.qc
+../common/turrets/checkpoint.qc
+../common/turrets/targettrigger.qc
../common/weapons/config.qc
-../common/weapons/all.qc // TODO
../csqcmodellib/sv_model.qc
#include "../common/mapinfo.qh"
#include "../common/util.qh"
-#include "../common/vehicles/sv_vehicles.qh"
+#include "../common/vehicles/all.qh"
#include "../common/weapons/all.qh"
#include "../csqcmodellib/sv_model.qh"
if(g_onslaught)
{
ActivateTeamplay();
+ fraglimit_override = autocvar_g_onslaught_point_limit;
have_team_spawns = -1; // request team spawns
MUTATOR_ADD(gamemode_onslaught);
}
+++ /dev/null
-#ifndef TURRETS_H
-#define TURRETS_H
-
-#ifdef TTURRETS_ENABLED
-
-// Include section.
-#include "../system/system_misc.qc" /// Assorted junk & jewls
-#include "../system/system_main.qc" /// And routines
-#include "../system/system_aimprocs.qc" /// Aiming realted stuff
-#include "../system/system_scoreprocs.qc" /// Target calssification
-#include "../system/system_damage.qc" /// Outch, they are hurting me! what should i do?
-
-// Non combat units
-#include "../units/unit_fusionreactor.qc" /// Supply unites that need it with power
-#include "../units/unit_targettrigger.qc" /// Hit me!
-#include "../units/unit_checkpoint.qc" /// Halfsmart pathing.
-
-// Combat units
-#include "../units/unit_plasma.qc" /// Basic energy cannon
-#include "../units/unit_mlrs.qc" /// Basic multibay RL
-#include "../units/unit_hellion.qc" /// Seeking missiles MLRS
-#include "../units/unit_flac.qc" /// anti missile turret
-#include "../units/unit_phaser.qc" /// ZzzapT
-#include "../units/unit_hk.qc" /// Hunter killers
-#include "../units/unit_machinegun.qc" /// whacka
-#include "../units/unit_tessla.qc" /// Chain lightning capabale turret
-#include "../units/unit_walker.qc" /// Moving minigun-rocket-meele err thing
-#include "../units/unit_ewheel.qc" /// A evil wheel. with guns on.
-//#include "../units/unit_repulsor.qc" /// Fires a wave that knocks foes back
-//#include "../units/unit_hive.qc" /// Swarm AI
-
-#endif // TTURRETS_ENABLED
-#endif
+++ /dev/null
-#ifndef TURRETS_EARLY_H
-#define TURRETS_EARLY_H
-
-// Comment out below to skip turrets
-#define TTURRETS_ENABLED
-
-#ifdef TTURRETS_ENABLED
-#ifdef SVQC
-//#message "with tZork turrets"
-
-float turret_count;
-
-vector real_origin(entity ent);
-
-/// Map time control over pain inflicted
-.float turret_scale_damage;
-/// Map time control targetting range
-.float turret_scale_range;
-/// Map time control refire
-.float turret_scale_refire;
-/// Map time control ammo held and recharged
-.float turret_scale_ammo;
-/// Map time control aim speed
-.float turret_scale_aim;
-/// Map time control health
-.float turret_scale_health;
-/// Map time control respawn time
-.float turret_scale_respawn;
-
-/// Used for cvar reloading
-.string cvar_basename;
-
-//.float spawnflags
-const float TSF_SUSPENDED = 1;
-/// Spawn a pillar model under the turret to make it look ok on uneven ground surfaces
-const float TSF_TERRAINBASE = 2;
-/// Disable builtin ammo regeneration
-const float TSF_NO_AMMO_REGEN = 4;
-/// Dont break path to chase enemys. will still fire at them if possible.
-const float TSF_NO_PATHBREAK = 8;
-/// Dont respawn
-const float TSL_NO_RESPAWN = 16;
-/// Let this turret roam when idle.
-const float TSL_ROAM = 32;
-
-/// target selection flags
-.float target_select_flags;
-/// target validatoin flags
-.float target_validate_flags;
-/// Dont select a target on its own.
-const float TFL_TARGETSELECT_NO = 2;
-/// Need line of sight
-const float TFL_TARGETSELECT_LOS = 4;
-/// Players are valid targets
-const float TFL_TARGETSELECT_PLAYERS = 8;
-/// Missiles are valid targets
-const float TFL_TARGETSELECT_MISSILES = 16;
-/// Responds to turret_trigger_target events
-const float TFL_TARGETSELECT_TRIGGERTARGET = 32;
-/// Angular limitations of turret head limits target selection
-const float TFL_TARGETSELECT_ANGLELIMITS = 64;
-/// Range limits apply in targetselection
-const float TFL_TARGETSELECT_RANGELIMTS = 128;
-/// DOnt select targets with a .team matching its own
-const float TFL_TARGETSELECT_TEAMCHECK = 256;
-/// Cant select targets on its own. needs to be triggerd or slaved.
-const float TFL_TARGETSELECT_NOBUILTIN = 512;
-/// TFL_TARGETSELECT_TEAMCHECK is inverted (selects only mebers of own .team)
-const float TFL_TARGETSELECT_OWNTEAM = 1024;
-/// Turrets aren't valid targets
-const float TFL_TARGETSELECT_NOTURRETS = 2048;
-/// Use feild of view
-const float TFL_TARGETSELECT_FOV = 4096;
-
-const float TFL_TARGETSELECT_MISSILESONLY = 8192;
-
-/// aim flags
-.float aim_flags;
-/// Dont aim.
-const float TFL_AIM_NO = 1;
-/// Go for ground, not direct hit, but only if target is on ground.
-const float TFL_AIM_GROUNDGROUND = 2;
-/// Try to predict target movement (does not account for gravity)
-const float TFL_AIM_LEAD = 4;
-/// Compensate for shot traveltime when lead
-const float TFL_AIM_SHOTTIMECOMPENSATE = 8;
-/// Try to do real prediction of targets z pos at impact.
-const float TFL_AIM_ZPREDICT = 16;
-/// Simply aim at target's current location
-const float TFL_AIM_SIMPLE = 32;
-
-/// track (turn and pitch head) flags
-.float track_flags;
-/// Dont move head
-const float TFL_TRACK_NO = 2;
-/// Pitch the head
-const float TFL_TRACK_PITCH = 4;
-/// Rotate the head
-const float TFL_TRACK_ROT = 8;
-
-/// How tracking is preformed
-.float track_type;
-/// Hard angle increments. Ugly for fast turning, best accuracy.
-const float TFL_TRACKTYPE_STEPMOTOR = 1;
-/// Smoth absolute movement. Looks ok, fair accuracy.
-const float TFL_TRACKTYPE_FLUIDPRECISE = 2;
-/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the fields below are set
-const float TFL_TRACKTYPE_FLUIDINERTIA = 3;
-/// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier
-.float track_accel_pitch;
-/// TFL_TRACKTYPE_FLUIDINERTIA: rotation multiplier
-.float track_accel_rot;
-/// TFL_TRACKTYPE_FLUIDINERTIA: Blendrate with old rotation (inertia simulation) 1 = only old, 0 = only new
-.float track_blendrate;
-
-/// How prefire check is preformed
-.float firecheck_flags;
-/// Dont kill the dead
-const float TFL_FIRECHECK_DEAD = 4;
-/// Range limits apply
-const float TFL_FIRECHECK_DISTANCES = 8;
-/// Line Of Sight needs to be clear
-const float TFL_FIRECHECK_LOS = 16;
-/// Consider distance inpactpoint<->aimspot
-const float TFL_FIRECHECK_AIMDIST = 32;
-/// Consider enemy origin<->impactpoint
-const float TFL_FIRECHECK_REALDIST = 64;
-/// Consider angular diff head<->aimspot
-const float TFL_FIRECHECK_ANGLEDIST = 128;
-/// (re)consider target.team<->self.team
-const float TFL_FIRECHECK_TEAMCECK = 256;
-/// Try to avoid friendly fire
-const float TFL_FIRECHECK_AFF = 512;
-/// Own .ammo needs to be >= then own .shot_dmg
-const float TFL_FIRECHECK_OWM_AMMO = 1024;
-/// Others ammo need to be < others .ammo_max
-const float TFL_FIRECHECK_OTHER_AMMO = 2048;
-/// Check own .attack_finished_single vs time
-const float TFL_FIRECHECK_REFIRE = 4096;
-/// Move the acctual target to aimspot before tracing impact (and back after)
-//#define TFL_FIRECHECK_VERIFIED 8192
-/// Dont do any chekcs
-const float TFL_FIRECHECK_NO = 16384;
-
-/// How shooting is done
-.float shoot_flags;
-/// Dont shoot
-const float TFL_SHOOT_NO = 64;
-/// Fire in vollys (partial implementation through .shot_volly)
-const float TFL_SHOOT_VOLLY = 2;
-/// Always do a full volly, even if target is lost or dead. (not implemented)
-const float TFL_SHOOT_VOLLYALWAYS = 4;
-/// Loop though all valid tarters, and hit them.
-const float TFL_SHOOT_HITALLVALID = 8;
-/// Fiering makes unit loose target (after volly is done, if in volly mode)
-const float TFL_SHOOT_CLEARTARGET = 16;
-///Custom shooting;
-const float TFL_SHOOT_CUSTOM = 32;
-
-/// Information aboute the units capabilities
-.float turrcaps_flags;
-/// No kown capabilities
-const float TFL_TURRCAPS_NONE = 0;
-/// Capable of sniping
-const float TFL_TURRCAPS_SNIPER = 2;
-/// Capable of splasdamage
-const float TFL_TURRCAPS_RADIUSDMG = 4;
-/// Has one or more cannons with zero shot traveltime
-const float TFL_TURRCAPS_HITSCAN = 8;
-/// More then one (type of) gun
-const float TFL_TURRCAPS_MULTIGUN = 16;
-/// Carries at least one guided weapon
-const float TFL_TURRCAPS_GUIDED = 32;
-/// At least one gun fiers slow projectiles
-const float TFL_TURRCAPS_SLOWPROJ = 64;
-/// At least one gun fiers medium speed projectiles
-const float TFL_TURRCAPS_MEDPROJ = 128;
-/// At least one gun fiers fast projectiles
-const float TFL_TURRCAPS_FASTPROJ = 256;
-/// At least one gun capable of damaging players
-const float TFL_TURRCAPS_PLAYERKILL = 512;
-/// At least one gun that can shoot town missiles
-const float TFL_TURRCAPS_MISSILEKILL = 1024;
-/// Has support capabilities. powerplants and sutch.
-const float TFL_TURRCAPS_SUPPORT = 2048;
-/// Proveides at least one type of ammmo
-const float TFL_TURRCAPS_AMMOSOURCE = 4096;
-/// Can recive targets from external sources
-const float TFL_TURRCAPS_RECIVETARGETS = 8192;
-/// Capable of self-transport
-const float TFL_TURRCAPS_MOVE = 16384;
-/// Will roam arround even if not chasing anyting
-const float TFL_TURRCAPS_ROAM = 32768;
-const float TFL_TURRCAPS_ISTURRET = 65536;
-
-/// Ammo types needed and/or provided
-//.float ammo_flags;
-#define ammo_flags currentammo
-/// Has and needs no ammo
-const float TFL_AMMO_NONE = 64;
-/// Uses power
-const float TFL_AMMO_ENERGY = 2;
-/// Uses bullets
-const float TFL_AMMO_BULLETS = 4;
-/// Uses explosives
-const float TFL_AMMO_ROCKETS = 8;
-/// Regenerates ammo on its own
-const float TFL_AMMO_RECHARGE = 16;
-/// Can recive ammo from others
-const float TFL_AMMO_RECIVE = 32;
-
-/// How incomming damage is handeld
-.float damage_flags;
-/// Cant be hurt
-const float TFL_DMG_NO = 256;
-/// Can be damaged
-const float TFL_DMG_YES = 2;
-/// Can be damaged by teammates
-const float TFL_DMG_TAKEFROMTEAM = 4;
-/// Traget attackers
-const float TFL_DMG_RETALIATE = 8;
-/// Target attackers, even is on own team
-const float TFL_DMG_RETALIATEONTEAM = 16;
-/// Loses target when damaged
-const float TFL_DMG_TARGETLOSS = 32;
-/// Reciving damage trows off aim (pointless atm, aim gets recalculated to fast). not implemented.
-const float TFL_DMG_AIMSHAKE = 64;
-/// Reciving damage slaps the head arround
-const float TFL_DMG_HEADSHAKE = 128;
-/// Die and stay dead.
-const float TFL_DMG_DEATH_NORESPAWN = 256;
-
-// Spawnflags
-/// Spawn in teambased modes
-const float TFL_SPAWN_TEAM = 2;
-/// Spawn in FFA modes
-const float TFL_SPAWN_FFA = 4;
-
-
-/*
-* Fields used by turrets
-*/
-/// Turrets internal ai speed
-.float ticrate;
-
-/// Where to point the when no target
-.vector idle_aim;
-
-/// Top part of turret
-.entity tur_head;
-
-/// Start/respawn health
-.float tur_health;
-
-/// Defend this entity (or ratehr this entitys position)
-.entity tur_defend;
-
-/// and shoot from here. (can be non constant, think MLRS)
-.vector tur_shotorg;
-
-/// Aim at this spot
-.vector tur_aimpos;
-
-/// Predicted time the round will impact
-.float tur_impacttime;
-
-// Predicted place the round will impact
-//.vector tur_impactpoint; // unused
-
-/// What entity the aimtrace hit, if any.
-.entity tur_impactent;
-
-/// Distance to enemy
-.float tur_dist_enemy;
-
-/// Distance to aimspot
-.float tur_dist_aimpos;
-
-/// Distance impact<->aim
-.float tur_dist_impact_to_aimpos;
-
-/// Decresment counter form .shot_volly to 0.
-.float volly_counter;
-
-/*
-* Projectile/missile. its up to the individual turret implementation to
-** deal the damage, blow upp the missile or whatever.
-*/
-/// Track then refireing is possible
-//.float attack_finished; = attack_finished_single
-/// Shoot this often
-.float shot_refire;
-/// Shots travel this fast, when appliable
-.float shot_speed;
-/// Inaccuracy
-.float shot_spread;
-/// Estimated (core) damage of projectiles. also reduce on ammo with this amount when fiering
-.float shot_dmg;
-/// If radius dmg, this is how big that radius is.
-.float shot_radius;
-/// Max force exserted by round impact
-.float shot_force;
-/// < 1 = shoot # times at target (if possible)
-.float shot_volly;
-/// Refire after a compleated volly.
-.float shot_volly_refire;
-
-/// Consider targets within this range
-.float target_range;
-/// Dont consider targets closer then
-.float target_range_min;
-/// Targets closer to this are prefered
-.float target_range_optimal;
-
-/*
-* The standard targetselection tries to select a target based on
-* range, angle offset, target type, "is old target"
-* Thise biases will allow score scaling to (dis)favor diffrent targets
-*/
-/// (dis)Favor best range this mutch
-.float target_select_rangebias;
-/// (dis)Favor targeting my old enemy this mutch
-.float target_select_samebias;
-/// (dis)Favor targeting the enemy closest to my guns current angle this mutch
-.float target_select_anglebias;
-/// (dis)Favor Missiles? (-1 to diable targeting compleatly)
-.float target_select_missilebias;
-/// (dis)Favot living players (-1 to diable targeting compleatly)
-.float target_select_playerbias;
-/// Field of view
-//.float target_select_fov;
-/// Last timestamp this turret aquierd a valid target
-.float target_select_time;
-/// Throttle re-validation of current target
-.float target_validate_time;
-/*
-* Aim refers to real aiming, not gun pos (thats done by track)
-*/
-/// Maximum offset between impact and aim spot to fire
-.float aim_firetolerance_dist;
-/// How fast can i rotate/pitch (per second in stepmotor mode, base force in smooth modes)
-.float aim_speed;
-/// cant aim higher/lower then this
-.float aim_maxpitch;
-/// I cant rotate more then this
-.float aim_maxrot;
-
-// Ammo/power. keeping dmg and ammo on a one to one ratio is preferable (for rating)
-/// Staring & current ammo
-.float ammo;
-/// Regenerate this mutch ammo (per second)
-.float ammo_recharge;
-/// Max amount of ammo i can hold
-.float ammo_max;
-
-
-// Uncomment below to enable various debug output.
-//#define TURRET_DEBUG
-//#define TURRET_DEBUG_TARGETVALIDATE
-//#define TURRET_DEBUG_TARGETSELECT
-
-#ifdef TURRET_DEBUG
-.float tur_dbg_dmg_t_h; // Total dmg that hit something (can be more then tur_dbg_dmg_t_f since it should count radius dmg.
-.float tur_dbg_dmg_t_f; // Total damage spent
-.float tur_dbg_start; // When did i go online?
-.float tur_dbg_tmr1; // timer for random use
-.float tur_dbg_tmr2; // timer for random use
-.float tur_dbg_tmr3; // timer for random use
-.vector tur_dbg_rvec; // Random vector, mainly for coloruing stuff'
-#endif
-
-// System main's
-/// Main AI loop
-void turret_think();
-/// Prefire checks and sutch
-void turret_fire();
-
-// Callbacks
-/// implements the actual fiering
-.void() turret_firefunc;
-/// prefire checks go here. return 1 to go bang, 0 not to.
-.float() turret_firecheckfunc;
-/// Execure AFTER main AI loop
-.void() turret_postthink;
-
-/// Add a target
-.float(entity e_target,entity e_sender) turret_addtarget;
-
-.void() turret_diehook;
-.void() turret_respawnhook;
-
-/*
-* Target selection, preferably but not nessesarely
-* return a normalized result.
-*/
-/// Function to use for target evaluation. usualy turret_stdproc_targetscore_generic
-.float(entity _turret, entity _target) turret_score_target;
-
-/*
-* Target selection
-*/
-/// Generic, fairly smart, bias-aware target selection.
-float turret_stdproc_targetscore_generic(entity _turret, entity _target);
-/// Experimental supportunits targetselector
-float turret_stdproc_targetscore_support(entity _turret,entity _target);
-
-/*
-* Aim functions
-*/
-/// Generic aimer guided by self.aim_flags
-vector turret_stdproc_aim_generic();
-
-/*
-* Turret turning & pitch
-*/
-/// Tries to line up the turret head with the aimpos
-void turret_stdproc_track();
-
-/// Generic damage handeling. blows up the turret when health <= 0
-void turret_stdproc_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce);
-/// Spawns a explotion, does some damage & trows bits arround.
-void turret_stdproc_die();
-/// reassembles the turret.
-void turret_stdproc_respawn();
-
-/// Evaluate target validity
-float turret_validate_target(entity e_turret,entity e_target,float validate_flags);
-/// Turret Head Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
-vector tvt_thadv;
-/// Turret Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
-vector tvt_tadv;
-/// Turret Head Angle Diff Float. updated by a sucsessfull call to turret_validate_target
-float tvt_thadf;
-/// Turret Angle Diff Float. updated by a sucsessfull call to turret_validate_target
-float tvt_tadf;
-/// Distance. updated by a sucsessfull call to turret_validate_target
-float tvt_dist;
-
-/// updates aim org, shot org, shot dir and enemy org for selected turret
-void turret_do_updates(entity e_turret);
-.vector tur_shotdir_updated;
-
-void turrets_precash();
-#endif // SVQC
-
-// common
-.int turret_type;
-const int TID_COMMON = 1;
-const int TID_EWHEEL = 2;
-const int TID_FLAC = 3;
-const int TID_FUSION = 4;
-const int TID_HELLION = 5;
-const int TID_HK = 6;
-const int TID_MACHINEGUN = 7;
-const int TID_MLRS = 8;
-const int TID_PHASER = 9;
-const int TID_PLASMA = 10;
-const int TID_PLASMA_DUAL = 11;
-const int TID_TESLA = 12;
-const int TID_WALKER = 13;
-const int TID_LAST = 13;
-
-const int TNSF_UPDATE = 2;
-const int TNSF_STATUS = 4;
-const int TNSF_SETUP = 8;
-const int TNSF_ANG = 16;
-const int TNSF_AVEL = 32;
-const int TNSF_MOVE = 64;
-.float anim_start_time;
-const int TNSF_ANIM = 128;
-
-const int TNSF_FULL_UPDATE = 16777215;
-
-#endif // TTURRETS_ENABLED
-#endif
+++ /dev/null
-/*
-* Generic aim
-
-supports:
-TFL_AIM_NO
-TFL_AIM_GROUNDGROUND
-TFL_AIM_LEAD
-TFL_AIM_SHOTTIMECOMPENSATE
-*/
-vector turret_stdproc_aim_generic()
-{
-
- vector pre_pos, prep;
- float distance, i, mintime;
-
- turret_tag_fire_update();
-
- if(self.aim_flags & TFL_AIM_SIMPLE)
- return real_origin(self.enemy);
-
- mintime = max(self.attack_finished_single - time,0) + sys_frametime;
-
- // Baseline
- pre_pos = real_origin(self.enemy);
-
- // Lead?
- if (self.aim_flags & TFL_AIM_LEAD)
- {
- if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
- {
- // FIXME: this cant be the best way to do this..
- prep = pre_pos;
- float impact_time = 0;
- for(i = 0; i < 4; ++i)
- {
- distance = vlen(prep - self.tur_shotorg);
- impact_time = distance / self.shot_speed;
- prep = pre_pos + self.enemy.velocity * impact_time;
- }
-
- prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
-
- if(self.aim_flags & TFL_AIM_ZPREDICT)
- if (!(self.enemy.flags & FL_ONGROUND))
- if(self.enemy.movetype == MOVETYPE_WALK || self.enemy.movetype == MOVETYPE_TOSS || self.enemy.movetype == MOVETYPE_BOUNCE)
- {
- float vz;
- prep.z = pre_pos.z;
- vz = self.enemy.velocity.z;
- for(i = 0; i < impact_time; i += sys_frametime)
- {
- vz = vz - (autocvar_sv_gravity * sys_frametime);
- prep.z = prep.z + vz * sys_frametime;
- }
- }
- pre_pos = prep;
- }
- else
- pre_pos = pre_pos + self.enemy.velocity * mintime;
- }
-
- if(self.aim_flags & TFL_AIM_GROUNDGROUND)
- {
- //tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
- traceline(pre_pos + '0 0 32',pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
- if(trace_fraction != 1.0)
- pre_pos = trace_endpos;
- }
-
- return pre_pos;
-}
+++ /dev/null
-/*
-* Spawn a boom, trow fake bits arround
-* and hide the real ones.
-*/
-void turret_hide()
-{
- self.effects |= EF_NODRAW;
- self.nextthink = time + self.respawntime - 0.2;
- self.think = turret_stdproc_respawn;
-}
-
-void turret_stdproc_die()
-{
- self.deadflag = DEAD_DEAD;
- self.tur_head.deadflag = self.deadflag;
-
-// Unsolidify and hide real parts
- self.solid = SOLID_NOT;
- self.tur_head.solid = self.solid;
-
- self.event_damage = func_null;
- self.takedamage = DAMAGE_NO;
-
- self.health = 0;
-
-// Go boom
- //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
-
- if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
- {
- if (self.turret_diehook)
- self.turret_diehook();
-
- remove(self.tur_head);
- remove(self);
- }
- else
- {
- // Setup respawn
- self.SendFlags |= TNSF_STATUS;
- self.nextthink = time + 0.2;
- self.think = turret_hide;
-
- if (self.turret_diehook)
- self.turret_diehook();
- }
-}
-
-void turret_stdproc_respawn()
-{
- // Make sure all parts belong to the same team since
- // this function doubles as "teamchange" function.
- self.tur_head.team = self.team;
-
- self.effects &= ~EF_NODRAW;
- self.deadflag = DEAD_NO;
- self.effects = EF_LOWPRECISION;
- self.solid = SOLID_BBOX;
-
- self.takedamage = DAMAGE_AIM;
- self.event_damage = turret_stdproc_damage;
-
- self.avelocity = '0 0 0';
- self.tur_head.avelocity = self.avelocity;
- self.tur_head.angles = self.idle_aim;
- self.health = self.tur_health;
-
- self.enemy = world;
- self.volly_counter = self.shot_volly;
- self.ammo = self.ammo_max;
-
- self.nextthink = time + self.ticrate;
- self.think = turret_think;
-
- self.SendFlags = TNSF_FULL_UPDATE;
-
- if (self.turret_respawnhook)
- self.turret_respawnhook();
-}
-
-/*
-* Standard damage proc.
-*/
-void turret_stdproc_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
- // Enougth allready!
- if(self.deadflag == DEAD_DEAD)
- return;
-
- // Inactive turrets take no damage. (hm..)
- if (!self.active)
- return;
-
- if (teamplay)
- if (self.team == attacker.team)
- {
- // This does not happen anymore. Re-enable if you fix that.
- if(IS_REAL_CLIENT(attacker))
- sprint(attacker, "\{1}Turret tells you: I'm on your team!\n");
-
- if(autocvar_g_friendlyfire)
- damage = damage * autocvar_g_friendlyfire;
- else
- return;
- }
-
- self.health = self.health - damage;
-
- // thorw head slightly off aim when hit?
- if (self.damage_flags & TFL_DMG_HEADSHAKE)
- {
- self.tur_head.angles_x = self.tur_head.angles.x + (-0.5 + random()) * damage;
- self.tur_head.angles_y = self.tur_head.angles.y + (-0.5 + random()) * damage;
-
- self.SendFlags |= TNSF_ANG;
- }
-
- if (self.turrcaps_flags & TFL_TURRCAPS_MOVE)
- self.velocity = self.velocity + vforce;
-
- if (self.health <= 0)
- {
- self.event_damage = func_null;
- self.tur_head.event_damage = func_null;
- self.takedamage = DAMAGE_NO;
- self.nextthink = time;
- self.think = turret_stdproc_die;
- }
-
- self.SendFlags |= TNSF_STATUS;
-}
+++ /dev/null
-#include "../../_all.qh"
-
-#include "../../g_damage.qh"
-#include "../../bot/bot.qh"
-
-#define cvar_base "g_turrets_unit_"
-.float clientframe;
-void turrets_setframe(float _frame, float client_only)
-{
- if((client_only ? self.clientframe : self.frame ) != _frame)
- {
- self.SendFlags |= TNSF_ANIM;
- self.anim_start_time = time;
- }
-
- if(client_only)
- self.clientframe = _frame;
- else
- self.frame = _frame;
-
-}
-
-float turret_send(entity to, int sf)
-{
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
- WriteByte(MSG_ENTITY, sf);
- if(sf & TNSF_SETUP)
- {
- WriteByte(MSG_ENTITY, self.turret_type);
-
- WriteCoord(MSG_ENTITY, self.origin.x);
- WriteCoord(MSG_ENTITY, self.origin.y);
- WriteCoord(MSG_ENTITY, self.origin.z);
-
- WriteAngle(MSG_ENTITY, self.angles.x);
- WriteAngle(MSG_ENTITY, self.angles.y);
- }
-
- if(sf & TNSF_ANG)
- {
- WriteShort(MSG_ENTITY, rint(self.tur_head.angles.x));
- WriteShort(MSG_ENTITY, rint(self.tur_head.angles.y));
- }
-
- if(sf & TNSF_AVEL)
- {
- WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity.x));
- WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity.y));
- }
-
- if(sf & TNSF_MOVE)
- {
- WriteShort(MSG_ENTITY, rint(self.origin.x));
- WriteShort(MSG_ENTITY, rint(self.origin.y));
- WriteShort(MSG_ENTITY, rint(self.origin.z));
-
- WriteShort(MSG_ENTITY, rint(self.velocity.x));
- WriteShort(MSG_ENTITY, rint(self.velocity.y));
- WriteShort(MSG_ENTITY, rint(self.velocity.z));
-
- WriteShort(MSG_ENTITY, rint(self.angles.y));
- }
-
- if(sf & TNSF_ANIM)
- {
- WriteCoord(MSG_ENTITY, self.anim_start_time);
- WriteByte(MSG_ENTITY, self.frame);
- }
-
- if(sf & TNSF_STATUS)
- {
- WriteByte(MSG_ENTITY, self.team);
-
- if(self.health <= 0)
- WriteByte(MSG_ENTITY, 0);
- else
- WriteByte(MSG_ENTITY, ceil((self.health / self.tur_health) * 255));
- }
-
- return true;
-}
-
-void load_unit_settings(entity ent, string unitname, float is_reload)
-{
- string sbase;
-
- if (ent == world)
- return;
-
- if (!ent.turret_scale_damage) ent.turret_scale_damage = 1;
- if (!ent.turret_scale_range) ent.turret_scale_range = 1;
- if (!ent.turret_scale_refire) ent.turret_scale_refire = 1;
- if (!ent.turret_scale_ammo) ent.turret_scale_ammo = 1;
- if (!ent.turret_scale_aim) ent.turret_scale_aim = 1;
- if (!ent.turret_scale_health) ent.turret_scale_health = 1;
- if (!ent.turret_scale_respawn) ent.turret_scale_respawn = 1;
-
- sbase = strcat(cvar_base,unitname);
- if (is_reload)
- {
- ent.enemy = world;
- ent.tur_head.avelocity = '0 0 0';
-
- ent.tur_head.angles = '0 0 0';
- }
-
- ent.health = cvar(strcat(sbase,"_health")) * ent.turret_scale_health;
- ent.respawntime = cvar(strcat(sbase,"_respawntime")) * ent.turret_scale_respawn;
-
- ent.shot_dmg = cvar(strcat(sbase,"_shot_dmg")) * ent.turret_scale_damage;
- ent.shot_refire = cvar(strcat(sbase,"_shot_refire")) * ent.turret_scale_refire;
- ent.shot_radius = cvar(strcat(sbase,"_shot_radius")) * ent.turret_scale_damage;
- ent.shot_speed = cvar(strcat(sbase,"_shot_speed"));
- ent.shot_spread = cvar(strcat(sbase,"_shot_spread"));
- ent.shot_force = cvar(strcat(sbase,"_shot_force")) * ent.turret_scale_damage;
- ent.shot_volly = cvar(strcat(sbase,"_shot_volly"));
- ent.shot_volly_refire = cvar(strcat(sbase,"_shot_volly_refire")) * ent.turret_scale_refire;
-
- ent.target_range = cvar(strcat(sbase,"_target_range")) * ent.turret_scale_range;
- ent.target_range_min = cvar(strcat(sbase,"_target_range_min")) * ent.turret_scale_range;
- ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * ent.turret_scale_range;
- //ent.target_range_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
-
- ent.target_select_rangebias = cvar(strcat(sbase,"_target_select_rangebias"));
- ent.target_select_samebias = cvar(strcat(sbase,"_target_select_samebias"));
- ent.target_select_anglebias = cvar(strcat(sbase,"_target_select_anglebias"));
- ent.target_select_playerbias = cvar(strcat(sbase,"_target_select_playerbias"));
- //ent.target_select_fov = cvar(cvar_gets(sbase,"_target_select_fov"));
-
- ent.ammo_max = cvar(strcat(sbase,"_ammo_max")) * ent.turret_scale_ammo;
- ent.ammo_recharge = cvar(strcat(sbase,"_ammo_recharge")) * ent.turret_scale_ammo;
-
- ent.aim_firetolerance_dist = cvar(strcat(sbase,"_aim_firetolerance_dist"));
- ent.aim_speed = cvar(strcat(sbase,"_aim_speed")) * ent.turret_scale_aim;
- ent.aim_maxrot = cvar(strcat(sbase,"_aim_maxrot"));
- ent.aim_maxpitch = cvar(strcat(sbase,"_aim_maxpitch"));
-
- ent.track_type = cvar(strcat(sbase,"_track_type"));
- ent.track_accel_pitch = cvar(strcat(sbase,"_track_accel_pitch"));
- ent.track_accel_rot = cvar(strcat(sbase,"_track_accel_rot"));
- ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
-
- if(is_reload)
- if(ent.turret_respawnhook)
- ent.turret_respawnhook();
-}
-
-void turret_projectile_explode()
-{
-
- self.takedamage = DAMAGE_NO;
- self.event_damage = func_null;
-#ifdef TURRET_DEBUG
- float d;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-#endif
- remove(self);
-}
-
-void turret_projectile_touch()
-{
- PROJECTILE_TOUCH;
- turret_projectile_explode();
-}
-
-void turret_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
- self.velocity += vforce;
- self.health -= damage;
- //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
- if(self.health <= 0)
- W_PrepareExplosionByDamage(self.owner, turret_projectile_explode);
-}
-
-entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
-{
- entity proj;
-
- sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
- proj.owner = self;
- proj.realowner = self;
- proj.bot_dodge = true;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_projectile_explode;
- proj.touch = turret_projectile_touch;
- proj.nextthink = time + 9;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.flags = FL_PROJECTILE;
- proj.enemy = self.enemy;
- proj.totalfrags = _death;
- PROJECTILE_MAKETRIGGER(proj);
- if(_health)
- {
- proj.health = _health;
- proj.takedamage = DAMAGE_YES;
- proj.event_damage = turret_projectile_damage;
- }
- else
- proj.flags |= FL_NOTARGET;
-
- CSQCProjectile(proj, _cli_anim, _proj_type, _cull);
-
- return proj;
-}
-
-/**
-** updates enemy distances, predicted impact point/time
-** and updated aim<->predict impact distance.
-**/
-void turret_do_updates(entity t_turret)
-{
- vector enemy_pos;
- entity oldself;
-
- oldself = self;
- self = t_turret;
-
- enemy_pos = real_origin(self.enemy);
-
- turret_tag_fire_update();
-
- self.tur_shotdir_updated = v_forward;
- self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos);
- self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos);
-
- /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy))
- {
- oldpos = self.enemy.origin;
- setorigin(self.enemy, self.tur_aimpos);
- tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
- setorigin(self.enemy, oldpos);
-
- if(trace_ent == self.enemy)
- self.tur_dist_impact_to_aimpos = 0;
- else
- self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
- }
- else*/
- tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
-
- self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5);
- self.tur_impactent = trace_ent;
- self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
-
- self = oldself;
-}
-
-/*
-vector turret_fovsearch_pingpong()
-{
- vector wish_angle;
- if(self.phase < time)
- {
- if( self.tur_head.phase )
- self.tur_head.phase = 0;
- else
- self.tur_head.phase = 1;
- self.phase = time + 5;
- }
-
- if( self.tur_head.phase)
- wish_angle = self.idle_aim + '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
- else
- wish_angle = self.idle_aim - '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
-
- return wish_angle;
-}
-
-vector turret_fovsearch_steprot()
-{
- vector wish_angle;
- //float rot_add;
-
- wish_angle = self.tur_head.angles;
- wish_angle_x = self.idle_aim_x;
-
- if (self.phase < time)
- {
- //rot_add = self.aim_maxrot / self.target_select_fov;
- wish_angle_y += (self.target_select_fov * 2);
-
- if(wish_angle_y > 360)
- wish_angle_y = wish_angle_y - 360;
-
- self.phase = time + 1.5;
- }
-
- return wish_angle;
-}
-
-vector turret_fovsearch_random()
-{
- vector wish_angle;
-
- if (self.phase < time)
- {
- wish_angle_y = random() * self.aim_maxrot;
- if(random() < 0.5)
- wish_angle_y *= -1;
-
- wish_angle_x = random() * self.aim_maxpitch;
- if(random() < 0.5)
- wish_angle_x *= -1;
-
- self.phase = time + 5;
-
- self.tur_aimpos = wish_angle;
- }
-
- return self.idle_aim + self.tur_aimpos;
-}
-*/
-
-/**
-** Handles head rotation according to
-** the units .track_type and .track_flags
-**/
-.float turret_framecounter;
-void turret_stdproc_track()
-{
- vector target_angle; // This is where we want to aim
- vector move_angle; // This is where we can aim
- float f_tmp;
- vector v1, v2;
- v1 = self.tur_head.angles;
- v2 = self.tur_head.avelocity;
-
- if (self.track_flags == TFL_TRACK_NO)
- return;
-
- if (!self.active)
- target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
- else if (self.enemy == world)
- {
- if(time > self.lip)
- target_angle = self.idle_aim + self.angles;
- else
- target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
- }
- else
- {
- target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
- }
-
- self.tur_head.angles_x = anglemods(self.tur_head.angles.x);
- self.tur_head.angles_y = anglemods(self.tur_head.angles.y);
-
- // Find the diffrence between where we currently aim and where we want to aim
- //move_angle = target_angle - (self.angles + self.tur_head.angles);
- //move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
-
- move_angle = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(self.angles), AnglesTransform_FromAngles(target_angle))) - self.tur_head.angles;
- move_angle = shortangle_vxy(move_angle, self.tur_head.angles);
-
- switch(self.track_type)
- {
- case TFL_TRACKTYPE_STEPMOTOR:
- f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
- if (self.track_flags & TFL_TRACK_PITCH)
- {
- self.tur_head.angles_x += bound(-f_tmp,move_angle.x, f_tmp);
- if(self.tur_head.angles.x > self.aim_maxpitch)
- self.tur_head.angles_x = self.aim_maxpitch;
-
- if(self.tur_head.angles.x < -self.aim_maxpitch)
- self.tur_head.angles_x = self.aim_maxpitch;
- }
-
- if (self.track_flags & TFL_TRACK_ROT)
- {
- self.tur_head.angles_y += bound(-f_tmp, move_angle.y, f_tmp);
- if(self.tur_head.angles.y > self.aim_maxrot)
- self.tur_head.angles_y = self.aim_maxrot;
-
- if(self.tur_head.angles.y < -self.aim_maxrot)
- self.tur_head.angles_y = self.aim_maxrot;
- }
-
- // CSQC
- self.SendFlags |= TNSF_ANG;
-
- return;
-
- case TFL_TRACKTYPE_FLUIDINERTIA:
- f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
- move_angle.x = bound(-self.aim_speed, move_angle.x * self.track_accel_pitch * f_tmp, self.aim_speed);
- move_angle.y = bound(-self.aim_speed, move_angle.y * self.track_accel_rot * f_tmp, self.aim_speed);
- move_angle = (self.tur_head.avelocity * self.track_blendrate) + (move_angle * (1 - self.track_blendrate));
- break;
-
- case TFL_TRACKTYPE_FLUIDPRECISE:
-
- move_angle.y = bound(-self.aim_speed, move_angle.y, self.aim_speed);
- move_angle.x = bound(-self.aim_speed, move_angle.x, self.aim_speed);
-
- break;
- }
-
- // pitch
- if (self.track_flags & TFL_TRACK_PITCH)
- {
- self.tur_head.avelocity_x = move_angle.x;
- if((self.tur_head.angles.x + self.tur_head.avelocity.x * self.ticrate) > self.aim_maxpitch)
- {
- self.tur_head.avelocity_x = 0;
- self.tur_head.angles_x = self.aim_maxpitch;
-
- self.SendFlags |= TNSF_ANG;
- }
-
- if((self.tur_head.angles.x + self.tur_head.avelocity.x * self.ticrate) < -self.aim_maxpitch)
- {
- self.tur_head.avelocity_x = 0;
- self.tur_head.angles_x = -self.aim_maxpitch;
-
- self.SendFlags |= TNSF_ANG;
- }
- }
-
- // rot
- if (self.track_flags & TFL_TRACK_ROT)
- {
- self.tur_head.avelocity_y = move_angle.y;
-
- if((self.tur_head.angles.y + self.tur_head.avelocity.y * self.ticrate) > self.aim_maxrot)
- {
- self.tur_head.avelocity_y = 0;
- self.tur_head.angles_y = self.aim_maxrot;
-
- self.SendFlags |= TNSF_ANG;
- }
-
- if((self.tur_head.angles.y + self.tur_head.avelocity.y * self.ticrate) < -self.aim_maxrot)
- {
- self.tur_head.avelocity_y = 0;
- self.tur_head.angles_y = -self.aim_maxrot;
-
- self.SendFlags |= TNSF_ANG;
- }
- }
-
- self.SendFlags |= TNSF_AVEL;
-
- // Force a angle update every 10'th frame
- self.turret_framecounter += 1;
- if(self.turret_framecounter >= 10)
- {
- self.SendFlags |= TNSF_ANG;
- self.turret_framecounter = 0;
- }
-}
-
-
-/*
- + = implemented
- - = not implemented
-
- + TFL_FIRECHECK_NO
- + TFL_FIRECHECK_WORLD
- + TFL_FIRECHECK_DEAD
- + TFL_FIRECHECK_DISTANCES
- - TFL_FIRECHECK_LOS
- + TFL_FIRECHECK_AIMDIST
- + TFL_FIRECHECK_REALDIST
- - TFL_FIRECHECK_ANGLEDIST
- - TFL_FIRECHECK_TEAMCECK
- + TFL_FIRECHECK_AFF
- + TFL_FIRECHECK_OWM_AMMO
- + TFL_FIRECHECK_OTHER_AMMO
- + TFL_FIRECHECK_REFIRE
-*/
-
-/**
-** Preforms pre-fire checks based on the uints firecheck_flags
-**/
-float turret_stdproc_firecheck()
-{
- // This one just dont care =)
- if (self.firecheck_flags & TFL_FIRECHECK_NO)
- return 1;
-
- if (self.enemy == world)
- return 0;
-
- // Ready?
- if (self.firecheck_flags & TFL_FIRECHECK_REFIRE)
- if (self.attack_finished_single > time) return 0;
-
- // Special case: volly fire turret that has to fire a full volly if a shot was fired.
- if (self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
- if (self.volly_counter != self.shot_volly)
- if(self.ammo >= self.shot_dmg)
- return 1;
-
- // Lack of zombies makes shooting dead things unnecessary :P
- if (self.firecheck_flags & TFL_FIRECHECK_DEAD)
- if (self.enemy.deadflag != DEAD_NO)
- return 0;
-
- // Own ammo?
- if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO)
- if (self.ammo < self.shot_dmg)
- return 0;
-
- // Other's ammo? (support-supply units)
- if (self.firecheck_flags & TFL_FIRECHECK_OTHER_AMMO)
- if (self.enemy.ammo >= self.enemy.ammo_max)
- return 0;
-
- // Target of opertunity?
- if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
- {
- self.enemy = self.tur_impactent;
- return 1;
- }
-
- if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
- {
- // To close?
- if (self.tur_dist_aimpos < self.target_range_min)
- if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
- return 1; // Target of opertunity?
- else
- return 0;
- }
-
- // Try to avoid FF?
- if (self.firecheck_flags & TFL_FIRECHECK_AFF)
- if (self.tur_impactent.team == self.team)
- return 0;
-
- // aim<->predicted impact
- if (self.firecheck_flags & TFL_FIRECHECK_AIMDIST)
- if (self.tur_dist_impact_to_aimpos > self.aim_firetolerance_dist)
- return 0;
-
- // Volly status
- if (self.shot_volly > 1)
- if (self.volly_counter == self.shot_volly)
- if (self.ammo < (self.shot_dmg * self.shot_volly))
- return 0;
-
- /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
- if(self.tur_impactent != self.enemy)
- return 0;*/
-
- return 1;
-}
-
-/*
- + TFL_TARGETSELECT_NO
- + TFL_TARGETSELECT_LOS
- + TFL_TARGETSELECT_PLAYERS
- + TFL_TARGETSELECT_MISSILES
- - TFL_TARGETSELECT_TRIGGERTARGET
- + TFL_TARGETSELECT_ANGLELIMITS
- + TFL_TARGETSELECT_RANGELIMTS
- + TFL_TARGETSELECT_TEAMCHECK
- - TFL_TARGETSELECT_NOBUILTIN
- + TFL_TARGETSELECT_OWNTEAM
-*/
-
-/**
-** Evaluate a entity for target valitity based on validate_flags
-** NOTE: the caller must check takedamage before calling this, to inline this check.
-**/
-float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
-{
- vector v_tmp;
-
- //if(!validate_flags & TFL_TARGETSELECT_NOBUILTIN)
- // return -0.5;
-
- if(e_target.owner == e_turret)
- return -0.5;
-
- if (!checkpvs(e_target.origin, e_turret))
- return -1;
-
- if (!e_target)
- return -2;
-
- if(g_onslaught)
- if (substring(e_target.classname, 0, 10) == "onslaught_") // don't attack onslaught targets, that's the player's job!
- return - 3;
-
- if (validate_flags & TFL_TARGETSELECT_NO)
- return -4;
-
- // If only this was used more..
- if (e_target.flags & FL_NOTARGET)
- return -5;
-
- // Cant touch this
- if(IS_VEHICLE(e_target))
- {
- if (e_target.vehicle_health <= 0)
- return -6;
- }
- else if (e_target.health <= 0)
- return -6;
-
- // player
- if (IS_CLIENT(e_target))
- {
- if (!(validate_flags & TFL_TARGETSELECT_PLAYERS))
- return -7;
-
- if (e_target.deadflag != DEAD_NO)
- return -8;
- }
-
- // enemy turrets
- if (validate_flags & TFL_TARGETSELECT_NOTURRETS)
- if (e_target.turret_firefunc || e_target.owner.tur_head == e_target)
- if(e_target.team != e_turret.team) // Dont break support units.
- return -9;
-
- // Missile
- if (e_target.flags & FL_PROJECTILE)
- if (!(validate_flags & TFL_TARGETSELECT_MISSILES))
- return -10;
-
- if (validate_flags & TFL_TARGETSELECT_MISSILESONLY)
- if (!(e_target.flags & FL_PROJECTILE))
- return -10.5;
-
- // Team check
- if (validate_flags & TFL_TARGETSELECT_TEAMCHECK)
- {
- if (validate_flags & TFL_TARGETSELECT_OWNTEAM)
- {
- if (e_target.team != e_turret.team)
- return -11;
-
- if (e_turret.team != e_target.owner.team)
- return -12;
- }
- else
- {
- if (e_target.team == e_turret.team)
- return -13;
-
- if (e_turret.team == e_target.owner.team)
- return -14;
- }
- }
-
- // Range limits?
- tvt_dist = vlen(e_turret.origin - real_origin(e_target));
- if (validate_flags & TFL_TARGETSELECT_RANGELIMTS)
- {
- if (tvt_dist < e_turret.target_range_min)
- return -15;
-
- if (tvt_dist > e_turret.target_range)
- return -16;
- }
-
- // Can we even aim this thing?
- tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target);
- tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
- tvt_thadf = vlen(tvt_thadv);
- tvt_tadf = vlen(tvt_tadv);
-
- /*
- if(validate_flags & TFL_TARGETSELECT_FOV)
- {
- if(e_turret.target_select_fov < tvt_thadf)
- return -21;
- }
- */
-
- if (validate_flags & TFL_TARGETSELECT_ANGLELIMITS)
- {
- if (fabs(tvt_tadv.x) > e_turret.aim_maxpitch)
- return -17;
-
- if (fabs(tvt_tadv.y) > e_turret.aim_maxrot)
- return -18;
- }
-
- // Line of sight?
- if (validate_flags & TFL_TARGETSELECT_LOS)
- {
- v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5);
-
- traceline(e_turret.origin + '0 0 16', v_tmp, 0, e_turret);
-
- if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos))
- return -19;
- }
-
- if (e_target.classname == "grapplinghook")
- return -20;
-
- /*
- if (e_target.classname == "func_button")
- return -21;
- */
-
-#ifdef TURRET_DEBUG_TARGETSELECT
- dprint("Target:",e_target.netname," is a valid target for ",e_turret.netname,"\n");
-#endif
-
- return 1;
-}
-
-entity turret_select_target()
-{
- entity e; // target looper entity
- float score; // target looper entity score
- entity e_enemy; // currently best scoreing target
- float m_score; // currently best scoreing target's score
-
- m_score = 0;
- if(self.enemy && self.enemy.takedamage && turret_validate_target(self,self.enemy,self.target_validate_flags) > 0)
- {
- e_enemy = self.enemy;
- m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias;
- }
- else
- e_enemy = self.enemy = world;
-
- e = findradius(self.origin, self.target_range);
-
- // Nothing to aim at?
- if (!e)
- return world;
-
- while (e)
- {
- if(e.takedamage)
- {
- float f = turret_validate_target(self, e, self.target_select_flags);
- //dprint("F is: ", ftos(f), "\n");
- if ( f > 0)
- {
- score = self.turret_score_target(self,e);
- if ((score > m_score) && (score > 0))
- {
- e_enemy = e;
- m_score = score;
- }
- }
- }
- e = e.chain;
- }
-
- return e_enemy;
-}
-
-void turret_think()
-{
- entity e;
-
- self.nextthink = time + self.ticrate;
-
- // ONS uses somewhat backwards linking.
- if (teamplay)
- {
- if (g_onslaught)
- if (self.target)
- {
- e = find(world, targetname,self.target);
- if (e != world)
- self.team = e.team;
- }
-
- if (self.team != self.tur_head.team)
- turret_stdproc_respawn();
- }
-
-#ifdef TURRET_DEBUG
- if (self.tur_dbg_tmr1 < time)
- {
- if (self.enemy) paint_target (self.enemy,128,self.tur_dbg_rvec,0.9);
- paint_target(self,256,self.tur_dbg_rvec,0.9);
- self.tur_dbg_tmr1 = time + 1;
- }
-#endif
-
- // Handle ammo
- if (!(self.spawnflags & TSF_NO_AMMO_REGEN))
- if (self.ammo < self.ammo_max)
- self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max);
-
- // Inactive turrets needs to run the think loop,
- // So they can handle animation and wake up if need be.
- if (!self.active)
- {
- turret_stdproc_track();
- return;
- }
-
- // This is typicaly used for zaping every target in range
- // turret_fusionreactor uses this to recharge friendlys.
- if (self.shoot_flags & TFL_SHOOT_HITALLVALID)
- {
- // Do a self.turret_fire for every valid target.
- e = findradius(self.origin,self.target_range);
- while (e)
- {
- if(e.takedamage)
- {
- if (turret_validate_target(self,e,self.target_validate_flags))
- {
- self.enemy = e;
-
- turret_do_updates(self);
-
- if (self.turret_firecheckfunc())
- turret_fire();
- }
- }
-
- e = e.chain;
- }
- self.enemy = world;
- }
- else if(self.shoot_flags & TFL_SHOOT_CUSTOM)
- {
- // This one is doing something.. oddball. assume its handles what needs to be handled.
-
- // Predict?
- if (!(self.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch?
- if (!(self.track_flags & TFL_TRACK_NO))
- turret_stdproc_track();
-
- turret_do_updates(self);
-
- // Fire?
- if (self.turret_firecheckfunc())
- turret_fire();
- }
- else
- {
- // Special case for volly always. if it fired once it must compleate the volly.
- if(self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
- if(self.volly_counter != self.shot_volly)
- {
- // Predict or whatnot
- if (!(self.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch
- if (!(self.track_flags & TFL_TRACK_NO))
- turret_stdproc_track();
-
- turret_do_updates(self);
-
- // Fire!
- if (self.turret_firecheckfunc() != 0)
- turret_fire();
-
- if(self.turret_postthink)
- self.turret_postthink();
-
- return;
- }
-
- // Check if we have a vailid enemy, and try to find one if we dont.
-
- // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan = 0;
- if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
- do_target_scan = 1;
-
- // Old target (if any) invalid?
- if(self.target_validate_time < time)
- if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
- {
- self.enemy = world;
- self.target_validate_time = time + 0.5;
- do_target_scan = 1;
- }
-
- // But never more often then g_turrets_targetscan_mindelay!
- if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
- do_target_scan = 0;
-
- if(do_target_scan)
- {
- self.enemy = turret_select_target();
- self.target_select_time = time;
- }
-
- // No target, just go to idle, do any custom stuff and bail.
- if (self.enemy == world)
- {
- // Turn & pitch
- if (!(self.track_flags & TFL_TRACK_NO))
- turret_stdproc_track();
-
- // do any per-turret stuff
- if(self.turret_postthink)
- self.turret_postthink();
-
- // And bail.
- return;
- }
- else
- self.lip = time + autocvar_g_turrets_aimidle_delay; // Keep track of the last time we had a target.
-
- // Predict?
- if (!(self.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch?
- if (!(self.track_flags & TFL_TRACK_NO))
- turret_stdproc_track();
-
- turret_do_updates(self);
-
- // Fire?
- if (self.turret_firecheckfunc())
- turret_fire();
- }
-
- // do any custom per-turret stuff
- if(self.turret_postthink)
- self.turret_postthink();
-}
-
-void turret_fire()
-{
- if (autocvar_g_turrets_nofire)
- return;
-
- self.turret_firefunc();
-
- self.attack_finished_single = time + self.shot_refire;
- self.ammo -= self.shot_dmg;
- self.volly_counter = self.volly_counter - 1;
-
- if (self.volly_counter <= 0)
- {
- self.volly_counter = self.shot_volly;
-
- if (self.shoot_flags & TFL_SHOOT_CLEARTARGET)
- self.enemy = world;
-
- if (self.shot_volly > 1)
- self.attack_finished_single = time + self.shot_volly_refire;
- }
-
-#ifdef TURRET_DEBUG
- if (self.enemy) paint_target3(self.tur_aimpos, 64, self.tur_dbg_rvec, self.tur_impacttime + 0.25);
-#endif
-}
-
-void turret_stdproc_fire()
-{
- dprint("^1Bang, ^3your dead^7 ",self.enemy.netname,"! ^1(turret with no real firefunc)\n");
-}
-
-/*
- When .used a turret switch team to activator.team.
- If activator is world, the turret go inactive.
-*/
-void turret_stdproc_use()
-{
- dprint("Turret ",self.netname, " used by ", activator.classname, "\n");
-
- self.team = activator.team;
-
- if(self.team == 0)
- self.active = ACTIVE_NOT;
- else
- self.active = ACTIVE_ACTIVE;
-
-}
-
-void turret_link()
-{
- Net_LinkEntity(self, true, 0, turret_send);
- self.think = turret_think;
- self.nextthink = time;
- self.tur_head.effects = EF_NODRAW;
-}
-
-void turrets_manager_think()
-{
- self.nextthink = time + 1;
-
- entity e;
- if (autocvar_g_turrets_reloadcvars)
- {
- e = nextent(world);
- while (e)
- {
- if(IS_TURRET(e))
- {
- load_unit_settings(e,e.cvar_basename,1);
- if(e.turret_postthink)
- e.turret_postthink();
- }
-
- e = nextent(e);
- }
- cvar_set("g_turrets_reloadcvars","0");
- }
-}
-
-/*
-* Standard turret initialization. use this!
-* (unless you have a very good reason not to)
-* if the return value is 0, the turret should be removed.
-*/
-float turret_stdproc_init (string cvar_base_name, string base, string head, float _turret_type)
-{
- entity e, ee = world;
-
- // Are turrets allowed?
- if (autocvar_g_turrets == 0)
- return 0;
-
- if(_turret_type < 1 || _turret_type > TID_LAST)
- {
- dprint("Invalid / Unkown turret type\"", ftos(_turret_type), "\", aborting!\n");
- return 0;
- }
- self.turret_type = _turret_type;
-
- e = find(world, classname, "turret_manager");
- if (!e)
- {
- e = spawn();
- e.classname = "turret_manager";
- e.think = turrets_manager_think;
- e.nextthink = time + 2;
- }
-
- if (!(self.spawnflags & TSF_SUSPENDED))
- builtin_droptofloor(); // why can't we use regular droptofloor here?
-
- self.cvar_basename = cvar_base_name;
- load_unit_settings(self, self.cvar_basename, 0);
-
- self.effects = EF_NODRAW;
-
- // Handle turret teams.
- if (!teamplay)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team, so they dont kill eachother.
- else if(g_onslaught && self.targetname)
- {
- e = find(world,target,self.targetname);
- if(e != world)
- {
- self.team = e.team;
- ee = e;
- }
- }
- else if(!self.team)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team, so they dont kill eachother.
-
- /*
- * Try to guess some reasonaly defaults
- * for missing params and do sanety checks
- * thise checks could produce some "interesting" results
- * if it hits a glitch in my logic :P so try to set as mutch
- * as possible beforehand.
- */
- if (!self.ticrate)
- {
- if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
- else
- self.ticrate = 0.1; // 10 fps for normal turrets
- }
-
- self.ticrate = bound(sys_frametime, self.ticrate, 60); // keep it sane
-
-// General stuff
- if (self.netname == "")
- self.netname = self.classname;
-
- if (!self.respawntime)
- self.respawntime = 60;
- self.respawntime = max(-1, self.respawntime);
-
- if (!self.health)
- self.health = 1000;
- self.tur_health = max(1, self.health);
- self.bot_attack = true;
- self.monster_attack = true;
-
- if (!self.turrcaps_flags)
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
-
- if (!self.damage_flags)
- self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE;
-
-// Shot stuff.
- if (!self.shot_refire)
- self.shot_refire = 1;
- self.shot_refire = bound(0.01, self.shot_refire, 9999);
-
- if (!self.shot_dmg)
- self.shot_dmg = self.shot_refire * 50;
- self.shot_dmg = max(1, self.shot_dmg);
-
- if (!self.shot_radius)
- self.shot_radius = self.shot_dmg * 0.5;
- self.shot_radius = max(1, self.shot_radius);
-
- if (!self.shot_speed)
- self.shot_speed = 2500;
- self.shot_speed = max(1, self.shot_speed);
-
- if (!self.shot_spread)
- self.shot_spread = 0.0125;
- self.shot_spread = bound(0.0001, self.shot_spread, 500);
-
- if (!self.shot_force)
- self.shot_force = self.shot_dmg * 0.5 + self.shot_radius * 0.5;
- self.shot_force = bound(0.001, self.shot_force, 5000);
-
- if (!self.shot_volly)
- self.shot_volly = 1;
- self.shot_volly = bound(1, self.shot_volly, floor(self.ammo_max / self.shot_dmg));
-
- if (!self.shot_volly_refire)
- self.shot_volly_refire = self.shot_refire * self.shot_volly;
- self.shot_volly_refire = bound(self.shot_refire, self.shot_volly_refire, 60);
-
- if (!self.firecheck_flags)
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
- TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK |
- TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE;
-
-// Range stuff.
- if (!self.target_range)
- self.target_range = self.shot_speed * 0.5;
- self.target_range = bound(0, self.target_range, MAX_SHOT_DISTANCE);
-
- if (!self.target_range_min)
- self.target_range_min = self.shot_radius * 2;
- self.target_range_min = bound(0, self.target_range_min, MAX_SHOT_DISTANCE);
-
- if (!self.target_range_optimal)
- self.target_range_optimal = self.target_range * 0.5;
- self.target_range_optimal = bound(0, self.target_range_optimal, MAX_SHOT_DISTANCE);
-
-
-// Aim stuff.
- if (!self.aim_maxrot)
- self.aim_maxrot = 90;
- self.aim_maxrot = bound(0, self.aim_maxrot, 360);
-
- if (!self.aim_maxpitch)
- self.aim_maxpitch = 20;
- self.aim_maxpitch = bound(0, self.aim_maxpitch, 90);
-
- if (!self.aim_speed)
- self.aim_speed = 36;
- self.aim_speed = bound(0.1, self.aim_speed, 1000);
-
- if (!self.aim_firetolerance_dist)
- self.aim_firetolerance_dist = 5 + (self.shot_radius * 2);
- self.aim_firetolerance_dist = bound(0.1, self.aim_firetolerance_dist, MAX_SHOT_DISTANCE);
-
- if (!self.aim_flags)
- {
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG)
- self.aim_flags |= TFL_AIM_GROUNDGROUND;
- }
-
- if (!self.track_type)
- self.track_type = TFL_TRACKTYPE_STEPMOTOR;
-
- if (self.track_type != TFL_TRACKTYPE_STEPMOTOR)
- {
- // Fluid / Ineria mode. Looks mutch nicer.
- // Can reduce aim preformance alot, needs a bit diffrent aimspeed
-
- if (!self.aim_speed)
- self.aim_speed = 180;
- self.aim_speed = bound(0.1, self.aim_speed, 1000);
-
- if (!self.track_accel_pitch)
- self.track_accel_pitch = 0.5;
-
- if (!self.track_accel_rot)
- self.track_accel_rot = 0.5;
-
- if (!self.track_blendrate)
- self.track_blendrate = 0.35;
- }
-
- if (!self.track_flags)
- self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROT;
-
-
-// Target selection stuff.
- if (!self.target_select_rangebias)
- self.target_select_rangebias = 1;
- self.target_select_rangebias = bound(-10, self.target_select_rangebias, 10);
-
- if (!self.target_select_samebias)
- self.target_select_samebias = 1;
- self.target_select_samebias = bound(-10, self.target_select_samebias, 10);
-
- if (!self.target_select_anglebias)
- self.target_select_anglebias = 1;
- self.target_select_anglebias = bound(-10, self.target_select_anglebias, 10);
-
- if (!self.target_select_missilebias)
- self.target_select_missilebias = -10;
-
- self.target_select_missilebias = bound(-10, self.target_select_missilebias, 10);
- self.target_select_playerbias = bound(-10, self.target_select_playerbias, 10);
-
- if (!self.target_select_flags)
- {
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK
- | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_ANGLELIMITS;
-
- if (self.turrcaps_flags & TFL_TURRCAPS_MISSILEKILL)
- self.target_select_flags |= TFL_TARGETSELECT_MISSILES;
-
- if (self.turrcaps_flags & TFL_TURRCAPS_PLAYERKILL)
- self.target_select_flags |= TFL_TARGETSELECT_PLAYERS;
- //else
- // self.target_select_flags = TFL_TARGETSELECT_NO;
- }
-
- self.target_validate_flags = self.target_select_flags;
-
-// Ammo stuff
- if (!self.ammo_max)
- self.ammo_max = self.shot_dmg * 10;
- self.ammo_max = max(self.shot_dmg, self.ammo_max);
-
- if (!self.ammo)
- self.ammo = self.shot_dmg * 5;
- self.ammo = bound(0,self.ammo, self.ammo_max);
-
- if (!self.ammo_recharge)
- self.ammo_recharge = self.shot_dmg * 0.5;
- self.ammo_recharge = max(0 ,self.ammo_recharge);
-
- // Convert the recharge from X per sec to X per ticrate
- self.ammo_recharge = self.ammo_recharge * self.ticrate;
-
- if (!self.ammo_flags)
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
-
-// Damage stuff
- if(self.spawnflags & TSL_NO_RESPAWN)
- if (!(self.damage_flags & TFL_DMG_DEATH_NORESPAWN))
- self.damage_flags |= TFL_DMG_DEATH_NORESPAWN;
-
-// Offsets & origins
- if (!self.tur_shotorg) self.tur_shotorg = '50 0 50';
-
- if (!self.health)
- self.health = 150;
-
-// Game hooks
- if(MUTATOR_CALLHOOK(TurretSpawn, self))
- return 0;
-
-// End of default & sanety checks, start building the turret.
-
-// Spawn extra bits
- self.tur_head = spawn();
- self.tur_head.netname = self.tur_head.classname = "turret_head";
- self.tur_head.team = self.team;
- self.tur_head.owner = self;
-
- setmodel(self, base);
- setmodel(self.tur_head, head);
-
- setsize(self, '-32 -32 0', '32 32 64');
- setsize(self.tur_head, '0 0 0', '0 0 0');
-
- setorigin(self.tur_head, '0 0 0');
- setattachment(self.tur_head, self, "tag_head");
-
- self.tur_health = self.health;
- self.solid = SOLID_BBOX;
- self.tur_head.solid = SOLID_NOT;
- self.takedamage = DAMAGE_AIM;
- self.tur_head.takedamage = DAMAGE_NO;
- self.movetype = MOVETYPE_NOCLIP;
- self.tur_head.movetype = MOVETYPE_NOCLIP;
-
- // Defend mode?
- if (!self.tur_defend)
- if (self.target != "")
- {
- self.tur_defend = find(world, targetname, self.target);
- if (self.tur_defend == world)
- {
- self.target = "";
- dprint("Turret has invalid defendpoint!\n");
- }
- }
-
- // In target defend mode, aim on the spot to defend when idle.
- if (self.tur_defend)
- self.idle_aim = self.tur_head.angles + angleofs(self.tur_head, self.tur_defend);
- else
- self.idle_aim = '0 0 0';
-
- // Attach stdprocs. override when and what needed
- self.turret_firecheckfunc = turret_stdproc_firecheck;
- self.turret_firefunc = turret_stdproc_fire;
- self.event_damage = turret_stdproc_damage;
-
- if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- self.turret_score_target = turret_stdproc_targetscore_support;
- else
- self.turret_score_target = turret_stdproc_targetscore_generic;
-
- self.use = turret_stdproc_use;
-
- ++turret_count;
- self.nextthink = time + 1;
- self.nextthink += turret_count * sys_frametime;
-
- self.tur_head.team = self.team;
- self.view_ofs = '0 0 0';
-
-#ifdef TURRET_DEBUG
- self.tur_dbg_start = self.nextthink;
- while (vlen(self.tur_dbg_rvec) < 2)
- self.tur_dbg_rvec = randomvec() * 4;
-
- self.tur_dbg_rvec_x = fabs(self.tur_dbg_rvec.x);
- self.tur_dbg_rvec_y = fabs(self.tur_dbg_rvec.y);
- self.tur_dbg_rvec_z = fabs(self.tur_dbg_rvec.z);
-#endif
-
- // Its all good.
- self.turrcaps_flags |= TFL_TURRCAPS_ISTURRET;
-
- self.classname = "turret_main";
-
- self.active = ACTIVE_ACTIVE;
-
- // In ONS mode, and linked to a ONS ent. need to call the use to set team.
- if (g_onslaught && ee)
- {
- activator = ee;
- self.use();
- }
-
- turret_link();
- turret_stdproc_respawn();
- turret_tag_fire_update();
-
- return 1;
-}
-
-
+++ /dev/null
-/*
-* Return a angle within +/- 360.
-*/
-float anglemods(float v)
-{
- v = v - 360 * floor(v / 360);
-
- if(v >= 180)
- return v - 360;
- else if(v <= -180)
- return v + 360;
- else
- return v;
-}
-
-/*
-* Return the short angle
-*/
-float shortangle_f(float ang1, float ang2)
-{
- if(ang1 > ang2)
- {
- if(ang1 > 180)
- return ang1 - 360;
- }
- else
- {
- if(ang1 < -180)
- return ang1 + 360;
- }
-
- return ang1;
-}
-
-vector shortangle_v(vector ang1, vector ang2)
-{
- vector vtmp;
-
- vtmp.x = shortangle_f(ang1_x,ang2_x);
- vtmp.y = shortangle_f(ang1_y,ang2_y);
- vtmp.z = shortangle_f(ang1_z,ang2_z);
-
- return vtmp;
-}
-
-vector shortangle_vxy(vector ang1, vector ang2)
-{
- vector vtmp = '0 0 0';
-
- vtmp.x = shortangle_f(ang1_x,ang2_x);
- vtmp.y = shortangle_f(ang1_y,ang2_y);
-
- return vtmp;
-}
-
-
-/*
-* Get "real" origin, in worldspace, even if ent is attached to something else.
-*/
-vector real_origin(entity ent)
-{
- entity e;
- vector v = ((ent.absmin + ent.absmax) * 0.5);
-
- e = ent.tag_entity;
- while(e)
- {
- v = v + ((e.absmin + e.absmax) * 0.5);
- e = e.tag_entity;
- }
-
- return v;
-}
-
-/*
-* Return the angle between two enteties
-*/
-vector angleofs(entity from, entity to)
-{
- vector v_res;
-
- v_res = normalize(to.origin - from.origin);
- v_res = vectoangles(v_res);
- v_res = v_res - from.angles;
-
- if (v_res.x < 0) v_res.x += 360;
- if (v_res.x > 180) v_res.x -= 360;
-
- if (v_res.y < 0) v_res.y += 360;
- if (v_res.y > 180) v_res.y -= 360;
-
- return v_res;
-}
-
-vector angleofs3(vector from, vector from_a, entity to)
-{
- vector v_res;
-
- v_res = normalize(to.origin - from);
- v_res = vectoangles(v_res);
- v_res = v_res - from_a;
-
- if (v_res.x < 0) v_res.x += 360;
- if (v_res.x > 180) v_res.x -= 360;
-
- if (v_res.y < 0) v_res.y += 360;
- if (v_res.y > 180) v_res.y -= 360;
-
- return v_res;
-}
-
-/*
-* Update self.tur_shotorg by getting up2date bone info
-* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
-*/
-#define turret_tag_fire_update() self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));v_forward = normalize(v_forward)
-float turret_tag_fire_update_s()
-{
- if(!self.tur_head)
- {
- error("Call to turret_tag_fire_update with self.tur_head missing!\n");
- self.tur_shotorg = '0 0 0';
- return false;
- }
-
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
- v_forward = normalize(v_forward);
-
- return true;
-}
-
-/*
-* Railgun-like beam, but has thickness and suppots slowing of target
-*/
-void FireImoBeam (vector start, vector end, vector smin, vector smax,
- float bforce, float f_dmg, float f_velfactor, int deathtype)
-
-{
- vector hitloc, force, endpoint, dir;
- entity ent;
-
- dir = normalize(end - start);
- force = dir * bforce;
-
- // go a little bit into the wall because we need to hit this wall later
- end = end + dir;
-
- // trace multiple times until we hit a wall, each obstacle will be made unsolid.
- // note down which entities were hit so we can damage them later
- while (1)
- {
- tracebox(start, smin, smax, end, false, self);
-
- // if it is world we can't hurt it so stop now
- if (trace_ent == world || trace_fraction == 1)
- break;
-
- if (trace_ent.solid == SOLID_BSP)
- break;
-
- // make the entity non-solid so we can hit the next one
- trace_ent.railgunhit = true;
- trace_ent.railgunhitloc = end;
- trace_ent.railgunhitsolidbackup = trace_ent.solid;
-
- // stop if this is a wall
-
- // make the entity non-solid
- trace_ent.solid = SOLID_NOT;
- }
-
- endpoint = trace_endpos;
-
- // find all the entities the railgun hit and restore their solid state
- ent = findfloat(world, railgunhit, true);
- while (ent)
- {
- // restore their solid type
- ent.solid = ent.railgunhitsolidbackup;
- ent = findfloat(ent, railgunhit, true);
- }
-
- // find all the entities the railgun hit and hurt them
- ent = findfloat(world, railgunhit, true);
- while (ent)
- {
- // get the details we need to call the damage function
- hitloc = ent.railgunhitloc;
- ent.railgunhitloc = '0 0 0';
- ent.railgunhitsolidbackup = SOLID_NOT;
- ent.railgunhit = false;
-
- // apply the damage
- if (ent.takedamage)
- {
- Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
- ent.velocity = ent.velocity * f_velfactor;
- //ent.alpha = 0.25 + random() * 0.75;
- }
-
- // advance to the next entity
- ent = findfloat(ent, railgunhit, true);
- }
- trace_endpos = endpoint;
-}
-
-// Plug this into wherever precache is done.
-void g_turrets_common_precash()
-{
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/marker.md3");
-}
-
-void turrets_precache_debug_models()
-{
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/pathlib/goodsquare.md3");
- precache_model ("models/pathlib/badsquare.md3");
- precache_model ("models/pathlib/square.md3");
- precache_model ("models/pathlib/edge.md3");
-}
-
-void turrets_precash()
-{
- #ifdef TURRET_DEBUG
- turrets_precache_debug_models();
- #endif
-}
-
-
-#ifdef TURRET_DEBUG
-void marker_think()
-{
- if(self.cnt)
- if(self.cnt < time)
- {
- self.think = SUB_Remove;
- self.nextthink = time;
- return;
- }
-
- self.frame += 1;
- if(self.frame > 29)
- self.frame = 0;
-
- self.nextthink = time;
-}
-
-void mark_error(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "error_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 0;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-void mark_info(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "info_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 1;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-entity mark_misc(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "mark_misc";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 3;
- if(lifetime)
- err.cnt = lifetime + time;
- return err;
-}
-
-/*
-* Paint a v_color colord circle on target onwho
-* that fades away over f_time
-*/
-void paint_target(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- //setsize(e, '0 0 0', '0 0 0');
- //setattachment(e,onwho,"");
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
-
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
- e.avelocity_x = -128;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target3(vector where, float f_size, vector v_color, float f_time)
-{
- entity e;
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
- setorigin(e,where+ '0 0 1');
- e.movetype = MOVETYPE_NONE;
- e.velocity = '0 0 0';
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-#endif
+++ /dev/null
-float turret_stdproc_targetscore_support(entity _turret,entity _target)
-{
- float score; // Total score
- float s_score = 0, d_score;
-
- if (_turret.enemy == _target) s_score = 1;
-
- d_score = min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist);
-
- score = (d_score * _turret.target_select_rangebias) +
- (s_score * _turret.target_select_samebias);
-
- return score;
-}
-
-/*
-* Generic bias aware score system.
-*/
-float turret_stdproc_targetscore_generic(entity _turret, entity _target)
-{
- float d_dist; // Defendmode Distance
- float score; // Total score
- float d_score; // Distance score
- float a_score; // Angular score
- float m_score = 0; // missile score
- float p_score = 0; // player score
- float ikr; // ideal kill range
-
- if (_turret.tur_defend)
- {
- d_dist = vlen(real_origin(_target) - _turret.tur_defend.origin);
- ikr = vlen(_turret.origin - _turret.tur_defend.origin);
- d_score = 1 - d_dist / _turret.target_range;
- }
- else
- {
- // Make a normlized value base on the targets distance from our optimal killzone
- ikr = _turret.target_range_optimal;
- d_score = min(ikr, tvt_dist) / max(ikr, tvt_dist);
- }
-
- a_score = 1 - tvt_thadf / _turret.aim_maxrot;
-
- if ((_turret.target_select_missilebias > 0) && (_target.flags & FL_PROJECTILE))
- m_score = 1;
-
- if ((_turret.target_select_playerbias > 0) && IS_CLIENT(_target))
- p_score = 1;
-
- d_score = max(d_score, 0);
- a_score = max(a_score, 0);
- m_score = max(m_score, 0);
- p_score = max(p_score, 0);
-
- score = (d_score * _turret.target_select_rangebias) +
- (a_score * _turret.target_select_anglebias) +
- (m_score * _turret.target_select_missilebias) +
- (p_score * _turret.target_select_playerbias);
-
- if(_turret.target_range < vlen(_turret.tur_shotorg - real_origin(_target)))
- {
- //dprint("Wtf?\n");
- score *= 0.001;
- }
-
-#ifdef TURRET_DEBUG
- string sd,sa,sm,sp,ss;
- string sdt,sat,smt,spt;
-
- sd = ftos(d_score);
- d_score *= _turret.target_select_rangebias;
- sdt = ftos(d_score);
-
- //sv = ftos(v_score);
- //v_score *= _turret.target_select_samebias;
- //svt = ftos(v_score);
-
- sa = ftos(a_score);
- a_score *= _turret.target_select_anglebias;
- sat = ftos(a_score);
-
- sm = ftos(m_score);
- m_score *= _turret.target_select_missilebias;
- smt = ftos(m_score);
-
- sp = ftos(p_score);
- p_score *= _turret.target_select_playerbias;
- spt = ftos(p_score);
-
-
- ss = ftos(score);
- bprint("^3Target scores^7 \[ ",_turret.netname, " \] ^3for^7 \[ ", _target.netname," \]\n");
- bprint("^5Range:\[ ",sd, " \]^2+bias:\[ ",sdt," \]\n");
- bprint("^5Angle:\[ ",sa, " \]^2+bias:\[ ",sat," \]\n");
- bprint("^5Missile:\[ ",sm," \]^2+bias:\[ ",smt," \]\n");
- bprint("^5Player:\[ ",sp, " \]^2+bias:\[ ",spt," \]\n");
- bprint("^3Total (w/bias):\[^1",ss,"\]\n");
-
-#endif
-
- return score;
-}
-
-/*
-float turret_stdproc_targetscore_close(entity _turret,entity _target)
-{
- return 1 - (tvt_dist / _turret.target_range);
-}
-
-float turret_stdproc_targetscore_far (entity _turret,entity _target)
-{
- return tvt_dist / _turret.target_range;
-}
-
-float turret_stdproc_targetscore_optimal(entity _turret,entity _target)
-{
- return min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist);
-}
-
-float turret_stdproc_score_angular(entity _turret,entity _target)
-{
- return 1 - (tvt_thadf / _turret.aim_maxrot);
-}
-
-float turret_stdproc_targetscore_defend(entity _turret,entity _target)
-{
- return 0;
- //min(_target.origin,_turret.tur_defend.origin) / max(_target.origin,_turret.tur_defend.origin);
-}
-*/
+++ /dev/null
-/**
- turret_checkpoint
-**/
-
-
-//.entity checkpoint_target;
-
-/*
-#define checkpoint_cache_who flagcarried
-#define checkpoint_cache_from lastrocket
-#define checkpoint_cache_to selected_player
-*/
-
-.entity pathgoal;
-.entity pathcurrent;
-
-/*
-entity path_makeorcache(entity forwho,entity start, entity end)
-{
- entity oldself;
- entity pth;
- oldself = self;
- self = forwho;
-
- //pth = pathlib_makepath(start.origin,end.origin,PFL_GROUNDSNAP,500,1.5,PT_QUICKSTAR);
-
- self = oldself;
- return pth;
-}
-*/
-
-void turret_checkpoint_use()
-{
-}
-
-#if 0
-void turret_checkpoint_think()
-{
- if(self.enemy)
- te_lightning1(self,self.origin, self.enemy.origin);
-
- self.nextthink = time + 0.25;
-}
-#endif
-/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
------------KEYS------------
-target: .targetname of next waypoint in chain.
-wait: Pause at this point # seconds.
------------SPAWNFLAGS-----------
----------NOTES----------
-If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
-If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
-*/
-//float tc_acum;
-void turret_checkpoint_init()
-{
- traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self);
- setorigin(self, trace_endpos + '0 0 32');
-
- if(self.target != "")
- {
- self.enemy = find(world, targetname, self.target);
- if(self.enemy == world)
- dprint("A turret_checkpoint faild to find its target!\n");
- }
- //self.think = turret_checkpoint_think;
- //self.nextthink = time + tc_acum + 0.25;
- //tc_acum += 0.25;
-}
-
-void spawnfunc_turret_checkpoint()
-{
- setorigin(self,self.origin);
- self.think = turret_checkpoint_init;
- self.nextthink = time + 0.2;
-}
-
-// Compat.
-void spawnfunc_walker_checkpoint()
-{
- self.classname = "turret_checkpoint";
- spawnfunc_turret_checkpoint();
-}
+++ /dev/null
-#include "../../bot/navigation.qh"
-
-const float ewheel_amin_stop = 0;
-const float ewheel_amin_fwd_slow = 1;
-const float ewheel_amin_fwd_fast = 2;
-const float ewheel_amin_bck_slow = 3;
-const float ewheel_amin_bck_fast = 4;
-
-void ewheel_attack()
-{
- float i;
- entity _mis;
-
- for (i = 0; i < 1; ++i)
- {
- turret_do_updates(self);
-
- _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
- _mis.missile_flags = MIF_SPLASH;
-
- Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- self.tur_head.frame += 2;
-
- if (self.tur_head.frame > 3)
- self.tur_head.frame = 0;
- }
-
-}
-//#define EWHEEL_FANCYPATH
-void ewheel_move_path()
-{
-#ifdef EWHEEL_FANCYPATH
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-#endif
-
- if (self.pathcurrent)
- {
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4);
- }
-}
-
-void ewheel_move_enemy()
-{
-
- float newframe;
-
- self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
-
- //self.steerto = steerlib_standoff(self.enemy.origin,self.target_range_optimal);
- //self.steerto = steerlib_beamsteer(self.steerto,1024,64,68,256);
- self.moveto = self.origin + self.steerto * 128;
-
- if (self.tur_dist_enemy > self.target_range_optimal)
- {
- if ( self.tur_head.spawnshieldtime < 1 )
- {
- newframe = ewheel_amin_fwd_fast;
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4);
- }
- else if (self.tur_head.spawnshieldtime < 2)
- {
-
- newframe = ewheel_amin_fwd_slow;
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4);
- }
- else
- {
- newframe = ewheel_amin_fwd_slow;
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slower, 0.4);
- }
- }
- else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
- {
- newframe = ewheel_amin_bck_slow;
- movelib_move_simple(v_forward * -1, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4);
- }
- else
- {
- newframe = ewheel_amin_stop;
- movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop);
- }
-
- turrets_setframe(newframe , false);
-
- /*if(self.frame != newframe)
- {
- self.frame = newframe;
- self.SendFlags |= TNSF_ANIM;
- self.anim_start_time = time;
- }*/
-}
-
-
-void ewheel_move_idle()
-{
- if(self.frame != 0)
- {
- self.SendFlags |= TNSF_ANIM;
- self.anim_start_time = time;
- }
-
- self.frame = 0;
- if (vlen(self.velocity))
- movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop);
-}
-
-void ewheel_postthink()
-{
- float vz;
- vector wish_angle, real_angle;
-
- vz = self.velocity.z;
-
- self.angles_x = anglemods(self.angles.x);
- self.angles_y = anglemods(self.angles.y);
-
- fixedmakevectors(self.angles);
-
- wish_angle = normalize(self.steerto);
- wish_angle = vectoangles(wish_angle);
- real_angle = wish_angle - self.angles;
- real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
-
- self.tur_head.spawnshieldtime = fabs(real_angle.y);
- real_angle.y = bound(-self.tur_head.aim_speed, real_angle.y, self.tur_head.aim_speed);
- self.angles_y = (self.angles.y + real_angle.y);
-
- if(self.enemy)
- ewheel_move_enemy();
- else if(self.pathcurrent)
- ewheel_move_path();
- else
- ewheel_move_idle();
-
-
- self.velocity_z = vz;
-
- if(vlen(self.velocity))
- self.SendFlags |= TNSF_MOVE;
-}
-
-void ewheel_respawnhook()
-{
- entity e;
-
- // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
- if(self.movetype != MOVETYPE_WALK)
- return;
-
- self.velocity = '0 0 0';
- self.enemy = world;
-
- setorigin(self, self.pos1);
-
- if (self.target != "")
- {
- e = find(world,targetname,self.target);
- if (!e)
- {
- dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- {
-
-#ifdef EWHEEL_FANCYPATH
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-}
-
-void ewheel_diehook()
-{
- self.velocity = '0 0 0';
-
-#ifdef EWHEEL_FANCYPATH
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-}
-
-void turret_ewheel_dinit()
-{
- entity e;
-
- if (self.netname == "")
- self.netname = "eWheel Turret";
-
- if (self.target != "")
- {
- e = find(world,targetname,self.target);
- if (!e)
- {
- bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- self.goalcurrent = e;
- }
-
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM ;
- self.turret_respawnhook = ewheel_respawnhook;
-
- self.turret_diehook = ewheel_diehook;
-
- if (turret_stdproc_init("ewheel_std", "models/turrets/ewheel-base2.md3", "models/turrets/ewheel-gun1.md3", TID_EWHEEL) == 0)
- {
- remove(self);
- return;
- }
-
- self.frame = 1;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- self.idle_aim = '0 0 0';
- self.pos1 = self.origin;
-
- setsize(self, '-32 -32 0', '32 32 48');
-
- // Our fire routine
- self.turret_firefunc = ewheel_attack;
- self.turret_postthink = ewheel_postthink;
- self.tur_head.frame = 1;
-
- // Convert from dgr / sec to dgr / tic
- self.tur_head.aim_speed = autocvar_g_turrets_unit_ewheel_turnrate;
- self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
-
- //setorigin(self,self.origin + '0 0 128');
- if (self.target != "")
- {
- e = find(world,targetname,self.target);
- if (!e)
- {
- dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- {
-#ifdef EWHEEL_FANCYPATH
- self.pathcurrent = WALKER_PATH(self.origin, e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-}
-
-void spawnfunc_turret_ewheel()
-{
- g_turrets_common_precash();
-
- precache_model ("models/turrets/ewheel-base2.md3");
- precache_model ("models/turrets/ewheel-gun1.md3");
-
- self.think = turret_ewheel_dinit;
- self.nextthink = time + 0.5;
-}
+++ /dev/null
-void spawnfunc_turret_flac();
-void turret_flac_dinit();
-void turret_flac_attack();
-
-void turret_flac_projectile_think_explode()
-{
- if(self.enemy != world)
- if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
- setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
-
-#ifdef TURRET_DEBUG
- float d;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-#endif
- remove(self);
-}
-
-void turret_flac_attack()
-{
- entity proj;
-
- turret_tag_fire_update();
-
- proj = turret_projectile("weapons/hagar_fire.wav", 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, true, true);
- Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- proj.think = turret_flac_projectile_think_explode;
- proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
- proj.missile_flags = MIF_SPLASH | MIF_PROXY;
-
- self.tur_head.frame = self.tur_head.frame + 1;
- if (self.tur_head.frame >= 4)
- self.tur_head.frame = 0;
-
-}
-
-void turret_flac_dinit()
-{
- if (self.netname == "")
- self.netname = "FLAC Cannon";
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_MISSILEKILL;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- if (turret_stdproc_init("flac_std", "models/turrets/base.md3", "models/turrets/flac.md3", TID_FLAC) == 0)
- {
- remove(self);
- return;
- }
- setsize(self.tur_head,'-32 -32 0','32 32 64');
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
-
- // Our fire routine
- self.turret_firefunc = turret_flac_attack;
-
-}
-/*QUAKED turret_flac (0 .5 .8) ?
-*/
-
-void spawnfunc_turret_flac()
-{
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/flac.md3");
-
- self.think = turret_flac_dinit;
- self.nextthink = time + 0.5;
-}
-
+++ /dev/null
-void spawnfunc_turret_fusionreactor();
-void turret_fusionreactor_dinit();
-void turret_fusionreactor_fire();
-
-void turret_fusionreactor_fire()
-{
- vector fl_org;
-
- self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
- fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
- te_smallflash(fl_org);
-}
-
-void turret_fusionreactor_postthink()
-{
- self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
-}
-
-/*
-void turret_fusionreactor_respawnhook()
-{
- self.tur_head.avelocity = '0 50 0';
-}
-*/
-
-/**
-** Preforms pre-fire checks for fusionreactor
-**/
-float turret_fusionreactor_firecheck()
-{
- if (self.attack_finished_single > time)
- return 0;
-
- if (self.enemy.deadflag != DEAD_NO)
- return 0;
-
- if (self.enemy == world)
- return 0;
-
- if (self.ammo < self.shot_dmg)
- return 0;
-
- if (self.enemy.ammo >= self.enemy.ammo_max)
- return 0;
-
- if (vlen(self.enemy.origin - self.origin) > self.target_range)
- return 0;
-
- if(self.team != self.enemy.team)
- return 0;
-
- if (!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
- return 0;
-
- return 1;
-}
-
-void turret_fusionreactor_dinit()
-{
- if (self.netname == "") self.netname = "Fusionreactor";
-
- self.turrcaps_flags = TFL_TURRCAPS_SUPPORT | TFL_TURRCAPS_AMMOSOURCE;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
- self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMTS;
- self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
- self.shoot_flags = TFL_SHOOT_HITALLVALID;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
- // self.turret_respawnhook = turret_fusionreactor_respawnhook;
-
- if (turret_stdproc_init("fusreac_std", "models/turrets/base.md3", "models/turrets/reactor.md3", TID_FUSION) == 0)
- {
- remove(self);
- return;
- }
- self.tur_head.scale = 0.75;
- self.tur_head.avelocity = '0 50 0';
- setsize(self,'-34 -34 0','34 34 90');
-
- self.turret_firecheckfunc = turret_fusionreactor_firecheck;
- self.turret_firefunc = turret_fusionreactor_fire;
- self.turret_postthink = turret_fusionreactor_postthink;
-}
-
-/*QUAKED turret_fusionreactor (0 .5 .8) ?
-*/
-void spawnfunc_turret_fusionreactor()
-{
- precache_model ("models/turrets/reactor.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_fusionreactor_dinit;
- self.nextthink = time + 0.5;
-}
+++ /dev/null
-void spawnfunc_turret_hellion();
-void turret_hellion_dinit();
-void turret_hellion_attack();
-
-void turret_hellion_missile_think()
-{
- vector olddir,newdir;
- vector pre_pos;
- float itime;
-
- self.nextthink = time + 0.05;
-
- olddir = normalize(self.velocity);
-
- if(self.tur_health < time)
- turret_projectile_explode();
-
- // Enemy dead? just keep on the current heading then.
- if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
- {
-
- // Make sure we dont return to tracking a respawned player
- self.enemy = world;
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
- turret_projectile_explode();
-
- // Accelerate
- self.velocity = olddir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max);
-
- UpdateCSQCProjectile(self);
-
- return;
- }
-
- // Enemy in range?
- if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
- turret_projectile_explode();
-
- // Predict enemy position
- itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
- pre_pos = self.enemy.origin + self.enemy.velocity * itime;
-
- pre_pos = (pre_pos + self.enemy.origin) * 0.5;
-
- // Find out the direction to that place
- newdir = normalize(pre_pos - self.origin);
-
- // Turn
- newdir = normalize(olddir + newdir * 0.35);
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- // Accelerate
- self.velocity = newdir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max);
-
- if (itime < 0.05)
- self.think = turret_projectile_explode;
-
- UpdateCSQCProjectile(self);
-}
-void turret_hellion_attack()
-{
- entity missile;
-
- if(self.tur_head.frame != 0)
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
- else
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
-
- missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, false, false);
- te_explosion (missile.origin);
- missile.think = turret_hellion_missile_think;
- missile.nextthink = time;
- missile.flags = FL_PROJECTILE;
- missile.tur_health = time + 9;
- missile.tur_aimpos = randomvec() * 128;
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
- self.tur_head.frame += 1;
-}
-
-void turret_hellion_postthink()
-{
- if (self.tur_head.frame != 0)
- self.tur_head.frame += 1;
-
- if (self.tur_head.frame >= 7)
- self.tur_head.frame = 0;
-}
-
-void turret_hellion_dinit()
-{
- if (self.netname == "") self.netname = "Hellion Missile Turret";
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK ;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
- if (turret_stdproc_init("hellion_std", "models/turrets/base.md3", "models/turrets/hellion.md3", TID_HELLION) == 0)
- {
- remove(self);
- return;
- }
-
- self.turret_firefunc = turret_hellion_attack;
- self.turret_postthink = turret_hellion_postthink;
-}
-
-/*QUAKED turret_hellion (0 .5 .8) ?
-*/
-void spawnfunc_turret_hellion()
-{
- precache_model ("models/turrets/hellion.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_hellion_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+++ /dev/null
-//#define TURRET_DEBUG_HK
-
-#ifdef TURRET_DEBUG_HK
-.float atime;
-#endif
-
-void spawnfunc_turret_hk();
-void turret_hk_dinit();
-void turret_hk_attack();
-
-
-float hk_is_valid_target(entity e_target)
-{
- if (e_target == world)
- return 0;
-
- // If only this was used more..
- if (e_target.flags & FL_NOTARGET)
- return 0;
-
- // Cant touch this
- if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
- return 0;
-
- // player
- if (IS_CLIENT(e_target))
- {
- if (self.owner.target_select_playerbias < 0)
- return 0;
-
- if (e_target.deadflag != DEAD_NO)
- return 0;
- }
-
- // Missile
- if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
- return 0;
-
- // Team check
- if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
- return 0;
-
- return 1;
-}
-void turret_hk_missile_think()
-{
- vector vu, vd, vf, vl, vr, ve; // Vector (direction)
- float fu, fd, ff, fl, fr, fe; // Fraction to solid
- vector olddir,wishdir,newdir; // Final direction
- float lt_for; // Length of Trace FORwrad
- float lt_seek; // Length of Trace SEEK (left, right, up down)
- float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
- vector pre_pos;
- float myspeed;
- entity e;
- float ad,edist;
-
- self.nextthink = time + self.ticrate;
-
- //if (self.cnt < time)
- // turret_hk_missile_explode();
-
- if (self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- // Pick the closest valid target.
- if (!self.enemy)
- {
- e = findradius(self.origin, 5000);
- while (e)
- {
- if (hk_is_valid_target(e))
- {
- if (!self.enemy)
- self.enemy = e;
- else
- if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
- self.enemy = e;
- }
- e = e.chain;
- }
- }
-
- self.angles = vectoangles(self.velocity);
- self.angles_x = self.angles.x * -1;
- makevectors(self.angles);
- self.angles_x = self.angles.x * -1;
-
- if (self.enemy)
- {
- edist = vlen(self.origin - self.enemy.origin);
- // Close enougth to do decent damage?
- if ( edist <= (self.owner.shot_radius * 0.25) )
- {
- turret_projectile_explode();
- return;
- }
-
- // Get data on enemy position
- pre_pos = self.enemy.origin +
- self.enemy.velocity *
- min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
-
- traceline(self.origin, pre_pos,true,self.enemy);
- ve = normalize(pre_pos - self.origin);
- fe = trace_fraction;
-
- }
- else
- {
- edist = 0;
- ve = '0 0 0';
- fe = 0;
- }
-
- if ((fe != 1) || (self.enemy == world) || (edist > 1000))
- {
- myspeed = vlen(self.velocity);
-
- lt_for = myspeed * 3;
- lt_seek = myspeed * 2.95;
-
- // Trace forward
- traceline(self.origin, self.origin + v_forward * lt_for,false,self);
- vf = trace_endpos;
- ff = trace_fraction;
-
- // Find angular offset
- ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
-
- // To close to something, Slow down!
- if ( ((ff < 0.7) || (ad > 4)) && (myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) )
- myspeed = max(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_decel, autocvar_g_turrets_unit_hk_std_shot_speed);
-
- // Failry clear, accelerate.
- if ( (ff > 0.7) && (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max) )
- myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel, autocvar_g_turrets_unit_hk_std_shot_speed_max);
-
- // Setup trace pitch
- pt_seek = 1 - ff;
- pt_seek = bound(0.15,pt_seek,0.8);
- if (ff < 0.5) pt_seek = 1;
-
- // Trace left
- traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
- vl = trace_endpos;
- fl = trace_fraction;
-
- // Trace right
- traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vr = trace_endpos;
- fr = trace_fraction;
-
- // Trace up
- traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vu = trace_endpos;
- fu = trace_fraction;
-
- // Trace down
- traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vd = trace_endpos;
- fd = trace_fraction;
-
- vl = normalize(vl - self.origin);
- vr = normalize(vr - self.origin);
- vu = normalize(vu - self.origin);
- vd = normalize(vd - self.origin);
-
- // Panic tresh passed, find a single direction and turn as hard as we can
- if (pt_seek == 1)
- {
- wishdir = v_right;
- if (fl > fr) wishdir = -1 * v_right;
- if (fu > fl) wishdir = v_up;
- if (fd > fu) wishdir = -1 * v_up;
- }
- else
- {
- // Normalize our trace vectors to make a smooth path
- wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
- }
-
- if (self.enemy)
- {
- if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
- wishdir = (wishdir * (1 - fe)) + (ve * fe);
- }
- }
- else
- {
- // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
- myspeed = vlen(self.velocity);
- if (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max)
- myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max);
-
- wishdir = ve;
- }
-
- if ((myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) && (self.cnt > time))
- myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max);
-
- // Ranoutagazfish?
- if (self.cnt < time)
- {
- self.cnt = time + 0.25;
- self.nextthink = 0;
- self.movetype = MOVETYPE_BOUNCE;
- return;
- }
-
- // Calculate new heading
- olddir = normalize(self.velocity);
- newdir = normalize(olddir + wishdir * autocvar_g_turrets_unit_hk_std_shot_speed_turnrate);
-
- // Set heading & speed
- self.velocity = newdir * myspeed;
-
- // Align model with new heading
- self.angles = vectoangles(self.velocity);
-
-
-#ifdef TURRET_DEBUG_HK
- //if(self.atime < time) {
- if ((fe <= 0.99)||(edist > 1000))
- {
- te_lightning2(world,self.origin, self.origin + vr * lt_seek);
- te_lightning2(world,self.origin, self.origin + vl * lt_seek);
- te_lightning2(world,self.origin, self.origin + vu * lt_seek);
- te_lightning2(world,self.origin, self.origin + vd * lt_seek);
- te_lightning2(world,self.origin, vf);
- }
- else
- {
- te_lightning2(world,self.origin, self.enemy.origin);
- }
- bprint("Speed: ", ftos(rint(myspeed)), "\n");
- bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
- bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
- self.atime = time + 0.2;
- //}
-#endif
-
- UpdateCSQCProjectile(self);
-}
-
-void turret_hk_attack()
-{
- entity missile;
-
- missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, false, false);
- te_explosion (missile.origin);
-
- missile.think = turret_hk_missile_think;
- missile.nextthink = time + 0.25;
- missile.movetype = MOVETYPE_BOUNCEMISSILE;
- missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
- missile.angles = vectoangles(missile.velocity);
- missile.cnt = time + 30;
- missile.ticrate = max(autocvar_sys_ticrate, 0.05);
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
-}
-
-void turret_hk_postthink()
-{
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-}
-
-float turret_hk_addtarget(entity e_target,entity e_sender)
-{
- if (e_target)
- {
- if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
- {
- self.enemy = e_target;
- return 1;
- }
- }
-
- return 0;
-}
-
-void turret_hk_dinit()
-{
- if (self.netname == "")
- self.netname = "Hunter-killer turret";
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_RECIVETARGETS;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
- self.shoot_flags = TFL_SHOOT_CLEARTARGET;
-
- if (turret_stdproc_init("hk_std", "models/turrets/base.md3", "models/turrets/hk.md3", TID_HK) == 0)
- {
- remove(self);
- return;
- }
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
-
- // Our fire routine
- self.turret_firefunc = turret_hk_attack;
-
- // re-color badge & handle recoil effect
- self.turret_postthink = turret_hk_postthink;
-
- // What to do when reciveing foreign target data
- self.turret_addtarget = turret_hk_addtarget;
-}
-
-
-/*QUAKED turret_hk (0 .5 .8) ?
-* Turret that fires Hunter-killer missiles.
-* Missiles seek their target and try to avoid obstacles. If target dies early, they
-* pick a new one on their own.
-*/
-
-void spawnfunc_turret_hk()
-{
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/hk.md3");
-
- self.think = turret_hk_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+++ /dev/null
-void W_MachineGun_MuzzleFlash(void);
-
-void spawnfunc_turret_machinegun();
-void turret_machinegun_std_init();
-void turret_machinegun_attack();
-
-//.float bulletcounter;
-void turret_machinegun_attack()
-{
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
-
- W_MachineGun_MuzzleFlash(); // WEAPONTODO
- setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
-}
-
-
-void turret_machinegun_std_init()
-{
- if (self.netname == "") self.netname = "Machinegun Turret";
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
-
- if (turret_stdproc_init("machinegun_std", "models/turrets/base.md3", "models/turrets/machinegun.md3", TID_MACHINEGUN) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- // Our fire routine
- self.turret_firefunc = turret_machinegun_attack;
-
-}
-
-
-/*QUAKED turret_machinegun (0 .5 .8) ?
-* machinegun turret. does what you'd expect
-*/
-void spawnfunc_turret_machinegun()
-{
- precache_model ("models/turrets/machinegun.md3");
- precache_model ("models/turrets/base.md3");
- precache_sound ("weapons/uzi_fire.wav");
-
- self.think = turret_machinegun_std_init;
- self.nextthink = time + 0.5;
-}
-
+++ /dev/null
-void spawnfunc_turret_mlrs();
-void turret_mlrs_dinit();
-void turret_mlrs_attack();
-
-void turret_mlrs_postthink()
-{
- // 0 = full, 6 = empty
- self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
- if(self.tur_head.frame < 0)
- {
- dprint("ammo:",ftos(self.ammo),"\n");
- dprint("shot_dmg:",ftos(self.shot_dmg),"\n");
- }
-}
-
-void turret_mlrs_attack()
-{
- entity missile;
-
- turret_tag_fire_update();
- missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, true, true);
- missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
- missile.missile_flags = MIF_SPLASH;
- te_explosion (missile.origin);
-}
-
-void turret_mlrs_dinit()
-{
- if (self.netname == "") self.netname = "MLRS turret";
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- if (turret_stdproc_init("mlrs_std", "models/turrets/base.md3", "models/turrets/mlrs.md3", TID_MLRS) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
- self.volly_counter = self.shot_volly;
-
- // Our fire routine
- self.turret_firefunc = turret_mlrs_attack;
- self.turret_postthink = turret_mlrs_postthink;
-
-}
-
-/*QUAKED turret_mlrs (0 .5 .8) ?
-*/
-
-void spawnfunc_turret_mlrs()
-{
- precache_model ("models/turrets/mlrs.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_mlrs_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+++ /dev/null
-#include "../../_all.qh"
-
-void spawnfunc_turret_phaser();
-void turret_phaser_dinit();
-void turret_phaser_attack();
-
-.float fireflag;
-
-float turret_phaser_firecheck()
-{
- if (self.fireflag != 0) return 0;
- return turret_stdproc_firecheck();
-}
-
-void turret_phaser_postthink()
-{
- if (self.tur_head.frame == 0)
- return;
-
- if (self.fireflag == 1)
- {
- if (self.tur_head.frame == 10)
- self.tur_head.frame = 1;
- else
- self.tur_head.frame = self.tur_head.frame +1;
- }
- else if (self.fireflag == 2 )
- {
- self.tur_head.frame = self.tur_head.frame +1;
- if (self.tur_head.frame == 15)
- {
- self.tur_head.frame = 0;
- self.fireflag = 0;
- }
- }
-}
-
-void beam_think()
-{
- if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
- {
- self.owner.attack_finished_single = time + self.owner.shot_refire;
- self.owner.fireflag = 2;
- self.owner.tur_head.frame = 10;
- sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
- remove(self);
- return;
- }
-
- turret_do_updates(self.owner);
-
- if (time - self.shot_spread > 0)
- {
- self.shot_spread = time + 2;
- sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
- }
-
-
- self.nextthink = time + self.ticrate;
-
- self.owner.attack_finished_single = time + frametime;
- entity oldself;
- oldself = self;
- self = self.owner;
- FireImoBeam ( self.tur_shotorg,
- self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
- '-1 -1 -1' * self.shot_radius,
- '1 1 1' * self.shot_radius,
- self.shot_force,
- oldself.shot_dmg,
- 0.75,
- DEATH_TURRET_PHASER);
- self = oldself;
- self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
-
-}
-
-void turret_phaser_attack()
-{
- entity beam;
-
- beam = spawn();
- beam.ticrate = 0.1; //autocvar_sys_ticrate;
- setmodel(beam,"models/turrets/phaser_beam.md3");
- beam.effects = EF_LOWPRECISION;
- beam.solid = SOLID_NOT;
- beam.think = beam_think;
- beam.cnt = time + self.shot_speed;
- beam.shot_spread = time + 2;
- beam.nextthink = time;
- beam.owner = self;
- beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
- beam.scale = self.target_range / 256;
- beam.movetype = MOVETYPE_NONE;
- beam.enemy = self.enemy;
- beam.bot_dodge = true;
- beam.bot_dodgerating = beam.shot_dmg;
- sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
- self.fireflag = 1;
-
- beam.attack_finished_single = self.attack_finished_single;
- self.attack_finished_single = time; // + autocvar_sys_ticrate;
-
- setattachment(beam,self.tur_head,"tag_fire");
-
- soundat (self, trace_endpos, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-}
-
-void turret_phaser_dinit()
-{
- if (self.netname == "") self.netname = "Phaser Cannon";
-
- self.turrcaps_flags = TFL_TURRCAPS_SNIPER|TFL_TURRCAPS_HITSCAN|TFL_TURRCAPS_PLAYERKILL;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.aim_flags = TFL_AIM_LEAD;
-
- if (turret_stdproc_init("phaser_std", "models/turrets/base.md3","models/turrets/phaser.md3", TID_PHASER) == 0)
- {
- remove(self);
- return;
- }
-
- self.turret_firecheckfunc = turret_phaser_firecheck;
- self.turret_firefunc = turret_phaser_attack;
- self.turret_postthink = turret_phaser_postthink;
-
-}
-
-/*QUAKED turret_phaser(0 .5 .8) ?
-*/
-void spawnfunc_turret_phaser()
-{
- precache_sound ("turrets/phaser.wav");
- precache_model ("models/turrets/phaser.md3");
- precache_model ("models/turrets/phaser_beam.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_phaser_dinit;
- self.nextthink = time + 0.5;
-}
-
+++ /dev/null
-void spawnfunc_turret_plasma();
-void spawnfunc_turret_plasma_dual();
-
-void turret_plasma_std_init();
-void turret_plasma_dual_init();
-
-void turret_plasma_attack();
-
-
-void turret_plasma_postthink()
-{
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-}
-
-void turret_plasma_dual_postthink()
-{
- if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 6)
- self.tur_head.frame = 0;
-}
-
-void turret_plasma_minsta_attack (void)
-{
- float flying;
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
- FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
- 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
-
- Send_Effect("nex_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v;
- v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- if(teamplay)
- {
- switch(self.team)
- {
- case NUM_TEAM_1: // Red
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_2: // Blue
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_3: // Yellow
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_4: // Pink
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), self.tur_shotorg, v);
- break;
- }
- }
- else
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), self.tur_shotorg, v);
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-}
-
-void turret_plasma_attack()
-{
- entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, true, true);
- missile.missile_flags = MIF_SPLASH;
-
- Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-}
-
-void turret_plasma_dual_attack()
-{
- entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, true, true);
- missile.missile_flags = MIF_SPLASH;
- Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- self.tur_head.frame += 1;
-}
-
-void turret_plasma_std_init()
-{
- if (self.netname == "") self.netname = "Plasma Cannon";
-
- // What ammo to use
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
-
- // How to aim
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND;
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
-
- if (turret_stdproc_init("plasma_std", "models/turrets/base.md3", "models/turrets/plasma.md3", TID_PLASMA) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
-
- // Our fireing routine
- if(g_instagib)
- self.turret_firefunc = turret_plasma_minsta_attack;
- else
- self.turret_firefunc = turret_plasma_attack;
-
- // Custom per turret frame stuff. usualy animation.
- self.turret_postthink = turret_plasma_postthink;
- turret_do_updates(self);
-}
-
-
-void turret_plasma_dual_init()
-{
- if (self.netname == "") self.netname = "Dual Plasma Cannon";
-
- // What ammo to use
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
-
- // How to aim at targets
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND ;
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
-
- if (turret_stdproc_init("plasma_dual", "models/turrets/base.md3", "models/turrets/plasmad.md3", TID_PLASMA_DUAL) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
-
- // Our fireing routine
- self.turret_firefunc = turret_plasma_dual_attack;
-
- // Custom per turret frame stuff. usualy animation.
- self.turret_postthink = turret_plasma_dual_postthink;
-}
-
-
-/*
-* Basic moderate (std) or fast (dual) fireing, short-mid range energy cannon.
-* Not too mutch of a therat on its own, but can be rather dangerous in groups.
-* Regenerates ammo slowly, support with a fusionreactor(s) to do some real damage.
-*/
-
-/*QUAKED turret_plasma (0 .5 .8) ?
-*/
-void spawnfunc_turret_plasma()
-{
- g_turrets_common_precash();
- precache_model ("models/turrets/plasma.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_plasma_std_init;
- self.nextthink = time + 0.5;
-}
-
-/*QUAKED turret_plasma_dual (0 .5 .8) ?
-*/
-void spawnfunc_turret_plasma_dual()
-{
-
- precache_model ("models/turrets/plasmad.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_plasma_dual_init;
- self.nextthink = time + 0.5;
-}
-
+++ /dev/null
-void spawnfunc_turret_targettrigger();
-void turret_targettrigger_touch();
-
-void turret_targettrigger_touch()
-{
- entity e;
- if (self.cnt > time) return;
- entity oldself;
- oldself = self;
-
- e = find(world, targetname, self.target);
- while (e)
- {
- if (e.turrcaps_flags & TFL_TURRCAPS_RECIVETARGETS)
- {
- self = e;
- if(e.turret_addtarget)
- e.turret_addtarget(other,oldself);
- }
-
- e = find(e, targetname, oldself.target);
- }
-
- oldself.cnt = time + 0.5;
-
- self = oldself;
-}
-
-/*QUAKED turret_targettrigger (.5 .5 .5) ?
-*/
-void spawnfunc_turret_targettrigger()
-{
- if (!autocvar_g_turrets)
- {
- remove(self);
- return;
- }
-
- InitTrigger ();
-
- self.touch = turret_targettrigger_touch;
-}
+++ /dev/null
-#include "../../csqceffects.qh"
-
-void spawnfunc_turret_tesla();
-void turret_tesla_dinit();
-void turret_tesla_fire();
-
-entity toast(entity from, float range, float damage)
-{
- entity e;
- entity etarget = world;
- float d,dd;
- float r;
-
- dd = range + 1;
-
- e = findradius(from.origin,range);
- while (e)
- {
- if ((e.railgunhit != 1) && (e != from))
- {
- r = turret_validate_target(self,e,self.target_validate_flags);
- if (r > 0)
- {
- traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
- if (trace_fraction == 1.0)
- {
- d = vlen(e.origin - from.origin);
- if (d < dd)
- {
- dd = d;
- etarget = e;
- }
- }
- }
- }
- e = e.chain;
- }
-
- if (etarget)
- {
- te_csqc_lightningarc(from.origin,etarget.origin);
- Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
- etarget.railgunhit = 1;
- }
-
- return etarget;
-}
-
-float turret_tesla_firecheck()
-{
- // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan = 0;
-
- if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
- do_target_scan = 1;
-
- // Old target (if any) invalid?
- if(self.target_validate_time < time)
- if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
- {
- self.enemy = world;
- self.target_validate_time = time + 0.5;
- do_target_scan = 1;
- }
-
- // But never more often then g_turrets_targetscan_mindelay!
- if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
- do_target_scan = 0;
-
- if(do_target_scan)
- {
- self.enemy = turret_select_target();
- self.target_select_time = time;
- }
-
- if (!turret_stdproc_firecheck())
- return 0;
-
- if(self.enemy)
- return 1;
-
- return 0;
-}
-
-
-void turret_tesla_fire()
-{
- entity e, t;
- float d, r, i;
-
- d = self.shot_dmg;
- r = self.target_range;
- e = spawn();
- setorigin(e,self.tur_shotorg);
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- t = toast(e,r,d);
- remove(e);
-
- if (t == world) return;
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
-
- self.attack_finished_single = time + self.shot_refire;
- for (i = 0; i < 10; ++i)
- {
- d *= 0.75;
- r *= 0.85;
- t = toast(t, r, d);
- if (t == world) break;
-
- }
-
- e = findchainfloat(railgunhit, 1);
- while (e)
- {
- e.railgunhit = 0;
- e = e.chain;
- }
-}
-
-void turret_tesla_postthink()
-{
- if (!self.active)
- {
- self.tur_head.avelocity = '0 0 0';
- return;
- }
-
- if(self.ammo < self.shot_dmg)
- {
- self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
- }
- else
- {
- self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
-
- if(self.attack_finished_single > time)
- return;
-
- float f;
- f = (self.ammo / self.ammo_max);
- f = f * f;
- if(f > random())
- if(random() < 0.1)
- te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
- }
-}
-
-
-void turret_tesla_dinit()
-{
- if (self.netname == "") self.netname = "Tesla Coil";
-
- self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_OWM_AMMO;
- self.shoot_flags = TFL_SHOOT_CUSTOM;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- if (turret_stdproc_init("tesla_std", "models/turrets/tesla_base.md3", "models/turrets/tesla_head.md3", TID_TESLA) == 0)
- {
- remove(self);
- return;
- }
- setsize(self,'-60 -60 0','60 60 128');
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.turret_firefunc = turret_tesla_fire;
- self.turret_postthink = turret_tesla_postthink;
- self.turret_firecheckfunc = turret_tesla_firecheck;
-}
-
-/*QUAKED turret_tesla (0 .5 .8) ?
-*/
-void spawnfunc_turret_tesla()
-{
- precache_model ("models/turrets/tesla_head.md3");
- precache_model ("models/turrets/tesla_base.md3");
-
-
- self.think = turret_tesla_dinit;
- self.nextthink = time + 0.5;
-}
-
+++ /dev/null
-#include "../../_all.qh"
-
-#include "../../movelib.qh"
-#include "../../steerlib.qh"
-
-const float ANIM_NO = 0;
-const float ANIM_TURN = 1;
-const float ANIM_WALK = 2;
-const float ANIM_RUN = 3;
-const float ANIM_STRAFE_L = 4;
-const float ANIM_STRAFE_R = 5;
-const float ANIM_JUMP = 6;
-const float ANIM_LAND = 7;
-const float ANIM_PAIN = 8;
-const float ANIM_MEELE = 9;
-const float ANIM_SWIM = 10;
-const float ANIM_ROAM = 11;
-.float animflag;
-
-const vector WALKER_MIN = '-70 -70 0';
-const vector WALKER_MAX = '70 70 95';
-
-#define WALKER_PATH(s,e) pathlib_astar(s,e)
-
-float walker_firecheck()
-{
- if (self.animflag == ANIM_MEELE)
- return 0;
-
- return turret_stdproc_firecheck();
-}
-
-void walker_meele_do_dmg()
-{
- vector where;
- entity e;
-
- makevectors(self.angles);
- where = self.origin + v_forward * 128;
-
- e = findradius(where,32);
- while (e)
- {
- if (turret_validate_target(self, e, self.target_validate_flags))
- if (e != self && e.owner != self)
- Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg, DEATH_TURRET_WALK_MEELE, '0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
-
- e = e.chain;
- }
-}
-
-void walker_setnoanim()
-{
- turrets_setframe(ANIM_NO, false);
- self.animflag = self.frame;
-}
-void walker_rocket_explode()
-{
- RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, world, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world);
-
- remove (self);
-}
-
-void walker_rocket_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
- self.health = self.health - damage;
- self.velocity = self.velocity + vforce;
-
- if (self.health <= 0)
- W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
-}
-
-#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, autocvar_g_turrets_unit_walker_std_rocket_speed, autocvar_g_turrets_unit_walker_std_rocket_turnrate); UpdateCSQCProjectile(self)
-void walker_rocket_loop();
-void walker_rocket_think()
-{
- vector newdir;
- float edist;
- float itime;
- float m_speed;
-
- self.nextthink = time;
-
- edist = vlen(self.enemy.origin - self.origin);
-
- // Simulate crude guidance
- if (self.cnt < time)
- {
- if (edist < 1000)
- self.tur_shotorg = randomvec() * min(edist, 64);
- else
- self.tur_shotorg = randomvec() * min(edist, 256);
-
- self.cnt = time + 0.5;
- }
-
- if (edist < 128)
- self.tur_shotorg = '0 0 0';
-
- if (self.tur_health < time)
- {
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- if (self.shot_dmg != 1337 && random() < 0.01)
- {
- walker_rocket_loop();
- return;
- }
-
- m_speed = vlen(self.velocity);
-
- // Enemy dead? just keep on the current heading then.
- if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- if (self.enemy)
- {
- itime = max(edist / m_speed, 1);
- newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
- }
- else
- newdir = normalize(self.velocity);
-
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop3()
-{
- vector newdir;
- self.nextthink = time;
-
- if (self.tur_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.think = walker_rocket_think;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-
- self.angles = vectoangles(self.velocity);
-}
-
-void walker_rocket_loop2()
-{
- vector newdir;
-
- self.nextthink = time;
-
- if (self.tur_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.tur_shotorg = self.origin - '0 0 200';
- self.think = walker_rocket_loop3;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop()
-{
- self.nextthink = time;
- self.tur_shotorg = self.origin + '0 0 300';
- self.think = walker_rocket_loop2;
- self.shot_dmg = 1337;
-}
-
-void walker_fire_rocket(vector org)
-{
- entity rocket;
-
- fixedmakevectors(self.angles);
-
- te_explosion (org);
-
- rocket = spawn ();
- setorigin(rocket, org);
-
- sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTEN_NORM);
- setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
- rocket.classname = "walker_rocket";
- rocket.owner = self;
- rocket.bot_dodge = true;
- rocket.bot_dodgerating = 50;
- rocket.takedamage = DAMAGE_YES;
- rocket.damageforcescale = 2;
- rocket.health = 25;
- rocket.tur_shotorg = randomvec() * 512;
- rocket.cnt = time + 1;
- rocket.enemy = self.enemy;
-
- if (random() < 0.01)
- rocket.think = walker_rocket_loop;
- else
- rocket.think = walker_rocket_think;
-
- rocket.event_damage = walker_rocket_damage;
-
- rocket.nextthink = time;
- rocket.movetype = MOVETYPE_FLY;
- rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * autocvar_g_turrets_unit_walker_std_rocket_speed;
- rocket.angles = vectoangles(rocket.velocity);
- rocket.touch = walker_rocket_explode;
- rocket.flags = FL_PROJECTILE;
- rocket.solid = SOLID_BBOX;
- rocket.tur_health = time + 9;
- rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
-
- CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
-}
-
-.vector enemy_last_loc;
-.float enemy_last_time;
-void walker_move_to(vector _target, float _dist)
-{
- switch (self.waterlevel)
- {
- case WATERLEVEL_NONE:
- if (_dist > 500)
- self.animflag = ANIM_RUN;
- else
- self.animflag = ANIM_WALK;
- case WATERLEVEL_WETFEET:
- case WATERLEVEL_SWIMMING:
- if (self.animflag != ANIM_SWIM)
- self.animflag = ANIM_WALK;
- else
- self.animflag = ANIM_SWIM;
- break;
- case WATERLEVEL_SUBMERGED:
- self.animflag = ANIM_SWIM;
- }
-
- self.moveto = _target;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- if(self.enemy)
- {
- self.enemy_last_loc = _target;
- self.enemy_last_time = time;
- }
-}
-
-//#define WALKER_FANCYPATHING
-
-void walker_move_path()
-{
-#ifdef WALKER_FANCYPATHING
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
- walker_move_to(self.moveto, 0);
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-
- if(!self.pathcurrent)
- return;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- walker_move_to(self.moveto, 0);
-#endif
-}
-
-.float idletime;
-void walker_postthink()
-{
- fixedmakevectors(self.angles);
-
- if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
- walker_move_path();
- else if (self.enemy == world)
- {
- if(self.pathcurrent)
- walker_move_path();
- else
- {
- if(self.enemy_last_time != 0)
- {
- if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
- self.enemy_last_time = 0;
- else
- walker_move_to(self.enemy_last_loc, 0);
- }
- else
- {
- if(self.animflag != ANIM_NO)
- {
- traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
-
- if(trace_fraction != 1.0)
- self.tur_head.idletime = -1337;
- else
- {
- traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
- if(trace_fraction == 1.0)
- self.tur_head.idletime = -1337;
- }
-
- if(self.tur_head.idletime == -1337)
- {
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.idletime = 0;
- }
-
- self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
- self.moveto_z = self.origin.z + 64;
- walker_move_to(self.moveto, 0);
- }
-
- if(self.idletime < time)
- {
- if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
- {
- self.idletime = time + 1 + random() * 5;
- self.moveto = self.origin;
- self.animflag = ANIM_NO;
- }
- else
- {
- self.animflag = ANIM_WALK;
- self.idletime = time + 4 + random() * 2;
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.moveto = self.moveto;
- self.tur_head.idletime = 0;
- }
- }
- }
- }
- }
- else
- {
- if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_meele_range && self.animflag != ANIM_MEELE)
- {
- vector wish_angle;
-
- wish_angle = angleofs(self, self.enemy);
- if (self.animflag != ANIM_SWIM)
- if (fabs(wish_angle.y) < 15)
- {
- self.moveto = self.enemy.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- self.animflag = ANIM_MEELE;
- }
- }
- else if (self.tur_head.attack_finished_single < time)
- {
- if(self.tur_head.shot_volly)
- {
- self.animflag = ANIM_NO;
-
- self.tur_head.shot_volly = self.tur_head.shot_volly -1;
- if(self.tur_head.shot_volly == 0)
- self.tur_head.attack_finished_single = time + autocvar_g_turrets_unit_walker_std_rocket_refire;
- else
- self.tur_head.attack_finished_single = time + 0.2;
-
- if(self.tur_head.shot_volly > 1)
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
- else
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
- }
- else
- {
- if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_rockets_range_min)
- if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_rockets_range)
- self.tur_head.shot_volly = 4;
- }
- }
- else
- {
- if (self.animflag != ANIM_MEELE)
- walker_move_to(self.enemy.origin, self.tur_dist_enemy);
- }
- }
-
- //if(self.animflag != ANIM_NO)
- {
- vector real_angle;
- float turny = 0, turnx = 0;
- float vz;
-
- real_angle = vectoangles(self.steerto) - self.angles;
- vz = self.velocity.z;
-
- switch (self.animflag)
- {
- case ANIM_NO:
- movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
- break;
-
- case ANIM_TURN:
- turny = autocvar_g_turrets_unit_walker_turn;
- movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
- break;
-
- case ANIM_WALK:
- turny = autocvar_g_turrets_unit_walker_turn_walk;
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_walk, 0.6);
- break;
-
- case ANIM_RUN:
- turny = autocvar_g_turrets_unit_walker_turn_run;
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_run, 0.6);
- break;
-
- case ANIM_STRAFE_L:
- turny = autocvar_g_turrets_unit_walker_turn_strafe;
- movelib_move_simple(v_right * -1, autocvar_g_turrets_unit_walker_speed_walk, 0.8);
- break;
-
- case ANIM_STRAFE_R:
- turny = autocvar_g_turrets_unit_walker_turn_strafe;
- movelib_move_simple(v_right, autocvar_g_turrets_unit_walker_speed_walk, 0.8);
- break;
-
- case ANIM_JUMP:
- self.velocity += '0 0 1' * autocvar_g_turrets_unit_walker_speed_jump;
- break;
-
- case ANIM_LAND:
- break;
-
- case ANIM_PAIN:
- if(self.frame != ANIM_PAIN)
- defer(0.25, walker_setnoanim);
-
- break;
-
- case ANIM_MEELE:
- if(self.frame != ANIM_MEELE)
- {
- defer(0.41, walker_setnoanim);
- defer(0.21, walker_meele_do_dmg);
- }
-
- movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
- break;
-
- case ANIM_SWIM:
- turny = autocvar_g_turrets_unit_walker_turn_swim;
- turnx = autocvar_g_turrets_unit_walker_turn_swim;
-
- self.angles_x += bound(-10, shortangle_f(real_angle.x, self.angles.x), 10);
- movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_swim, 0.3);
- vz = self.velocity_z + sin(time * 4) * 8;
- break;
-
- case ANIM_ROAM:
- turny = autocvar_g_turrets_unit_walker_turn_walk;
- movelib_move_simple(v_forward ,autocvar_g_turrets_unit_walker_speed_roam, 0.5);
- break;
- }
-
- if(turny)
- {
- turny = bound( turny * -1, shortangle_f(real_angle.y, self.angles.y), turny );
- self.angles_y += turny;
- }
-
- if(turnx)
- {
- turnx = bound( turnx * -1, shortangle_f(real_angle.x, self.angles.x), turnx );
- self.angles_x += turnx;
- }
-
- self.velocity_z = vz;
- }
-
-
- if(self.origin != self.oldorigin)
- self.SendFlags |= TNSF_MOVE;
-
- self.oldorigin = self.origin;
- turrets_setframe(self.animflag, false);
-}
-
-void walker_attack()
-{
- sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTEN_NORM);
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
- Send_Effect("laser_muzzleflash", self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-}
-
-
-void walker_respawnhook()
-{
- entity e;
-
- // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
- if(self.movetype != MOVETYPE_WALK)
- return;
-
- setorigin(self, self.pos1);
- self.angles = self.pos2;
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- {
- #ifdef WALKER_FANCYPATHING
- self.pathcurrent = WALKER_PATH(self.origin, e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-}
-
-void walker_diehook()
-{
-#ifdef WALKER_FANCYPATHING
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-}
-
-void turret_walker_dinit()
-{
- entity e;
-
- if (self.netname == "") self.netname = "Walker Turret";
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE ;
- self.aim_flags = TFL_AIM_LEAD;
-
- self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
-
-
- self.turret_respawnhook = walker_respawnhook;
- self.turret_diehook = walker_diehook;
-
- self.ticrate = 0.05;
- if (turret_stdproc_init("walker_std", "models/turrets/walker_body.md3", "models/turrets/walker_head_minigun.md3", TID_WALKER) == 0)
- {
- remove(self);
- return;
- }
- setsize(self, WALKER_MIN, WALKER_MAX);
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- setorigin(self, self.origin);
- tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
- setorigin(self, trace_endpos + '0 0 4');
- self.pos1 = self.origin;
- self.pos2 = self.angles;
- self.idle_aim = '0 0 0';
- self.turret_firecheckfunc = walker_firecheck;
- self.turret_firefunc = walker_attack;
- self.turret_postthink = walker_postthink;
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- {
-#ifdef WALKER_FANCYPATHING
- self.pathcurrent = WALKER_PATH(self.origin, e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-}
-
-
-void spawnfunc_turret_walker()
-{
- g_turrets_common_precash();
-
- precache_model ("models/turrets/walker_head_minigun.md3");
- precache_model ("models/turrets/walker_body.md3");
- precache_model ( "models/turrets/rocket.md3");
- precache_sound ( "weapons/rocket_impact.wav" );
-
- self.think = turret_walker_dinit;
- self.nextthink = time + 0.5;
-}
{
if(!autocvar_sv_itemstime)
return FALSE;
- if(!warmup_stage && e.classname == "player")
+ if(!warmup_stage && IS_PLAYER(e))
return FALSE;
}
else if(self.team && self.rule == SPRITERULE_DEFAULT)
WriteCoord(MSG_ENTITY, self.fade_time);
WriteCoord(MSG_ENTITY, self.teleport_time);
WriteShort(MSG_ENTITY, self.fade_rate); // maxdist
- float f;
- f = 0;
+ float f = 0;
if(self.currentammo)
f |= 1; // hideable
if(self.exteriormodeltoclient == to)
f |= 2; // my own
+ if(g_onslaught)
+ {
+ if(self.owner.classname == "onslaught_controlpoint")
+ {
+ entity wp_owner = self.owner;
+ entity e = WaypointSprite_getviewentity(to);
+ if(SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; }
+ if(!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; }
+ }
+ if(self.owner.classname == "onslaught_generator")
+ {
+ entity wp_owner = self.owner;
+ if(wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; }
+ if(wp_owner.health <= 0) { f |= 2; }
+ }
+ }
WriteByte(MSG_ENTITY, f);
}
#!/usr/bin/env bash
-
-find . -type f -print0 | \
+cd ${0%[\\/]*}
+find . -name .git -prune -o -type f -print0 | \
xargs -0 sed -i \
`# strip trailing spaces` \
-e 's/[[:space:]]*$//' \
set g_turrets_reloadcvars 0
set g_turrets_nofire 0
-// Target scanning and validation can be resource intensive
-// Dont let turrets look for new targets more frequently then this
-set g_turrets_targetscan_mindelay 0.1
+set g_turrets_targetscan_mindelay 0.1 "delay target rescanning to lower resource usage"
+set g_turrets_targetscan_maxdelay 1 "scan at least this often"
+set g_turrets_aimidle_delay 5 "become idle if target is lost for this long"
-// Do a targetscan at least this often regarless.
-set g_turrets_targetscan_maxdelay 1
+alias g_turrets_reload "set g_turrets_reloadcvars 1"
-// Turrets with no target returns to their idle aim after this much time.
-set g_turrets_aimidle_delay 5
+// {{{ #1: eWheel Turret
+set g_turrets_unit_ewheel_health 200
+set g_turrets_unit_ewheel_respawntime 30
-// --- Units ---
+set g_turrets_unit_ewheel_turnrate 200
-// Machinegun on a stick.
-exec unit_machinegun.cfg
+set g_turrets_unit_ewheel_speed_fast 500
+set g_turrets_unit_ewheel_speed_slow 150
+set g_turrets_unit_ewheel_speed_slower 50
+set g_turrets_unit_ewheel_speed_stop 25
-// Hunter killer rocket turret. "smart rockets"
-exec unit_hk.cfg
+set g_turrets_unit_ewheel_shot_dmg 30
+set g_turrets_unit_ewheel_shot_refire 0.1
+set g_turrets_unit_ewheel_shot_spread 0.025
+set g_turrets_unit_ewheel_shot_force 125
+set g_turrets_unit_ewheel_shot_radius 50
+set g_turrets_unit_ewheel_shot_speed 9000
-// Fires a pair of accelerating, simple homing rockets.
-exec unit_hellion.cfg
+set g_turrets_unit_ewheel_shot_volly 2
+set g_turrets_unit_ewheel_shot_volly_refire 1
-// Fire lots of dumbfire rockets
-exec unit_mlrs.cfg
+set g_turrets_unit_ewheel_target_range 5000
+set g_turrets_unit_ewheel_target_range_optimal 900
+set g_turrets_unit_ewheel_target_range_min 0.1
-// Kills killable enemy missiles.
-exec unit_flac.cfg
+set g_turrets_unit_ewheel_target_select_rangebias 0.25
+set g_turrets_unit_ewheel_target_select_samebias 2
+set g_turrets_unit_ewheel_target_select_anglebias 0.5
+set g_turrets_unit_ewheel_target_select_playerbias 1
+set g_turrets_unit_ewheel_target_select_missilebias 0
-// Support unit. Recharges friendly energy based turrets in range
-exec unit_fusreac.cfg
+set g_turrets_unit_ewheel_ammo_max 4000
+set g_turrets_unit_ewheel_ammo 500
+set g_turrets_unit_ewheel_ammo_recharge 50
-// "Electro" turret.
-exec unit_plasma.cfg
+set g_turrets_unit_ewheel_aim_firetolerance_dist 150
+set g_turrets_unit_ewheel_aim_speed 90
+set g_turrets_unit_ewheel_aim_maxrot 20
+set g_turrets_unit_ewheel_aim_maxpitch 45
-// The the all new "Electro" turret, same ting with two barrels.
-exec unit_plasma2.cfg
+set g_turrets_unit_ewheel_track_type 1
+set g_turrets_unit_ewheel_track_accel_pitch 0
+set g_turrets_unit_ewheel_track_accel_rot 0
+// }}}
+// {{{ #2: FLAC Cannon
+set g_turrets_unit_flac_health 700
+set g_turrets_unit_flac_respawntime 90
-// AAAaaaarg! Bzzaat! yber turret. chain lightning missile and player killing.
-exec unit_tesla.cfg
+set g_turrets_unit_flac_shot_dmg 20
+set g_turrets_unit_flac_shot_refire 0.1
+set g_turrets_unit_flac_shot_radius 100
+set g_turrets_unit_flac_shot_speed 9000
+set g_turrets_unit_flac_shot_spread 0.02
+set g_turrets_unit_flac_shot_force 25
+set g_turrets_unit_flac_shot_volly 0
+set g_turrets_unit_flac_shot_volly_refire 0
-// Fires a constant beam that slows down and slowly damages its target.
-exec unit_phaser.cfg
+set g_turrets_unit_flac_target_range 4000
+set g_turrets_unit_flac_target_range_min 500
+set g_turrets_unit_flac_target_range_optimal 1250
-// The bastred son of a turret and a quake monster.
-// A walking minigun with longrage missiles and closerange meele attack.
-exec unit_walker.cfg
+set g_turrets_unit_flac_target_select_rangebias 0.25
+set g_turrets_unit_flac_target_select_samebias 1
+set g_turrets_unit_flac_target_select_anglebias 0.5
+set g_turrets_unit_flac_target_select_playerbias 0
+set g_turrets_unit_flac_target_select_missilebias 1
-// OMG! Its the Evil Wheel! :O
-exec unit_ewheel.cfg
+set g_turrets_unit_flac_ammo_max 1000
+set g_turrets_unit_flac_ammo 400
+set g_turrets_unit_flac_ammo_recharge 100
-// It is so repulsive, it doesn't even exist!
-// exec unit_repulsor.cfg
+set g_turrets_unit_flac_aim_firetolerance_dist 150
+set g_turrets_unit_flac_aim_speed 200
+set g_turrets_unit_flac_aim_maxrot 360
+set g_turrets_unit_flac_aim_maxpitch 35
-set g_turrets_reloadcvars 0 // reload when this cfg has been exec'd
-alias g_turrets_reload "set g_turrets_reloadcvars 1"
+set g_turrets_unit_flac_track_type 3
+set g_turrets_unit_flac_track_accel_pitch 0.5
+set g_turrets_unit_flac_track_accel_rot 0.7
+set g_turrets_unit_flac_track_blendrate 0.2
+// }}}
+// {{{ #3: Fusion Reactor
+set g_turrets_unit_fusreac_health 700
+set g_turrets_unit_fusreac_respawntime 90
+
+set g_turrets_unit_fusreac_shot_speed 1
+set g_turrets_unit_fusreac_shot_dmg 20
+set g_turrets_unit_fusreac_shot_refire 0.2
+
+set g_turrets_unit_fusreac_target_range 1024
+set g_turrets_unit_fusreac_target_range_min 1
+
+set g_turrets_unit_fusreac_ammo_max 100
+set g_turrets_unit_fusreac_ammo 0
+set g_turrets_unit_fusreac_ammo_recharge 100
+
+set g_turrets_unit_fusreac_shot_radius 0
+set g_turrets_unit_fusreac_shot_spread 0
+set g_turrets_unit_fusreac_shot_force 0
+set g_turrets_unit_fusreac_shot_volly 0
+set g_turrets_unit_fusreac_shot_volly_refire 0
+set g_turrets_unit_fusreac_target_range_optimal 0
+set g_turrets_unit_fusreac_target_select_rangebias 0
+set g_turrets_unit_fusreac_target_select_samebias 0
+set g_turrets_unit_fusreac_target_select_anglebias 0
+set g_turrets_unit_fusreac_target_select_playerbias 0
+set g_turrets_unit_fusreac_aim_firetolerance_dist 0
+set g_turrets_unit_fusreac_aim_speed 0
+set g_turrets_unit_fusreac_aim_maxrot 0
+set g_turrets_unit_fusreac_aim_maxpitch 0
+set g_turrets_unit_fusreac_track_type 0
+set g_turrets_unit_fusreac_track_accel_pitch 0
+set g_turrets_unit_fusreac_track_accel_rot 0
+set g_turrets_unit_fusreac_track_blendrate 0
+// }}}
+// {{{ #4: Hellion Missile Turret
+set g_turrets_unit_hellion_health 500
+set g_turrets_unit_hellion_respawntime 90
+
+set g_turrets_unit_hellion_shot_dmg 50
+set g_turrets_unit_hellion_shot_refire 0.2
+set g_turrets_unit_hellion_shot_radius 80
+
+set g_turrets_unit_hellion_shot_speed 650
+set g_turrets_unit_hellion_shot_speed_max 4000
+set g_turrets_unit_hellion_shot_speed_gain 1.01
+
+set g_turrets_unit_hellion_shot_spread 0.08
+set g_turrets_unit_hellion_shot_force 250
+set g_turrets_unit_hellion_shot_volly 2
+set g_turrets_unit_hellion_shot_volly_refire 4
+
+set g_turrets_unit_hellion_target_range 6000
+set g_turrets_unit_hellion_target_range_min 150
+set g_turrets_unit_hellion_target_range_optimal 4500
+
+set g_turrets_unit_hellion_target_select_rangebias 0.7
+set g_turrets_unit_hellion_target_select_samebias 0.01
+set g_turrets_unit_hellion_target_select_anglebias 0.01
+set g_turrets_unit_hellion_target_select_playerbias 1
+set g_turrets_unit_hellion_target_select_missilebias 0
+
+set g_turrets_unit_hellion_ammo_max 200
+set g_turrets_unit_hellion_ammo 100
+set g_turrets_unit_hellion_ammo_recharge 50
+
+set g_turrets_unit_hellion_aim_firetolerance_dist 200
+set g_turrets_unit_hellion_aim_speed 100
+set g_turrets_unit_hellion_aim_maxrot 360
+set g_turrets_unit_hellion_aim_maxpitch 20
+
+set g_turrets_unit_hellion_track_type 3
+set g_turrets_unit_hellion_track_accel_pitch 0.25
+set g_turrets_unit_hellion_track_accel_rot 0.6
+set g_turrets_unit_hellion_track_blendrate 0.25
+// }}}
+// {{{ #5: Hunter-Killer Turret
+set g_turrets_unit_hk_health 500
+set g_turrets_unit_hk_respawntime 90
+
+set g_turrets_unit_hk_shot_dmg 120
+set g_turrets_unit_hk_shot_refire 5
+set g_turrets_unit_hk_shot_radius 200
+
+set g_turrets_unit_hk_shot_speed 500
+set g_turrets_unit_hk_shot_speed_max 1000
+set g_turrets_unit_hk_shot_speed_accel 1.025
+set g_turrets_unit_hk_shot_speed_accel2 1.05
+set g_turrets_unit_hk_shot_speed_decel 0.9
+set g_turrets_unit_hk_shot_speed_turnrate 0.25
+
+set g_turrets_unit_hk_shot_spread 0
+set g_turrets_unit_hk_shot_force 600
+set g_turrets_unit_hk_shot_volly 0
+set g_turrets_unit_hk_shot_volly_refire 0
+
+set g_turrets_unit_hk_target_range 6000
+set g_turrets_unit_hk_target_range_min 220
+set g_turrets_unit_hk_target_range_optimal 5000
+
+set g_turrets_unit_hk_target_select_rangebias 0.5
+set g_turrets_unit_hk_target_select_samebias 0.01
+set g_turrets_unit_hk_target_select_anglebias 0.1
+set g_turrets_unit_hk_target_select_playerbias 1
+set g_turrets_unit_hk_target_select_missilebias 0
+
+set g_turrets_unit_hk_ammo_max 240
+set g_turrets_unit_hk_ammo 120
+set g_turrets_unit_hk_ammo_recharge 16
+
+set g_turrets_unit_hk_aim_firetolerance_dist 500
+set g_turrets_unit_hk_aim_speed 100
+set g_turrets_unit_hk_aim_maxrot 360
+set g_turrets_unit_hk_aim_maxpitch 20
+
+set g_turrets_unit_hk_track_type 3
+set g_turrets_unit_hk_track_accel_pitch 0.25
+set g_turrets_unit_hk_track_accel_rot 0.6
+set g_turrets_unit_hk_track_blendrate 0.2
+// }}}
+// {{{ #6: Machinegun Turret
+set g_turrets_unit_machinegun_health 256
+set g_turrets_unit_machinegun_respawntime 60
+
+set g_turrets_unit_machinegun_shot_dmg 10
+set g_turrets_unit_machinegun_shot_refire 0.1
+set g_turrets_unit_machinegun_shot_spread 0.015
+set g_turrets_unit_machinegun_shot_force 20
+set g_turrets_unit_machinegun_shot_radius 0
+set g_turrets_unit_machinegun_shot_speed 34920
+
+set g_turrets_unit_machinegun_shot_volly 5
+set g_turrets_unit_machinegun_shot_volly_refire 0.5
+
+set g_turrets_unit_machinegun_target_range 4500
+set g_turrets_unit_machinegun_target_range_min 2
+set g_turrets_unit_machinegun_target_range_optimal 1000
+
+set g_turrets_unit_machinegun_target_select_rangebias 0.25
+set g_turrets_unit_machinegun_target_select_samebias 0.25
+set g_turrets_unit_machinegun_target_select_anglebias 0.5
+set g_turrets_unit_machinegun_target_select_playerbias 1
+set g_turrets_unit_machinegun_target_select_missilebias 0
+
+set g_turrets_unit_machinegun_ammo_max 1500
+set g_turrets_unit_machinegun_ammo 300
+set g_turrets_unit_machinegun_ammo_recharge 75
+
+set g_turrets_unit_machinegun_aim_firetolerance_dist 25
+set g_turrets_unit_machinegun_aim_speed 120
+set g_turrets_unit_machinegun_aim_maxrot 360
+set g_turrets_unit_machinegun_aim_maxpitch 25
+
+set g_turrets_unit_machinegun_track_type 3
+set g_turrets_unit_machinegun_track_accel_pitch 0.4
+set g_turrets_unit_machinegun_track_accel_rot 0.9
+set g_turrets_unit_machinegun_track_blendrate 0.2
+// }}}
+// {{{ #7: MLRS Turret
+set g_turrets_unit_mlrs_health 500
+set g_turrets_unit_mlrs_respawntime 60
+
+set g_turrets_unit_mlrs_shot_dmg 50
+set g_turrets_unit_mlrs_shot_refire 0.1
+set g_turrets_unit_mlrs_shot_radius 125
+set g_turrets_unit_mlrs_shot_speed 2000
+set g_turrets_unit_mlrs_shot_spread 0.05
+set g_turrets_unit_mlrs_shot_force 25
+
+set g_turrets_unit_mlrs_shot_volly 6
+
+set g_turrets_unit_mlrs_shot_volly_refire 4
+
+set g_turrets_unit_mlrs_target_range 3000
+set g_turrets_unit_mlrs_target_range_min 500
+set g_turrets_unit_mlrs_target_range_optimal 500
+
+set g_turrets_unit_mlrs_target_select_rangebias 0.25
+set g_turrets_unit_mlrs_target_select_samebias 0.5
+set g_turrets_unit_mlrs_target_select_anglebias 0.5
+set g_turrets_unit_mlrs_target_select_playerbias 1
+set g_turrets_unit_mlrs_target_select_missilebias 0
+
+set g_turrets_unit_mlrs_ammo_max 300
+set g_turrets_unit_mlrs_ammo 300
+set g_turrets_unit_mlrs_ammo_recharge 75
+
+set g_turrets_unit_mlrs_aim_firetolerance_dist 120
+set g_turrets_unit_mlrs_aim_speed 100
+set g_turrets_unit_mlrs_aim_maxrot 360
+set g_turrets_unit_mlrs_aim_maxpitch 20
+
+set g_turrets_unit_mlrs_track_type 3
+set g_turrets_unit_mlrs_track_accel_pitch 0.5
+set g_turrets_unit_mlrs_track_accel_rot 0.7
+set g_turrets_unit_mlrs_track_blendrate 0.2
+// }}}
+// {{{ #8: Phaser Cannon
+set g_turrets_unit_phaser_health 500
+
+set g_turrets_unit_phaser_respawntime 90
+
+set g_turrets_unit_phaser_shot_dmg 100
+set g_turrets_unit_phaser_shot_refire 4
+set g_turrets_unit_phaser_shot_radius 8
+set g_turrets_unit_phaser_shot_speed 4
+set g_turrets_unit_phaser_shot_spread 0
+set g_turrets_unit_phaser_shot_force 5
+set g_turrets_unit_phaser_shot_volly 0
+set g_turrets_unit_phaser_shot_volly_refire 5
+
+set g_turrets_unit_phaser_target_range 3000
+set g_turrets_unit_phaser_target_range_min 0
+set g_turrets_unit_phaser_target_range_optimal 1500
+
+set g_turrets_unit_phaser_target_select_rangebias 0.85
+set g_turrets_unit_phaser_target_select_samebias 0
+set g_turrets_unit_phaser_target_select_anglebias 0.25
+set g_turrets_unit_phaser_target_select_playerbias 1
+set g_turrets_unit_phaser_target_select_missilebias 0
+
+set g_turrets_unit_phaser_ammo_max 2000
+set g_turrets_unit_phaser_ammo 1000
+set g_turrets_unit_phaser_ammo_recharge 25
+
+set g_turrets_unit_phaser_aim_firetolerance_dist 100
+
+set g_turrets_unit_phaser_aim_speed 300
+set g_turrets_unit_phaser_aim_maxrot 360
+set g_turrets_unit_phaser_aim_maxpitch 30
+
+set g_turrets_unit_phaser_track_type 3
+set g_turrets_unit_phaser_track_accel_pitch 0.5
+set g_turrets_unit_phaser_track_accel_rot 0.65
+set g_turrets_unit_phaser_track_blendrate 0.2
+// }}}
+// {{{ #9: Plasma Cannon
+set g_turrets_unit_plasma_health 500
+set g_turrets_unit_plasma_respawntime 60
+
+set g_turrets_unit_plasma_shot_dmg 80
+set g_turrets_unit_plasma_shot_refire 0.6
+set g_turrets_unit_plasma_shot_radius 150
+set g_turrets_unit_plasma_shot_speed 2000
+set g_turrets_unit_plasma_shot_spread 0.015
+set g_turrets_unit_plasma_shot_force 100
+set g_turrets_unit_plasma_shot_volly 0
+set g_turrets_unit_plasma_shot_volly_refire 0
+
+set g_turrets_unit_plasma_target_range 3500
+set g_turrets_unit_plasma_target_range_min 200
+set g_turrets_unit_plasma_target_range_optimal 500
+
+set g_turrets_unit_plasma_target_select_rangebias 0.5
+set g_turrets_unit_plasma_target_select_samebias 0.01
+set g_turrets_unit_plasma_target_select_anglebias 0.25
+set g_turrets_unit_plasma_target_select_playerbias 1
+set g_turrets_unit_plasma_target_select_missilebias 0
+
+set g_turrets_unit_plasma_ammo_max 640
+set g_turrets_unit_plasma_ammo 320
+set g_turrets_unit_plasma_ammo_recharge 40
+
+set g_turrets_unit_plasma_aim_firetolerance_dist 120
+set g_turrets_unit_plasma_aim_speed 200
+set g_turrets_unit_plasma_aim_maxrot 360
+set g_turrets_unit_plasma_aim_maxpitch 30
+
+set g_turrets_unit_plasma_track_type 3
+set g_turrets_unit_plasma_track_accel_pitch 0.5
+set g_turrets_unit_plasma_track_accel_rot 0.7
+set g_turrets_unit_plasma_track_blendrate 0.2
+// }}}
+// {{{ #10: Dual Plasma Cannon
+set g_turrets_unit_plasma_dual_health 500
+set g_turrets_unit_plasma_dual_respawntime 60
+
+set g_turrets_unit_plasma_dual_shot_dmg 80
+set g_turrets_unit_plasma_dual_shot_refire 0.35
+set g_turrets_unit_plasma_dual_shot_radius 150
+set g_turrets_unit_plasma_dual_shot_speed 2000
+set g_turrets_unit_plasma_dual_shot_spread 0.015
+set g_turrets_unit_plasma_dual_shot_force 100
+
+set g_turrets_unit_plasma_dual_shot_volly 0
+set g_turrets_unit_plasma_dual_shot_volly_refire 0
+
+set g_turrets_unit_plasma_dual_target_range 3000
+set g_turrets_unit_plasma_dual_target_range_min 80
+set g_turrets_unit_plasma_dual_target_range_optimal 1000
+
+set g_turrets_unit_plasma_dual_target_select_rangebias 0.2
+set g_turrets_unit_plasma_dual_target_select_samebias 0.4
+set g_turrets_unit_plasma_dual_target_select_anglebias 0.4
+set g_turrets_unit_plasma_dual_target_select_playerbias 1
+set g_turrets_unit_plasma_dual_target_select_missilebias 0
+
+set g_turrets_unit_plasma_dual_ammo_max 640
+set g_turrets_unit_plasma_dual_ammo 320
+set g_turrets_unit_plasma_dual_ammo_recharge 40
+
+set g_turrets_unit_plasma_dual_aim_firetolerance_dist 200
+
+set g_turrets_unit_plasma_dual_aim_speed 100
+set g_turrets_unit_plasma_dual_aim_maxrot 360
+set g_turrets_unit_plasma_dual_aim_maxpitch 30
+
+set g_turrets_unit_plasma_dual_track_type 3
+set g_turrets_unit_plasma_dual_track_accel_pitch 0.5
+set g_turrets_unit_plasma_dual_track_accel_rot 0.7
+set g_turrets_unit_plasma_dual_track_blendrate 0.2
+// }}}
+// {{{ #11: Tesla Coil
+set g_turrets_unit_tesla_health 1000
+set g_turrets_unit_tesla_respawntime 120
+
+set g_turrets_unit_tesla_shot_dmg 200
+set g_turrets_unit_tesla_shot_refire 1.5
+set g_turrets_unit_tesla_shot_force 400
+
+set g_turrets_unit_tesla_shot_volly 1
+set g_turrets_unit_tesla_shot_volly_refire 2.5
+
+set g_turrets_unit_tesla_target_range_min 0
+set g_turrets_unit_tesla_target_range 1000
+
+set g_turrets_unit_tesla_target_select_playerbias 1
+set g_turrets_unit_tesla_target_select_missilebias 1
+
+set g_turrets_unit_tesla_ammo_max 1000
+set g_turrets_unit_tesla_ammo 200
+set g_turrets_unit_tesla_ammo_recharge 15
+// }}}
+// {{{ #12: Walker Turret
+set g_turrets_unit_walker_health 500
+set g_turrets_unit_walker_respawntime 60
+
+set g_turrets_unit_walker_speed_run 300
+set g_turrets_unit_walker_speed_roam 100
+set g_turrets_unit_walker_speed_walk 200
+set g_turrets_unit_walker_speed_swim 200
+set g_turrets_unit_walker_speed_jump 800
+set g_turrets_unit_walker_speed_stop 90
+
+set g_turrets_unit_walker_turn 20
+set g_turrets_unit_walker_turn_walk 15
+set g_turrets_unit_walker_turn_run 7
+set g_turrets_unit_walker_turn_swim 10
+set g_turrets_unit_walker_turn_strafe 5
+
+set g_turrets_unit_walker_shot_dmg 5
+set g_turrets_unit_walker_shot_refire 0.05
+set g_turrets_unit_walker_shot_spread 0.025
+set g_turrets_unit_walker_shot_force 10
+set g_turrets_unit_walker_shot_radius 0
+set g_turrets_unit_walker_shot_speed 18000
+
+set g_turrets_unit_walker_shot_volly 10
+set g_turrets_unit_walker_shot_volly_refire 1
+
+set g_turrets_unit_walker_target_range 5000
+set g_turrets_unit_walker_target_range_optimal 100
+set g_turrets_unit_walker_target_range_min 0
+
+set g_turrets_unit_walker_target_select_rangebias 0.25
+set g_turrets_unit_walker_target_select_samebias 0.25
+set g_turrets_unit_walker_target_select_anglebias 0.5
+set g_turrets_unit_walker_target_select_playerbias 1
+set g_turrets_unit_walker_target_select_missilebias 0
+
+set g_turrets_unit_walker_ammo_max 4000
+set g_turrets_unit_walker_ammo 500
+set g_turrets_unit_walker_ammo_recharge 100
+
+set g_turrets_unit_walker_aim_firetolerance_dist 100
+set g_turrets_unit_walker_aim_speed 45
+set g_turrets_unit_walker_aim_maxrot 90
+set g_turrets_unit_walker_aim_maxpitch 15
+
+set g_turrets_unit_walker_track_type 1
+
+set g_turrets_unit_walker_rocket_range 4000
+set g_turrets_unit_walker_rocket_range_min 500
+set g_turrets_unit_walker_rocket_refire 10
+set g_turrets_unit_walker_rocket_damage 45
+set g_turrets_unit_walker_rocket_radius 150
+set g_turrets_unit_walker_rocket_force 150
+set g_turrets_unit_walker_rocket_turnrate 0.05
+set g_turrets_unit_walker_rocket_speed 1000
+
+set g_turrets_unit_walker_melee_range 100
+set g_turrets_unit_walker_melee_damage 100
+set g_turrets_unit_walker_melee_force 600
+
+set g_turrets_unit_walker_track_accel_pitch 0.5
+set g_turrets_unit_walker_track_accel_rot 0.8
+set g_turrets_unit_walker_track_blendrate 0.2
+// }}}
+++ /dev/null
-set g_turrets_unit_ewheel_std_health 200
-set g_turrets_unit_ewheel_std_respawntime 30
-
-// dgr / sec
-set g_turrets_unit_ewheel_turnrate 200
-
-set g_turrets_unit_ewheel_speed_fast 500
-set g_turrets_unit_ewheel_speed_slow 150
-set g_turrets_unit_ewheel_speed_slower 50
-set g_turrets_unit_ewheel_speed_stop 25
-
-set g_turrets_unit_ewheel_std_shot_dmg 30
-set g_turrets_unit_ewheel_std_shot_refire 0.1
-set g_turrets_unit_ewheel_std_shot_spread 0.025
-set g_turrets_unit_ewheel_std_shot_force 125
-set g_turrets_unit_ewheel_std_shot_radius 50
-set g_turrets_unit_ewheel_std_shot_speed 9000
-
-set g_turrets_unit_ewheel_std_shot_volly 2
-set g_turrets_unit_ewheel_std_shot_volly_refire 1
-
-set g_turrets_unit_ewheel_std_target_range 5000
-set g_turrets_unit_ewheel_std_target_range_optimal 900
-set g_turrets_unit_ewheel_std_target_range_min 0.1
-
-set g_turrets_unit_ewheel_std_target_select_rangebias 0.25
-set g_turrets_unit_ewheel_std_target_select_samebias 2
-set g_turrets_unit_ewheel_std_target_select_anglebias 0.5
-set g_turrets_unit_ewheel_std_target_select_playerbias 1
-set g_turrets_unit_ewheel_std_target_select_missilebias 0
-
-set g_turrets_unit_ewheel_std_ammo_max 4000
-set g_turrets_unit_ewheel_std_ammo 500
-set g_turrets_unit_ewheel_std_ammo_recharge 50
-
-set g_turrets_unit_ewheel_std_aim_firetolerance_dist 150
-set g_turrets_unit_ewheel_std_aim_speed 90
-set g_turrets_unit_ewheel_std_aim_maxrot 20
-set g_turrets_unit_ewheel_std_aim_maxpitch 45
-
-set g_turrets_unit_ewheel_std_track_type 1
-set g_turrets_unit_ewheel_std_track_accel_pitch 0
-set g_turrets_unit_ewheel_std_track_accel_rot 0
+++ /dev/null
-set g_turrets_unit_flac_std_health 700
-set g_turrets_unit_flac_std_respawntime 90
-
-set g_turrets_unit_flac_std_shot_dmg 20
-set g_turrets_unit_flac_std_shot_refire 0.1
-set g_turrets_unit_flac_std_shot_radius 100
-set g_turrets_unit_flac_std_shot_speed 9000
-set g_turrets_unit_flac_std_shot_spread 0.02
-set g_turrets_unit_flac_std_shot_force 25
-set g_turrets_unit_flac_std_shot_volly 0
-set g_turrets_unit_flac_std_shot_volly_refire 0
-
-set g_turrets_unit_flac_std_target_range 4000
-set g_turrets_unit_flac_std_target_range_min 500
-set g_turrets_unit_flac_std_target_range_optimal 1250
-
-set g_turrets_unit_flac_std_target_select_rangebias 0.25
-set g_turrets_unit_flac_std_target_select_samebias 1
-set g_turrets_unit_flac_std_target_select_anglebias 0.5
-set g_turrets_unit_flac_std_target_select_playerbias 0
-set g_turrets_unit_flac_std_target_select_missilebias 1
-
-set g_turrets_unit_flac_std_ammo_max 1000
-set g_turrets_unit_flac_std_ammo 400
-set g_turrets_unit_flac_std_ammo_recharge 100
-
-set g_turrets_unit_flac_std_aim_firetolerance_dist 150
-set g_turrets_unit_flac_std_aim_speed 200
-set g_turrets_unit_flac_std_aim_maxrot 360
-set g_turrets_unit_flac_std_aim_maxpitch 35
-
-set g_turrets_unit_flac_std_track_type 3
-set g_turrets_unit_flac_std_track_accel_pitch 0.5
-set g_turrets_unit_flac_std_track_accel_rot 0.7
-set g_turrets_unit_flac_std_track_blendrate 0.2
+++ /dev/null
-set g_turrets_unit_fusreac_std_health 700
-set g_turrets_unit_fusreac_std_respawntime 90
-
-set g_turrets_unit_fusreac_std_shot_speed 1
-set g_turrets_unit_fusreac_std_shot_dmg 20
-set g_turrets_unit_fusreac_std_shot_refire 0.2
-
-set g_turrets_unit_fusreac_std_target_range 1024
-set g_turrets_unit_fusreac_std_target_range_min 1
-
-set g_turrets_unit_fusreac_std_ammo_max 100
-set g_turrets_unit_fusreac_std_ammo 0
-set g_turrets_unit_fusreac_std_ammo_recharge 100
-
-set g_turrets_unit_fusreac_std_shot_radius 0
-set g_turrets_unit_fusreac_std_shot_spread 0
-set g_turrets_unit_fusreac_std_shot_force 0
-set g_turrets_unit_fusreac_std_shot_volly 0
-set g_turrets_unit_fusreac_std_shot_volly_refire 0
-set g_turrets_unit_fusreac_std_target_range_optimal 0
-set g_turrets_unit_fusreac_std_target_select_rangebias 0
-set g_turrets_unit_fusreac_std_target_select_samebias 0
-set g_turrets_unit_fusreac_std_target_select_anglebias 0
-set g_turrets_unit_fusreac_std_target_select_playerbias 0
-set g_turrets_unit_fusreac_std_aim_firetolerance_dist 0
-set g_turrets_unit_fusreac_std_aim_speed 0
-set g_turrets_unit_fusreac_std_aim_maxrot 0
-set g_turrets_unit_fusreac_std_aim_maxpitch 0
-set g_turrets_unit_fusreac_std_track_type 0
-set g_turrets_unit_fusreac_std_track_accel_pitch 0
-set g_turrets_unit_fusreac_std_track_accel_rot 0
-set g_turrets_unit_fusreac_std_track_blendrate 0
\ No newline at end of file
+++ /dev/null
-set g_turrets_unit_hellion_std_health 500
-set g_turrets_unit_hellion_std_respawntime 90
-
-set g_turrets_unit_hellion_std_shot_dmg 50
-set g_turrets_unit_hellion_std_shot_refire 0.2
-set g_turrets_unit_hellion_std_shot_radius 80
-
-set g_turrets_unit_hellion_std_shot_speed 650
-set g_turrets_unit_hellion_std_shot_speed_max 4000
-set g_turrets_unit_hellion_std_shot_speed_gain 1.01
-
-set g_turrets_unit_hellion_std_shot_spread 0.08
-set g_turrets_unit_hellion_std_shot_force 250
-set g_turrets_unit_hellion_std_shot_volly 2
-set g_turrets_unit_hellion_std_shot_volly_refire 4
-
-set g_turrets_unit_hellion_std_target_range 6000
-set g_turrets_unit_hellion_std_target_range_min 150
-set g_turrets_unit_hellion_std_target_range_optimal 4500
-
-set g_turrets_unit_hellion_std_target_select_rangebias 0.7
-set g_turrets_unit_hellion_std_target_select_samebias 0.01
-set g_turrets_unit_hellion_std_target_select_anglebias 0.01
-set g_turrets_unit_hellion_std_target_select_playerbias 1
-set g_turrets_unit_hellion_std_target_select_missilebias 0
-
-set g_turrets_unit_hellion_std_ammo_max 200
-set g_turrets_unit_hellion_std_ammo 100
-set g_turrets_unit_hellion_std_ammo_recharge 50
-
-set g_turrets_unit_hellion_std_aim_firetolerance_dist 200
-set g_turrets_unit_hellion_std_aim_speed 100
-set g_turrets_unit_hellion_std_aim_maxrot 360
-set g_turrets_unit_hellion_std_aim_maxpitch 20
-
-set g_turrets_unit_hellion_std_track_type 3
-set g_turrets_unit_hellion_std_track_accel_pitch 0.25
-set g_turrets_unit_hellion_std_track_accel_rot 0.6
-set g_turrets_unit_hellion_std_track_blendrate 0.25
-
+++ /dev/null
-set g_turrets_unit_hk_std_health 500
-set g_turrets_unit_hk_std_respawntime 90
-
-set g_turrets_unit_hk_std_shot_dmg 120
-set g_turrets_unit_hk_std_shot_refire 5
-set g_turrets_unit_hk_std_shot_radius 200
-
-set g_turrets_unit_hk_std_shot_speed 500
-set g_turrets_unit_hk_std_shot_speed_max 1000
-set g_turrets_unit_hk_std_shot_speed_accel 1.025
-set g_turrets_unit_hk_std_shot_speed_accel2 1.05
-set g_turrets_unit_hk_std_shot_speed_decel 0.9
-set g_turrets_unit_hk_std_shot_speed_turnrate 0.25
-
-set g_turrets_unit_hk_std_shot_spread 0
-set g_turrets_unit_hk_std_shot_force 600
-set g_turrets_unit_hk_std_shot_volly 0
-set g_turrets_unit_hk_std_shot_volly_refire 0
-
-set g_turrets_unit_hk_std_target_range 6000
-set g_turrets_unit_hk_std_target_range_min 220
-set g_turrets_unit_hk_std_target_range_optimal 5000
-
-set g_turrets_unit_hk_std_target_select_rangebias 0.5
-set g_turrets_unit_hk_std_target_select_samebias 0.01
-set g_turrets_unit_hk_std_target_select_anglebias 0.1
-set g_turrets_unit_hk_std_target_select_playerbias 1
-set g_turrets_unit_hk_std_target_select_missilebias 0
-
-set g_turrets_unit_hk_std_ammo_max 240
-set g_turrets_unit_hk_std_ammo 120
-set g_turrets_unit_hk_std_ammo_recharge 16
-
-set g_turrets_unit_hk_std_aim_firetolerance_dist 500
-set g_turrets_unit_hk_std_aim_speed 100
-set g_turrets_unit_hk_std_aim_maxrot 360
-set g_turrets_unit_hk_std_aim_maxpitch 20
-
-set g_turrets_unit_hk_std_track_type 3
-set g_turrets_unit_hk_std_track_accel_pitch 0.25
-set g_turrets_unit_hk_std_track_accel_rot 0.6
-set g_turrets_unit_hk_std_track_blendrate 0.2
-
+++ /dev/null
-set g_turrets_unit_machinegun_std_health 256
-set g_turrets_unit_machinegun_std_respawntime 60
-
-set g_turrets_unit_machinegun_std_shot_dmg 10
-set g_turrets_unit_machinegun_std_shot_refire 0.1
-set g_turrets_unit_machinegun_std_shot_spread 0.015
-set g_turrets_unit_machinegun_std_shot_force 20
-set g_turrets_unit_machinegun_std_shot_radius 0
-set g_turrets_unit_machinegun_std_shot_speed 34920
-
-set g_turrets_unit_machinegun_std_shot_volly 5
-set g_turrets_unit_machinegun_std_shot_volly_refire 0.5
-
-set g_turrets_unit_machinegun_std_target_range 4500
-set g_turrets_unit_machinegun_std_target_range_min 2
-set g_turrets_unit_machinegun_std_target_range_optimal 1000
-
-set g_turrets_unit_machinegun_std_target_select_rangebias 0.25
-set g_turrets_unit_machinegun_std_target_select_samebias 0.25
-set g_turrets_unit_machinegun_std_target_select_anglebias 0.5
-set g_turrets_unit_machinegun_std_target_select_playerbias 1
-set g_turrets_unit_machinegun_std_target_select_missilebias 0
-
-set g_turrets_unit_machinegun_std_ammo_max 1500
-set g_turrets_unit_machinegun_std_ammo 300
-set g_turrets_unit_machinegun_std_ammo_recharge 75
-
-set g_turrets_unit_machinegun_std_aim_firetolerance_dist 25
-set g_turrets_unit_machinegun_std_aim_speed 120
-set g_turrets_unit_machinegun_std_aim_maxrot 360
-set g_turrets_unit_machinegun_std_aim_maxpitch 25
-
-set g_turrets_unit_machinegun_std_track_type 3
-set g_turrets_unit_machinegun_std_track_accel_pitch 0.4
-set g_turrets_unit_machinegun_std_track_accel_rot 0.9
-set g_turrets_unit_machinegun_std_track_blendrate 0.2
-
-
+++ /dev/null
-set g_turrets_unit_mlrs_std_health 500
-set g_turrets_unit_mlrs_std_respawntime 60
-
-set g_turrets_unit_mlrs_std_shot_dmg 50
-set g_turrets_unit_mlrs_std_shot_refire 0.1
-set g_turrets_unit_mlrs_std_shot_radius 125
-set g_turrets_unit_mlrs_std_shot_speed 2000
-set g_turrets_unit_mlrs_std_shot_spread 0.05
-set g_turrets_unit_mlrs_std_shot_force 25
-
-set g_turrets_unit_mlrs_std_shot_volly 6
-
-// !must be correctly matched with ammo_recharge as this unit use
-// volly_always. (means ammo_recharge * ammo_max must be eaqual to volly_refire)
-set g_turrets_unit_mlrs_std_shot_volly_refire 4
-
-set g_turrets_unit_mlrs_std_target_range 3000
-set g_turrets_unit_mlrs_std_target_range_min 500
-set g_turrets_unit_mlrs_std_target_range_optimal 500
-
-set g_turrets_unit_mlrs_std_target_select_rangebias 0.25
-set g_turrets_unit_mlrs_std_target_select_samebias 0.5
-set g_turrets_unit_mlrs_std_target_select_anglebias 0.5
-set g_turrets_unit_mlrs_std_target_select_playerbias 1
-set g_turrets_unit_mlrs_std_target_select_missilebias 0
-
-// !must be shot_dmg * 6 as this unit uses ammo to control the animation
-set g_turrets_unit_mlrs_std_ammo_max 300
-set g_turrets_unit_mlrs_std_ammo 300
-set g_turrets_unit_mlrs_std_ammo_recharge 75
-
-set g_turrets_unit_mlrs_std_aim_firetolerance_dist 120
-set g_turrets_unit_mlrs_std_aim_speed 100
-set g_turrets_unit_mlrs_std_aim_maxrot 360
-set g_turrets_unit_mlrs_std_aim_maxpitch 20
-
-set g_turrets_unit_mlrs_std_track_type 3
-set g_turrets_unit_mlrs_std_track_accel_pitch 0.5
-set g_turrets_unit_mlrs_std_track_accel_rot 0.7
-set g_turrets_unit_mlrs_std_track_blendrate 0.2
+++ /dev/null
-set g_turrets_unit_phaser_std_health 500
-
-set g_turrets_unit_phaser_std_respawntime 90
-
-set g_turrets_unit_phaser_std_shot_dmg 100
-set g_turrets_unit_phaser_std_shot_refire 4
-set g_turrets_unit_phaser_std_shot_radius 8
-set g_turrets_unit_phaser_std_shot_speed 4 // Used for how long to sustain the beam for this turret (seconds)
-set g_turrets_unit_phaser_std_shot_spread 0
-set g_turrets_unit_phaser_std_shot_force 5
-set g_turrets_unit_phaser_std_shot_volly 0
-set g_turrets_unit_phaser_std_shot_volly_refire 5
-
-set g_turrets_unit_phaser_std_target_range 3000
-set g_turrets_unit_phaser_std_target_range_min 0
-set g_turrets_unit_phaser_std_target_range_optimal 1500
-
-set g_turrets_unit_phaser_std_target_select_rangebias 0.85
-set g_turrets_unit_phaser_std_target_select_samebias 0
-set g_turrets_unit_phaser_std_target_select_anglebias 0.25
-set g_turrets_unit_phaser_std_target_select_playerbias 1
-set g_turrets_unit_phaser_std_target_select_missilebias 0
-
-set g_turrets_unit_phaser_std_ammo_max 2000
-set g_turrets_unit_phaser_std_ammo 1000
-set g_turrets_unit_phaser_std_ammo_recharge 25
-
-set g_turrets_unit_phaser_std_aim_firetolerance_dist 100
-
-set g_turrets_unit_phaser_std_aim_speed 300
-set g_turrets_unit_phaser_std_aim_maxrot 360
-set g_turrets_unit_phaser_std_aim_maxpitch 30
-
-set g_turrets_unit_phaser_std_track_type 3
-set g_turrets_unit_phaser_std_track_accel_pitch 0.5
-set g_turrets_unit_phaser_std_track_accel_rot 0.65
-set g_turrets_unit_phaser_std_track_blendrate 0.2
-
+++ /dev/null
-set g_turrets_unit_plasma_std_health 500
-set g_turrets_unit_plasma_std_respawntime 60
-
-// Do this mutch damage
-set g_turrets_unit_plasma_std_shot_dmg 80
-//This often
-set g_turrets_unit_plasma_std_shot_refire 0.6
-//Over this mutch area
-set g_turrets_unit_plasma_std_shot_radius 150
-//Traveling at this speed
-set g_turrets_unit_plasma_std_shot_speed 2000
-//With a random spread of
-set g_turrets_unit_plasma_std_shot_spread 0.015
-//Pushing things this hard
-set g_turrets_unit_plasma_std_shot_force 100
-//Each volly is this many shots (0=1)
-set g_turrets_unit_plasma_std_shot_volly 0
-// Refire time upon compleated volly
-set g_turrets_unit_plasma_std_shot_volly_refire 0
-
-// Scan for targets within this range
-set g_turrets_unit_plasma_std_target_range 3500
-// But no close then this
-set g_turrets_unit_plasma_std_target_range_min 200
-// If we have a choise, prefer the ones closer to this distance
-set g_turrets_unit_plasma_std_target_range_optimal 500
-
-
-// Targetselect is made for each turret based on range, angle (turrets needs to turn to aim at), if its a player / missile
-// scale range score this mucth
-set g_turrets_unit_plasma_std_target_select_rangebias 0.5
-// scale 'same' score this mutch (stick with same target)
-set g_turrets_unit_plasma_std_target_select_samebias 0.01
-// and so on
-set g_turrets_unit_plasma_std_target_select_anglebias 0.25
-set g_turrets_unit_plasma_std_target_select_playerbias 1
-set g_turrets_unit_plasma_std_target_select_missilebias 0
-
-// Can carry this mutch ammo. one dmg = one ammo
-set g_turrets_unit_plasma_std_ammo_max 640
-// Start with this mutch ammo
-set g_turrets_unit_plasma_std_ammo 320
-// Regain ammo this fast (per sec)
-set g_turrets_unit_plasma_std_ammo_recharge 40
-
-// If predicted emeypos is this or closer to predicted impact, fire is ok
-set g_turrets_unit_plasma_std_aim_firetolerance_dist 120
-// Aim how fast. for track_type 1 this is dgr/sec, for 2 & 3 its the maximum angle speed added each second
-set g_turrets_unit_plasma_std_aim_speed 200
-// Max rottation of head
-set g_turrets_unit_plasma_std_aim_maxrot 360
-// Max pitch of head
-set g_turrets_unit_plasma_std_aim_maxpitch 30
-
-// How the head turns.
-// 1 = hard steps, good for aiming preformace, bad for visuals.
-// 2 = smooth w/o inertia
-// 3 = smmoth with simulated inertia
-set g_turrets_unit_plasma_std_track_type 3
-// Following controls how _track_type = 3 works.
-set g_turrets_unit_plasma_std_track_accel_pitch 0.5
-set g_turrets_unit_plasma_std_track_accel_rot 0.7
-set g_turrets_unit_plasma_std_track_blendrate 0.2
-
+++ /dev/null
-set g_turrets_unit_plasma_dual_health 500
-set g_turrets_unit_plasma_dual_respawntime 60
-
-set g_turrets_unit_plasma_dual_shot_dmg 80
-set g_turrets_unit_plasma_dual_shot_refire 0.35
-set g_turrets_unit_plasma_dual_shot_radius 150
-set g_turrets_unit_plasma_dual_shot_speed 2000
-set g_turrets_unit_plasma_dual_shot_spread 0.015
-set g_turrets_unit_plasma_dual_shot_force 100
-
-set g_turrets_unit_plasma_dual_shot_volly 0
-set g_turrets_unit_plasma_dual_shot_volly_refire 0
-
-set g_turrets_unit_plasma_dual_target_range 3000
-set g_turrets_unit_plasma_dual_target_range_min 80
-set g_turrets_unit_plasma_dual_target_range_optimal 1000
-
-set g_turrets_unit_plasma_dual_target_select_rangebias 0.2
-set g_turrets_unit_plasma_dual_target_select_samebias 0.4
-set g_turrets_unit_plasma_dual_target_select_anglebias 0.4
-set g_turrets_unit_plasma_dual_target_select_playerbias 1
-set g_turrets_unit_plasma_dual_target_select_missilebias 0
-
-set g_turrets_unit_plasma_dual_ammo_max 640
-set g_turrets_unit_plasma_dual_ammo 320
-set g_turrets_unit_plasma_dual_ammo_recharge 40
-
-set g_turrets_unit_plasma_dual_aim_firetolerance_dist 200
-
-set g_turrets_unit_plasma_dual_aim_speed 100
-set g_turrets_unit_plasma_dual_aim_maxrot 360
-set g_turrets_unit_plasma_dual_aim_maxpitch 30
-
-set g_turrets_unit_plasma_dual_track_type 3
-set g_turrets_unit_plasma_dual_track_accel_pitch 0.5
-set g_turrets_unit_plasma_dual_track_accel_rot 0.7
-set g_turrets_unit_plasma_dual_track_blendrate 0.2
-
+++ /dev/null
-set g_turrets_unit_tesla_std_health 1000
-set g_turrets_unit_tesla_std_respawntime 120
-
-set g_turrets_unit_tesla_std_shot_dmg 200
-set g_turrets_unit_tesla_std_shot_refire 1.5
-set g_turrets_unit_tesla_std_shot_force 400
-
-set g_turrets_unit_tesla_std_shot_volly 1
-set g_turrets_unit_tesla_std_shot_volly_refire 2.5
-
-set g_turrets_unit_tesla_std_target_range_min 0
-set g_turrets_unit_tesla_std_target_range 1000
-
-set g_turrets_unit_tesla_std_target_select_playerbias 1
-set g_turrets_unit_tesla_std_target_select_missilebias 1
-
-set g_turrets_unit_tesla_std_ammo_max 1000
-set g_turrets_unit_tesla_std_ammo 200
-set g_turrets_unit_tesla_std_ammo_recharge 15
+++ /dev/null
-set g_turrets_unit_walker_std_health 500
-set g_turrets_unit_walker_std_respawntime 60
-
-set g_turrets_unit_walker_speed_run 300
-set g_turrets_unit_walker_speed_roam 100
-set g_turrets_unit_walker_speed_walk 200
-set g_turrets_unit_walker_speed_swim 200
-set g_turrets_unit_walker_speed_jump 800
-set g_turrets_unit_walker_speed_stop 90
-
-set g_turrets_unit_walker_turn 20
-set g_turrets_unit_walker_turn_walk 15
-set g_turrets_unit_walker_turn_run 7
-set g_turrets_unit_walker_turn_swim 10
-set g_turrets_unit_walker_turn_strafe 5
-
-// Main machineguns prop's
-set g_turrets_unit_walker_std_shot_dmg 5
-set g_turrets_unit_walker_std_shot_refire 0.05
-set g_turrets_unit_walker_std_shot_spread 0.025
-set g_turrets_unit_walker_std_shot_force 10
-set g_turrets_unit_walker_std_shot_radius 0
-set g_turrets_unit_walker_std_shot_speed 18000
-
-set g_turrets_unit_walker_std_shot_volly 10
-set g_turrets_unit_walker_std_shot_volly_refire 1
-
-set g_turrets_unit_walker_std_target_range 5000
-set g_turrets_unit_walker_std_target_range_optimal 100
-set g_turrets_unit_walker_std_target_range_min 0
-
-set g_turrets_unit_walker_std_target_select_rangebias 0.25
-set g_turrets_unit_walker_std_target_select_samebias 0.25
-set g_turrets_unit_walker_std_target_select_anglebias 0.5
-set g_turrets_unit_walker_std_target_select_playerbias 1
-set g_turrets_unit_walker_std_target_select_missilebias 0
-
-set g_turrets_unit_walker_std_ammo_max 4000
-set g_turrets_unit_walker_std_ammo 500
-set g_turrets_unit_walker_std_ammo_recharge 100
-
-set g_turrets_unit_walker_std_aim_firetolerance_dist 100
-set g_turrets_unit_walker_std_aim_speed 45
-set g_turrets_unit_walker_std_aim_maxrot 90
-set g_turrets_unit_walker_std_aim_maxpitch 15
-
-// Head (minigun) is attached. must use tractype 1
-set g_turrets_unit_walker_std_track_type 1
-
-// "Wobbly" homing rockets that sometimes loop
-set g_turrets_unit_walker_std_rockets_range 4000
-set g_turrets_unit_walker_std_rockets_range_min 500
-set g_turrets_unit_walker_std_rocket_refire 10
-set g_turrets_unit_walker_std_rocket_dmg 45
-set g_turrets_unit_walker_std_rocket_radius 150
-set g_turrets_unit_walker_std_rocket_force 150
-set g_turrets_unit_walker_std_rocket_turnrate 0.05
-set g_turrets_unit_walker_std_rocket_speed 1000
-
-// Meele attack. Only happens when theres a target directly in front
-set g_turrets_unit_walker_std_meele_range 100
-set g_turrets_unit_walker_std_meele_dmg 100
-set g_turrets_unit_walker_std_meele_force 600
-
-set g_turrets_unit_walker_std_track_accel_pitch 0.5
-set g_turrets_unit_walker_std_track_accel_rot 0.8
-set g_turrets_unit_walker_std_track_blendrate 0.2