seta hud_panel_pressedkeys_bg_border "" "if set to something else than \"\" = override default size of border around the background"
seta hud_panel_pressedkeys_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
seta hud_panel_pressedkeys_aspect "" "forced aspect on panel"
+seta hud_panel_pressedkeys_attack "" "show attack buttons too"
seta hud_panel_chat "" "enable/disable this panel"
seta hud_panel_chat_pos "" "position of this base of the panel"
// 0: only damage from contents (lava/slime) or exceptions
// 1: only self damage or damage from contents or exceptions
// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
set g_projectiles_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
// 0: only damage from contents (lava/slime) or exceptions
// 1: only self damage or damage from contents or exceptions
// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
set g_projectiles_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
// 0: only damage from contents (lava/slime) or exceptions
// 1: only self damage or damage from contents or exceptions
// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
set g_projectiles_newton_style 0
// possible values:
// 0: absolute velocity projectiles (like Quake)
// 0: only damage from contents (lava/slime) or exceptions
// 1: only self damage or damage from contents or exceptions
// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
set g_projectiles_newton_style 2
// possible values:
// 0: absolute velocity projectiles (like Quake)
seta cl_gibs_maxcount 100 "maximum amount of gibs (must be at least 1)"
seta cl_vehicle_spiderbot_cross_alpha 0.6
seta cl_vehicle_spiderbot_cross_size 1
+seta cl_vehicles_hudscale 0.5
+seta cl_vehicles_hudalpha 0.75
+seta cl_vehicles_hud_tactical 1
//cl_gunalign calculator
seta menu_cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only"
//lightradius 50
//lightradiusfade 50
//lightcolor 1 0.9 0.7
-//lightshadow 1
\ No newline at end of file
+//lightshadow 1
cl_decals 1
-cl_decals_models 1
+cl_decals_models 0
cl_decals_time 10
cl_particles_quality 1
cl_damageeffect 1
seta hud_panel_pressedkeys_bg_border ""
seta hud_panel_pressedkeys_bg_padding ""
seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
seta hud_panel_chat 1
seta hud_panel_chat_pos "0.010000 0.700000"
seta hud_panel_pressedkeys_bg_border ""
seta hud_panel_pressedkeys_bg_padding ""
seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
seta hud_panel_chat 1
seta hud_panel_chat_pos "0 0.775000"
seta hud_panel_pressedkeys_bg_border ""
seta hud_panel_pressedkeys_bg_padding ""
seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
seta hud_panel_chat 1
seta hud_panel_chat_pos "0 0.775000"
seta hud_panel_pressedkeys_bg_border ""
seta hud_panel_pressedkeys_bg_padding ""
seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
seta hud_panel_chat 1
seta hud_panel_chat_pos "0.020000 0.780000"
seta hud_panel_pressedkeys_bg_border ""
seta hud_panel_pressedkeys_bg_padding ""
seta hud_panel_pressedkeys_aspect "1.600000"
+seta hud_panel_pressedkeys_attack "0"
seta hud_panel_chat 1
seta hud_panel_chat_pos "0 0.760000"
DamageInfo_Precache();
Vehicles_Precache();
turrets_precache();
- Announcer_Precache();
+ Announcer_Precache();
Tuba_Precache();
if(autocvar_cl_reticle)
float autocvar_cl_stripcolorcodes;
var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+var float autocvar_cl_vehicles_hud_tactical = 1;
float autocvar_cl_velocityzoom;
var float autocvar_cl_velocityzoom_type = 3;
float autocvar_cl_velocityzoom_speed;
float autocvar_hud_panel_powerups_text;
float autocvar_hud_panel_pressedkeys;
float autocvar_hud_panel_pressedkeys_aspect;
+float autocvar_hud_panel_pressedkeys_attack;
float autocvar_hud_panel_racetimer;
float autocvar_hud_panel_radar;
float autocvar_hud_panel_radar_foreground_alpha;
}
vector keysize;
- keysize = eX * mySize_x * (1/3) + eY * mySize_y * 0.5;
+ keysize = eX * mySize_x * (1/3.0) + eY * mySize_y * (1/(3.0 - !autocvar_hud_panel_pressedkeys_attack));
float pressedkeys;
pressedkeys = getstatf(STAT_PRESSED_KEYS);
+ if(autocvar_hud_panel_pressedkeys_attack)
+ {
+ drawpic_aspect_skin(pos + eX * keysize_x * 0.5, ((pressedkeys & KEY_ATCK) ? "key_atck_inv.tga" : "key_atck.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(pos + eX * keysize_x * 1.5, ((pressedkeys & KEY_ATCK2) ? "key_atck_inv.tga" : "key_atck.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ pos_y += keysize_y;
+ }
+
drawpic_aspect_skin(pos, ((pressedkeys & KEY_CROUCH) ? "key_crouch_inv.tga" : "key_crouch.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
drawpic_aspect_skin(pos + eX * keysize_x, ((pressedkeys & KEY_FORWARD) ? "key_forward_inv.tga" : "key_forward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
drawpic_aspect_skin(pos + eX * keysize_x * 2, ((pressedkeys & KEY_JUMP) ? "key_jump_inv.tga" : "key_jump.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
HUD_Write_PanelCvar_q("_dom_layout");
break;
case HUD_PANEL_PRESSEDKEYS:
+ HUD_Write_PanelCvar_q("_attack");
HUD_Write_PanelCvar_q("_aspect");
break;
case HUD_PANEL_ENGINEINFO:
return;
float dist = vlen(self.origin - view_origin);
+ float t = (GetPlayerColor(player_localnum) + 1);
+
vector o;
- /*
- // 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)
- {
- switch(hud)
- {
- case HUD_SPIDERBOT:
- case HUD_WAKIZASHI:
- case HUD_RAPTOR:
- vector pz = drawgetimagesize("gfx/vehicles/axh-bracket.tga") * 0.25;
- drawpic(o - pz * 0.5 , "gfx/vehicles/axh-bracket.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
- break;
+ 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)
+ {
+ switch(hud)
+ {
+ case HUD_SPIDERBOT:
+ case HUD_WAKIZASHI:
+ case HUD_RAPTOR:
+ if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
+ txt = "gfx/vehicles/vth-mover.tga";
+ else
+ txt = "gfx/vehicles/vth-stationary.tga";
+
+ vector pz = drawgetimagesize(txt) * 0.25;
+ drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
+ break;
+ }
}
- }
- */
+ }
if(dist > self.maxdistance)
return;
string spriteimage = self.netname;
- float t = (GetPlayerColor(player_localnum) + 1);
float a = self.alpha * autocvar_hud_panel_fg_alpha;
vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage));
}
- string txt = self.netname;
+ txt = self.netname;
if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
txt = _("Spam");
else
void turret_die()
{
- entity headgib;
sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
turret_tid2info(self.turret_type);
-
- // 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);
- }
+ 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
- turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
-
- 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;
+ {
+ 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;
+ }
}
}
void Vehicles_Precache()
{
// fixme: HAAAAKKKZZZ!!!!!!!!!!!! (this belongs as a setting in default.cfg)
- autocvar_cl_vehicles_hudscale = 0.5;
- autocvar_cl_vehicles_hudalpha = 0.75;
-
+ if(!autocvar_cl_vehicles_hudscale )
+ autocvar_cl_vehicles_hudscale = 0.5;
+
+ if(!autocvar_cl_vehicles_hudalpha)
+ autocvar_cl_vehicles_hudalpha = 0.75;
- precache_model("models/vehicles/wakizashi.dpm");
+ //precache_model("models/vehicles/wakizashi.dpm");
precache_model("models/vehicles/bomblet.md3");
precache_model("models/vehicles/clusterbomb.md3");
{
entlen = tokenize(l); // using insane tokenizer for CSV
-#define CAMPAIGN_GETARG0 if(i >= entlen)
-#define CAMPAIGN_GETARG1 CAMPAIGN_GETARG0 error("syntax error in campaign file: line has not enough fields");
-#define CAMPAIGN_GETARG2 CAMPAIGN_GETARG1 a = argv(++i);
-#define CAMPAIGN_GETARG3 CAMPAIGN_GETARG2 if(a == ",")
-#define CAMPAIGN_GETARG4 CAMPAIGN_GETARG3 a = "";
-#define CAMPAIGN_GETARG5 CAMPAIGN_GETARG4 else
-#define CAMPAIGN_GETARG CAMPAIGN_GETARG5 ++i
+#define CAMPAIGN_GETARG \
+ a = argv(++i); \
+ if(a == ",") \
+ a = ""; \
+ else \
+ ++i
// What you're seeing here is what people will do when your compiler supports
// C-style macros but no line continuations.
CAMPAIGN_GETARG; campaign_mutators[campaign_entries] = strzone(a);
CAMPAIGN_GETARG; campaign_shortdesc[campaign_entries] = strzone(a);
CAMPAIGN_GETARG; campaign_longdesc[campaign_entries] = strzone(strreplace("\\n", "\n", a));
+
+ if(i > entlen)
+ error("syntax error in campaign file: line has not enough fields");
+
campaign_entries = campaign_entries + 1;
if(campaign_entries >= n)
markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i;
markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i;
markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i;
+ unused_float = i;
}
string GenericCommand_markup(string s2)
const float KEY_RIGHT = 8;
const float KEY_JUMP = 16;
const float KEY_CROUCH = 32;
+const float KEY_ATCK = 64;
+const float KEY_ATCK2 = 128;
///////////////////////////
// cvar constants
# define WEPSET_BIT(a) power2of((a) - WEP_FIRST)
# define WEPSET_DECLARE_A(a) float _WS_##a
# define WEPSET_CLEAR_E(e) ((e)._WS_weapons = 0)
-# define WEPSET_CLEAR_A(a) ((_WS_##a) = 0)
+# define WEPSET_CLEAR_A(a) (_WS_##a = 0)
# define WEPSET_EMPTY_E(e) ((e)._WS_weapons == 0)
-# define WEPSET_EMPTY_A(a) ((_WS_##a) == 0)
-# define WEPSET_COPY_AS(a) ((_WS_##a) = getstati(STAT_WEAPONS))
+# define WEPSET_EMPTY_A(a) (_WS_##a == 0)
+# define WEPSET_COPY_AS(a) (_WS_##a = getstati(STAT_WEAPONS))
# define WEPSET_ADDSTAT() addstat(STAT_WEAPONS, AS_INT, _WS_weapons)
+# define WEPSET_WRITE_E(dest,a) WriteInt24_t(dest, (a)._WS_weapons)
+# define WEPSET_WRITE_A(dest,a) WriteInt24_t(dest, _WS_##a)
+# define WEPSET_WRITE_W(dest,a) WriteInt24_t(dest, WEPSET_BIT(a))
+# define WEPSET_READ_E(a) (a)._WS_weapons = ReadInt24_t()
+# define WEPSET_READ_A(a) (_WS_##a) = ReadInt24_t()
# define WEPSET_OP1_EE(a,b,mergeop,x) ((a)._WS_weapons x (b)._WS_weapons)
# define WEPSET_OP2_EE(a,b,mergeop,x,y) ((a)._WS_weapons x (b)._WS_weapons y (a)._WS_weapons)
# define WEPSET_OP1_EA(a,b,mergeop,x) ((a)._WS_weapons x _WS_##b)
# define WEPSET_EMPTY_A(a) ((_WS1_##a) == 0 && (_WS2_##a) == 0)
# define WEPSET_COPY_AS(a) ((_WS1_##a) = getstati(STAT_WEAPONS), (_WS2_##a) = getstati(STAT_WEAPONS2))
# define WEPSET_ADDSTAT() addstat(STAT_WEAPONS, AS_INT, _WS1_weapons); addstat(STAT_WEAPONS2, AS_INT, _WS2_weapons)
+# define WEPSET_WRITE_E(dest,a) WriteInt24_t(dest, (a)._WS1_weapons); WriteInt24_t(dest, (a)._WS2_weapons)
+# define WEPSET_WRITE_A(dest,a) WriteInt24_t(dest, _WS1_##a); WriteInt24_t(dest, _WS2_##a)
+# define WEPSET_WRITE_W(dest,a) WriteInt24_t(dest, WEPSET_BIT1(a)); WriteInt24_t(dest, WEPSET_BIT2(a))
+# define WEPSET_READ_E(a) (a)._WS1_weapons = ReadInt24_t(); (a)._WS2_weapons = ReadInt24_t()
+# define WEPSET_READ_A(a) (_WS1_##a) = ReadInt24_t(); (_WS2_##a) = ReadInt24_t()
# define WEPSET_OP1_EE(a,b,mergeop,x) (((a)._WS1_weapons x (b)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons))
# define WEPSET_OP2_EE(a,b,mergeop,x,y) (((a)._WS1_weapons x (b)._WS1_weapons y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons y (a)._WS2_weapons))
# define WEPSET_OP1_EA(a,b,mergeop,x) (((a)._WS1_weapons x _WS1_##b) mergeop ((a)._WS2_weapons x _WS2_##b))
MapInfo_Map_author = s;
else if(t == "has")
{
- t = car(s); s = cdr(s);
+ t = car(s); // s = cdr(s);
if (t == "weapons") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS;
else if(t == "turrets") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_TURRETS;
else if(t == "vehicles") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_VEHICLES;
return v;
}
+vector solve_shotdirection(vector myorg, vector myvel, vector eorg, vector evel, float spd, float newton_style)
+{
+ vector ret;
+
+ // make origin and speed relative
+ eorg -= myorg;
+ if(newton_style)
+ evel -= myvel;
+
+ // now solve for ret, ret normalized:
+ // eorg + t * evel == t * ret * spd
+ // or, rather, solve for t:
+ // |eorg + t * evel| == t * spd
+ // eorg^2 + t^2 * evel^2 + 2 * t * (eorg * evel) == t^2 * spd^2
+ // t^2 * (evel^2 - spd^2) + t * (2 * (eorg * evel)) + eorg^2 == 0
+ vector solution = solve_quadratic(evel * evel - spd * spd, 2 * (eorg * evel), eorg * eorg);
+ // p = 2 * (eorg * evel) / (evel * evel - spd * spd)
+ // q = (eorg * eorg) / (evel * evel - spd * spd)
+ if(!solution_z) // no real solution
+ {
+ // happens if D < 0
+ // (eorg * evel)^2 < (evel^2 - spd^2) * eorg^2
+ // (eorg * evel)^2 / eorg^2 < evel^2 - spd^2
+ // spd^2 < ((evel^2 * eorg^2) - (eorg * evel)^2) / eorg^2
+ // spd^2 < evel^2 * (1 - cos^2 angle(evel, eorg))
+ // spd^2 < evel^2 * sin^2 angle(evel, eorg)
+ // spd < |evel| * sin angle(evel, eorg)
+ return '0 0 0';
+ }
+ else if(solution_x > 0)
+ {
+ // both solutions > 0: take the smaller one
+ // happens if p < 0 and q > 0
+ ret = normalize(eorg + solution_x * evel);
+ }
+ else if(solution_y > 0)
+ {
+ // one solution > 0: take the larger one
+ // happens if q < 0 or q == 0 and p < 0
+ ret = normalize(eorg + solution_y * evel);
+ }
+ else
+ {
+ // no solution > 0: reject
+ // happens if p > 0 and q >= 0
+ // 2 * (eorg * evel) / (evel * evel - spd * spd) > 0
+ // (eorg * eorg) / (evel * evel - spd * spd) >= 0
+ //
+ // |evel| >= spd
+ // eorg * evel > 0
+ //
+ // "Enemy is moving away from me at more than spd"
+ return '0 0 0';
+ }
+
+ // NOTE: we always got a solution if spd > |evel|
+
+ if(newton_style == 2)
+ ret = normalize(ret * spd + myvel);
+
+ return ret;
+}
+
+vector get_shotvelocity(vector myvel, vector mydir, float spd, float newton_style, float mi, float ma)
+{
+ if(!newton_style)
+ return spd * mydir;
+
+ if(newton_style == 2)
+ {
+ // true Newtonian projectiles with automatic aim adjustment
+ //
+ // solve: |outspeed * mydir - myvel| = spd
+ // outspeed^2 - 2 * outspeed * (mydir * myvel) + myvel^2 - spd^2 = 0
+ // outspeed = (mydir * myvel) +- sqrt((mydir * myvel)^2 - myvel^2 + spd^2)
+ // PLUS SIGN!
+ // not defined?
+ // then...
+ // myvel^2 - (mydir * myvel)^2 > spd^2
+ // velocity without mydir component > spd
+ // fire at smallest possible spd that works?
+ // |(mydir * myvel) * myvel - myvel| = spd
+
+ vector solution = solve_quadratic(1, -2 * (mydir * myvel), myvel * myvel - spd * spd);
+
+ float outspeed;
+ if(solution_z)
+ outspeed = solution_y; // the larger one
+ else
+ {
+ //outspeed = 0; // slowest possible shot
+ outspeed = solution_x; // the real part (that is, the average!)
+ //dprint("impossible shot, adjusting\n");
+ }
+
+ outspeed = bound(spd * mi, outspeed, spd * ma);
+ return mydir * outspeed;
+ }
+
+ // real Newtonian
+ return myvel + spd * mydir;
+}
+
void check_unacceptable_compiler_bugs()
{
if(cvar("_allow_unacceptable_compiler_bugs"))
}
to_execute_next_frame = strzone(s);
}
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+ return
+ ((( startspeedfactor + endspeedfactor - 2
+ ) * x - 2 * startspeedfactor - endspeedfactor + 3
+ ) * x + startspeedfactor
+ ) * x;
+}
+
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+ if(startspeedfactor < 0 || endspeedfactor < 0)
+ return FALSE;
+
+ /*
+ // if this is the case, the possible zeros of the first derivative are outside
+ // 0..1
+ We can calculate this condition as condition
+ if(se <= 3)
+ return TRUE;
+ */
+
+ // better, see below:
+ if(startspeedfactor <= 3 && endspeedfactor <= 3)
+ return TRUE;
+
+ // if this is the case, the first derivative has no zeros at all
+ float se = startspeedfactor + endspeedfactor;
+ float s_e = startspeedfactor - endspeedfactor;
+ if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+ return TRUE;
+
+ // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+ // we also get s_e <= 6 - se
+ // 3 * (se - 4)^2 + (6 - se)^2
+ // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+ // Therefore, above "better" check works!
+
+ return FALSE;
+
+ // known good cases:
+ // (0, [0..3])
+ // (0.5, [0..3.8])
+ // (1, [0..4])
+ // (1.5, [0..3.9])
+ // (2, [0..3.7])
+ // (2.5, [0..3.4])
+ // (3, [0..3])
+ // (3.5, [0.2..2.3])
+ // (4, 1)
+}
// z = 1 if a real solution exists, 0 if not
// if no real solution exists, x contains the real part and y the imaginary part of the complex solutions x+iy and x-iy
+vector solve_shotdirection(vector myorg, vector myvel, vector eorg, vector evel, float spd, float newton_style);
+vector get_shotvelocity(vector myvel, vector mydir, float spd, float newton_style, float mi, float ma);
+
void check_unacceptable_compiler_bugs();
float compressShotOrigin(vector v);
// execute-stuff-next-frame subsystem
void execute_next_frame();
void queue_to_execute_next_frame(string s);
+
+// for marking written-to values as unused where it's a good idea to do this
+noref float unused_float;
+
+
+
+// a function f with:
+// f(0) = 0
+// f(1) = 1
+// f'(0) = startspeedfactor
+// f'(1) = endspeedfactor
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x);
+
+// checks whether f'(x) = 0 anywhere from 0 to 1
+// because if this is the case, the function is not usable for platforms
+// as it may exceed 0..1 bounds, or go in reverse
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
float islocalplayer = (self == to);
float isnolocalplayer = (isplayer && (self != to));
+ unused_float = isplayer;
+ unused_float = islocalplayer;
+ unused_float = isnolocalplayer;
+
WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
WriteShort(MSG_ENTITY, sf);
float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+ unused_float = isplayer;
+ unused_float = islocalplayer;
+ unused_float = isnolocalplayer;
+
#ifdef CSQCPLAYER_FORCE_UPDATES
if(isplayer && time > self.csqcmodel_nextforcedupdate)
{
other.parent = me;
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
else if(ch2 == "x") // ^x found
{
theColor = '1 1 1';
- theTempColor = '0 0 0';
component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
if (component >= 0) // ^xr found
}
float InputContainer_mouseRelease(entity me, vector pos)
{
- float r;
- r = SUPER(InputContainer).mouseRelease(me, pos);
+ SUPER(InputContainer).mouseRelease(me, pos); // return value?
if(me.focused) // am I still eligible for this? (UGLY HACK, but a mouse event could have changed focus away)
if(me._changeFocusXY(me, pos))
return 1;
// and give it a nice click event
if(me.nItems > 0)
{
- absSize = boxToGlobalSize(me.size, eX * (1 - me.controlWidth) + eY * me.itemHeight);
me.clickListBoxItem(me, me.selectedItem, globalToBox(pos, eY * (me.selectedItem * me.itemHeight - me.scrollPos), eX * (1 - me.controlWidth) + eY * me.itemHeight));
}
}
me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Game settings:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating")));
+ me.TD(me, 1, 2.8, makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Spawn shield:")));
- me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime"));
+ me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Spawn shield:")));
+ me.TD(me, 1, 1.6, makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime"));
me.TR(me);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Game speed:")));
- me.TD(me, 1, 1.6, e = makeXonoticSlider(0.5, 2.0, 0.1, "slowmo"));
+ me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Game speed:")));
+ me.TD(me, 1, 1.6, makeXonoticSlider(0.5, 2.0, 0.1, "slowmo"));
me.TR(me);
me.TR(me);
me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Teamplay settings:")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire scale:")));
- me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire"));
+ me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire scale:")));
+ me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire"));
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)")));
+ me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire penalty:")));
- me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage"));
+ me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire penalty:")));
+ me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage"));
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)")));
+ me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Teams:")));
+ me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Teams:")));
me.TD(me, 1, 1.6, e = makeXonoticTextSlider("g_tdm_teams_override g_domination_teams_override g_keyhunt_teams_override"));
e.addValue(e, "Default", "0");
e.addValue(e, "2 teams", "2");
e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Map voting:")));
+ me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Map voting:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("g_maplist_votable"));
e.addValue(e, _("No voting"), "0");
e.addValue(e, _("2 choices"), "2");
e.addValue(e, _("9 choices"), "9");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall")));
+ me.TD(me, 1, 3, makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall")));
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
setDependentStringNotEqual(s, "mastervolume", "0");
me.TR(me);
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
+ me.TD(me, 1, 3, makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "snd_mutewhenidle", _("Mute sounds when not active")));
+ me.TD(me, 1, 3, makeXonoticCheckBox(0, "snd_mutewhenidle", _("Mute sounds when not active")));
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Frequency:")));
+ me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Frequency:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_speed"));
e.addValue(e, _("8 kHz"), "8000");
e.addValue(e, _("11.025 kHz"), "11025");
e.addValue(e, _("48 kHz"), "48000");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Channels:")));
+ me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Channels:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_channels"));
e.addValue(e, _("Mono"), "1");
e.addValue(e, _("Stereo"), "2");
me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode")));
setDependent(e, "snd_channels", 1.5, 0.5);
me.TR(me);
- /*me.TR(me); // Samual: I REALLY don't think these are relevant to anyone, and just clutter up the menu pointlessly. The defaults are fine.
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Spatial voices:")));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "0", ZCTX(_("VOCS^None"))));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "2", ZCTX(_("VOCS^Taunts"))));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "1", ZCTX(_("VOCS^All"))));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Taunt range:")));
- setDependent(e, "cl_voice_directional", 0.5, -0.5);
- me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_voice_directional_taunt_attenuation"));
- e.addValue(e, ZCTX(_("RNG^Very short")), "3");
- e.addValue(e, ZCTX(_("RNG^Short")), "2");
- e.addValue(e, ZCTX(_("RNG^Normal")), "0.5");
- e.addValue(e, ZCTX(_("RNG^Long")), "0.25");
- e.addValue(e, ZCTX(_("RNG^Full")), "0.015625");
- e.configureXonoticTextSliderValues(e);
- setDependent(e, "cl_voice_directional", 0.5, -0.5);
- me.TR(me);*/
+ me.TD(me, 1, 3, makeXonoticCheckBox(0, "cl_hitsound", _("Hit indication sound")));
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_hitsound", _("Hit indication sound")));
+ me.TD(me, 1, 3, makeXonoticCheckBox(0, "con_chatsound", _("Chat message sound")));
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_chatsound", _("Chat message sound")));
+ me.TD(me, 1, 3, makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds")));
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds")));
me.TR(me);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Time announcer:")));
+ me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Time announcer:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_announcer_maptime"));
e.addValue(e, ZCTX(_("WRN^Disabled")), "0");
e.addValue(e, _("1 minute"), "1");
e.savedValue = 0.65; // default
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Frequency:")));
+ me.TD(me, 1, 0.8, makeXonoticTextLabel(0, _("Frequency:")));
me.TD(me, 1, 2, sl);
me.TR(me);
me.TR(me);
if(cvar("developer"))
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
-
+ me.TD(me, 1, 3, makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_$menu_snd_attenuation_method; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY));
#define GAMETYPE(id) if(i++ == cnt) return id;
GAMETYPES
#undef GAMETYPE
+
+ unused_float = i;
return 0;
}
string autocvar_g_playerstats_uri;
float autocvar_g_powerups;
float autocvar_g_projectiles_damage;
+float autocvar_g_projectiles_keep_owner;
float autocvar_g_projectiles_newton_style;
float autocvar_g_projectiles_newton_style_2_maxfactor;
float autocvar_g_projectiles_newton_style_2_minfactor;
rr = CTS_RECORD;
else
rr = RACE_RECORD;
- t = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
msg_entity = self;
race_send_recordtime(MSG_ONE);
self.pressedkeys |= KEY_CROUCH;
else
self.pressedkeys &~= KEY_CROUCH;
+
+ if (self.BUTTON_ATCK)
+ self.pressedkeys |= KEY_ATCK;
+ else
+ self.pressedkeys &~= KEY_ATCK;
+ if (self.BUTTON_ATCK2)
+ self.pressedkeys |= KEY_ATCK2;
+ else
+ self.pressedkeys &~= KEY_ATCK2;
}
/*
{
vector mdirection;
float mspeed;
- float outspeed;
- float nstyle;
vector outvelocity;
mvelocity = mvelocity * g_weaponspeedfactor;
mdirection = normalize(mvelocity);
mspeed = vlen(mvelocity);
- nstyle = autocvar_g_projectiles_newton_style;
- if(nstyle == 0 || forceAbsolute)
- {
- // absolute velocity
- outvelocity = mvelocity;
- }
- else if(nstyle == 1)
- {
- // true Newtonian projectiles
- outvelocity = pvelocity + mvelocity;
- }
- else if(nstyle == 2)
- {
- // true Newtonian projectiles with automatic aim adjustment
- //
- // solve: |outspeed * mdirection - pvelocity| = mspeed
- // outspeed^2 - 2 * outspeed * (mdirection * pvelocity) + pvelocity^2 - mspeed^2 = 0
- // outspeed = (mdirection * pvelocity) +- sqrt((mdirection * pvelocity)^2 - pvelocity^2 + mspeed^2)
- // PLUS SIGN!
- // not defined?
- // then...
- // pvelocity^2 - (mdirection * pvelocity)^2 > mspeed^2
- // velocity without mdirection component > mspeed
- // fire at smallest possible mspeed that works?
- // |(mdirection * pvelocity) * pvelocity - pvelocity| = mspeed
-
- vector solution;
- solution = solve_quadratic(1, -2 * (mdirection * pvelocity), pvelocity * pvelocity - mspeed * mspeed);
- if(solution_z)
- outspeed = solution_y; // the larger one
- else
- {
- //outspeed = 0; // slowest possible shot
- outspeed = solution_x; // the real part (that is, the average!)
- //dprint("impossible shot, adjusting\n");
- }
-
- outspeed = bound(mspeed * autocvar_g_projectiles_newton_style_2_minfactor, outspeed, mspeed * autocvar_g_projectiles_newton_style_2_maxfactor);
- outvelocity = mdirection * outspeed;
- }
- else
- error("g_projectiles_newton_style must be 0 (absolute), 1 (Newtonian) or 2 (Newtonian + aimfix)!");
+ outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor);
return outvelocity;
}
}
}
-void ClientCommand_reportcvar(float request, float argc, string command)
-{
- switch(request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if(argv(1) != "")
- {
- float tokens;
- string s;
-
- if(substring(argv(2), 0, 1) == "$") // undefined cvar: use the default value on the server then
- {
- s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
- tokens = tokenize_console(s);
- }
-
- GetCvars(1);
-
- return;
- }
- }
-
- default:
- sprint(self, "Incorrect parameters for ^2reportcvar^7\n");
- case CMD_REQUEST_USAGE:
- {
- sprint(self, "\nUsage:^3 cmd reportcvar <cvar>\n");
- sprint(self, " Where 'cvar' is the cvar plus arguments to send to the server.\n");
- return;
- }
- }
-}
-
void ClientCommand_say(float request, float argc, string command)
{
switch(request)
if(argc == 2) // undefined cvar: use the default value on the server then
{
s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\"");
- tokens = tokenize_console(s);
+ tokenize_console(s);
}
GetCvars(1);
CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(request, arguments), "Retrieve mapshot picture from the server") \
CLIENT_COMMAND("join", ClientCommand_join(request), "Become a player in the game") \
CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
- CLIENT_COMMAND("reportcvar", ClientCommand_reportcvar(request, arguments, command), "Old system for sending a client cvar to the server") \
CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \
CLIENT_COMMAND("say_team", ClientCommand_say_team(request, arguments, command), "Print a message to chat to all team mates") \
CLIENT_COMMAND("selectteam", ClientCommand_selectteam(request, arguments), "Attempt to choose a team to join into") \
case "mv_getpicture": break; // handled by server in this file
case "pause": break; // handled by engine in host_cmd.c
case "prespawn": break; // handled by engine in host_cmd.c
- case "reportcvar": break; // handled by server in this file
case "sentcvar": break; // handled by server in this file
case "spawn": break; // handled by engine in host_cmd.c
c = trace_endpos;
}
- n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world);
+ n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world, FALSE);
white += vlen(trace_endpos - c);
c = trace_endpos;
}
return FALSE;
-}
\ No newline at end of file
+}
.float t_length, t_width;
.vector destvec; // for rain
+.vector destvec2; // for train
.float cnt; // for rain
.float count;
//.float cnt2;
// after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
float culprit;
culprit = DEATH_WEAPONOF(deathtype);
- if(!culprit || !WEPSET_CONTAINS_EW(attacker, culprit))
+ if(!culprit)
+ culprit = attacker.weapon;
+ else if(!WEPSET_CONTAINS_EW(attacker, culprit))
culprit = attacker.weapon;
if(g_weaponarena_random_with_laser && culprit == WEP_LASER)
if(autocvar_g_mirrordamage_virtual)
{
- vector v;
- v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
- v_z = 0; // fteqcc sucks
+ vector v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
attacker.dmg_take += v_x;
attacker.dmg_save += v_y;
attacker.dmg_inflictor = inflictor;
if(autocvar_g_friendlyfire_virtual)
{
- vector v;
- v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
- v_z = 0; // fteqcc sucks
+ vector v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
targ.dmg_take += v_x;
targ.dmg_save += v_y;
targ.dmg_inflictor = inflictor;
float phasepos;
float nexttick;
vector delta;
+ vector delta2;
vector veloc;
vector nextpos;
+ delta = self.destvec;
+ delta2 = self.destvec2;
if(time < self.animstate_endtime) {
- delta = self.destvec;
nexttick = time + sys_frametime;
- if(nexttick < self.animstate_endtime) {
- traveltime = self.animstate_endtime - self.animstate_starttime;
- phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
+ traveltime = self.animstate_endtime - self.animstate_starttime;
+ phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
+ if(self.platmovetype != 1)
+ {
phasepos = 3.14159265 + (phasepos * 3.14159265); // range: [pi, 2pi]
phasepos = cos(phasepos); // cos [pi, 2pi] is in [-1, 1]
phasepos = phasepos + 1; // correct range to [0, 2]
phasepos = phasepos / 2; // correct range to [0, 1]
- nextpos = self.origin + (delta * phasepos);
+ }
+ nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
+ // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
+ if(nexttick < self.animstate_endtime) {
veloc = nextpos - self.owner.origin;
veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
-
} else {
veloc = self.finaldest - self.owner.origin;
veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
self.owner.velocity = veloc;
self.nextthink = nexttick;
} else {
+ // derivative: delta + 2 * delta2 (e.g. for angle positioning)
oldself = self;
self.owner.think = self.think1;
self = self.owner;
}
}
-void SUB_CalcMove (vector tdest, float tspeed, void() func)
+void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector dest)
+{
+ // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
+ // 2 * control * t - 2 * control * t * t + dest * t * t
+ // 2 * control * t + (dest - 2 * control) * t * t
+
+ controller.origin = org; // starting point
+ control -= org;
+ dest -= org;
+
+ controller.destvec = 2 * control; // control point
+ controller.destvec2 = dest - 2 * control; // quadratic part required to reach end point
+}
+
+void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest)
+{
+ // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
+ // 2 * control * t - 2 * control * t * t + dest * t * t
+ // 2 * control * t + (dest - 2 * control) * t * t
+
+ controller.origin = org; // starting point
+ dest -= org;
+
+ controller.destvec = dest; // end point
+ controller.destvec2 = '0 0 0';
+}
+
+void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() func)
{
- vector delta;
float traveltime;
entity controller;
self.finaldest = tdest;
self.think = SUB_CalcMoveDone;
- if (tdest == self.origin)
- {
- self.velocity = '0 0 0';
- self.nextthink = self.ltime + 0.1;
- return;
- }
+ if(tspeed > 0) // positive: start speed
+ traveltime = 2 * vlen(tcontrol - self.origin) / tspeed;
+ else // negative: end speed
+ traveltime = 2 * vlen(tcontrol - tdest) / -tspeed;
- delta = tdest - self.origin;
- traveltime = vlen (delta) / tspeed;
-
- if (traveltime < 0.1)
+ if (traveltime < 0.1) // useless anim
{
self.velocity = '0 0 0';
self.nextthink = self.ltime + 0.1;
return;
}
- // Very short animations don't really show off the effect
- // of controlled animation, so let's just use linear movement.
- // Alternatively entities can choose to specify non-controlled movement.
- // The only currently implemented alternative movement is linear (value 1)
- if (traveltime < 0.15 || self.platmovetype == 1)
- {
- self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
- self.nextthink = self.ltime + traveltime;
- return;
- }
-
controller = spawn();
controller.classname = "SUB_CalcMove_controller";
controller.owner = self;
- controller.origin = self.origin; // starting point
+ controller.platmovetype = self.platmovetype;
+ SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest);
controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit.
- controller.destvec = delta;
controller.animstate_starttime = time;
controller.animstate_endtime = time + traveltime;
controller.think = SUB_CalcMove_controller_think;
self = self.owner;
}
+void SUB_CalcMove (vector tdest, float tspeed, void() func)
+{
+ vector delta;
+ float traveltime;
+
+ if (!tspeed)
+ objerror ("No speed is defined!");
+
+ self.think1 = func;
+ self.finaldest = tdest;
+ self.think = SUB_CalcMoveDone;
+
+ if (tdest == self.origin)
+ {
+ self.velocity = '0 0 0';
+ self.nextthink = self.ltime + 0.1;
+ return;
+ }
+
+ delta = tdest - self.origin;
+ traveltime = vlen (delta) / tspeed;
+
+ // Very short animations don't really show off the effect
+ // of controlled animation, so let's just use linear movement.
+ // Alternatively entities can choose to specify non-controlled movement.
+ // The only currently implemented alternative movement is linear (value 1)
+ if (traveltime < 0.15 || self.platmovetype == 1)
+ {
+ self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
+ self.nextthink = self.ltime + traveltime;
+ return;
+ }
+
+ // now just run like a bezier curve...
+ SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeed, func);
+}
+
void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
{
entity oldself;
tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE);
}
-float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent) // returns the number of traces done, for benchmarking
+float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity) // returns the number of traces done, for benchmarking
{
vector pos, dir, t;
float nudge;
+ entity stopentity;
//nudge = 2 * cvar("collision_impactnudge"); // why not?
nudge = 0.5;
dprint(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
}
+ stopentity = trace_ent;
+
if(trace_startsolid)
{
// we started inside solid.
// t is still inside solid? bad
// force advance, then, and retry
pos = t + dir * nudge;
+
+ // but if we hit an entity, stop RIGHT before it
+ if(stopatentity && stopentity)
+ {
+ trace_ent = stopentity;
+ trace_endpos = t;
+ trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
+ return c;
+ }
}
else
{
}
}
-void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent)
+void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity)
{
-#if 0
- vector pos, dir, t;
- float nudge;
-
- //nudge = 2 * cvar("collision_impactnudge"); // why not?
- nudge = 0.5;
-
- dir = normalize(v2 - v1);
-
- pos = v1 + dir * nudge;
-
- for(;;)
- {
- if((pos - v1) * dir >= (v2 - v1) * dir)
- {
- // went too far
- trace_fraction = 1;
- return;
- }
-
- traceline(pos, v2, nomonsters, forent);
-
- if(trace_startsolid)
- {
- // we started inside solid.
- // then trace from endpos to pos
- t = trace_endpos;
- traceline(t, pos, nomonsters, forent);
- if(trace_startsolid)
- {
- // t is inside solid? bad
- // force advance, then
- pos = pos + dir * nudge;
- }
- else
- {
- // we actually LEFT solid!
- trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
- return;
- }
- }
- else
- {
- // pos is outside solid?!? but why?!? never mind, just return it.
- trace_endpos = pos;
- trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
- return;
- }
- }
-#else
- tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent);
+ tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity);
}
/*
void attach_sameorigin(entity e, entity to, string tag)
{
vector org, t_forward, t_left, t_up, e_forward, e_up;
- vector org0, ang0;
float tagscale;
- ang0 = e.angles;
- org0 = e.origin;
-
org = e.origin - gettaginfo(to, gettagindex(to, tag));
tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
t_forward = v_forward * tagscale;
{
if(time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
- g_freezetag = 1;
freezetag_Initialize();
}
MUTATOR_ONREMOVE
{
- g_freezetag = 0;
error("This is a game type and it cannot be removed at runtime.");
}
{
if(time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
- g_keepaway = 1;
ka_Initialize();
}
MUTATOR_ONREMOVE
{
- g_keepaway = 0;
error("This is a game type and it cannot be removed at runtime.");
}
{
if(time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
- g_keyhunt = 1;
kh_Initialize();
}
MUTATOR_ONREMOVE
{
- g_keyhunt = 0;
error("This is a game type and it cannot be removed at runtime.");
}
MUTATOR_ONADD
{
- g_nexball = 1;
g_nexball_meter_period = autocvar_g_nexball_meter_period;
if(g_nexball_meter_period <= 0)
g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
float velocity_difference;
float clean_up_and_do_nothing;
+ if (self.deadflag != DEAD_NO)
+ return 0;
+
new_velocity_gain = 0;
clean_up_and_do_nothing = 0;
}
}
-
-
if (dodge_detected == 1) {
self.last_dodging_time = time;
entity curse1, rune1, curse2, rune2;
- rune = curse = world;
rcount = ccount = r = c = 0;
rune = find(rune, classname, "rune");
while(rune)
numtodrop = autocvar_g_runematch_drop_runes_max;
prevent_same = !autocvar_g_runematch_allow_same;
- rune = curse = world;
do
{
rune = find(rune, classname, "rune");
float autocvar_g_vehicle_racer_rocket_locking_releasetime;
float autocvar_g_vehicle_racer_rocket_locked_time;
float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+float autocvar_g_vehicle_racer_rocket_climbspeed;
float autocvar_g_vehicle_racer_respawntime;
var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
-void racer_align4point()
+void racer_align4point(float _delta)
{
- vector push_vector, v_add;
+ vector push_vector;
float fl_push, fr_push, bl_push, br_push;
-
push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
fr_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
fl_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
br_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
bl_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
- self.velocity += (push_vector * frametime);
+ self.velocity += push_vector * _delta;
// Anti ocilation
- if(self.velocity_z > 0)
- self.velocity_z *= 1 - (autocvar_g_vehicle_racer_upforcedamper * frametime);
-
- self.velocity += v_add;
- //self.velocity_z -= autocvar_sv_gravity * frametime;
+ if(self.velocity_z > 0)
+ self.velocity_z *= 1 - autocvar_g_vehicle_racer_upforcedamper * _delta;
push_vector_x = (fl_push - bl_push);
push_vector_x += (fr_push - br_push);
push_vector_z *= 360;
// Apply angle diffrance
- self.angles_z += push_vector_z * frametime;
- self.angles_x += push_vector_x * frametime;
+ self.angles_z += push_vector_z * _delta;
+ self.angles_x += push_vector_x * _delta;
// Apply stabilizer
- self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
- self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
+ self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+ self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
}
void racer_fire_cannon(string tagname)
newvel = oldvel + self.lip;
makevectors(vectoangles(olddir));
+ float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
+ vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
+
traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
- newdir = normalize(self.enemy.origin - self.origin);
+ newdir = normalize(predicted_origin - self.origin);
+
+ //vector
+ float height_diff = predicted_origin_z - self.origin_z;
if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
{
return;
}
- if(trace_fraction != 1.0)
+ if(trace_fraction != 1.0 && trace_ent != self.enemy)
newdir_z += 16 * sys_frametime;
self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
self.velocity_z -= 800 * sys_frametime;
+ self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
UpdateCSQCProjectile(self);
return;
void racer_fire_rocket(string tagname, entity trg)
{
- vector v;
- entity rocket;
-
- v = gettaginfo(self, gettagindex(self, tagname));
- rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
+ vector v = gettaginfo(self, gettagindex(self, tagname));
+ entity rocket = rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
DEATH_WAKIROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE);
player = self;
racer = self.vehicle;
self = racer;
-
+
player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
-
+
vehicles_painframe();
-
+
if(racer.deadflag != DEAD_NO)
{
self = player;
return 1;
}
- racer_align4point();
+ racer_align4point(frametime);
crosshair_trace(player);
makevectors(racer.angles);
racer.angles_x *= -1;
-
- ftmp = racer.velocity_z;
+ //ftmp = racer.velocity_z;
df = racer.velocity * -autocvar_g_vehicle_racer_friction;
- racer.velocity_z = ftmp;
+ //racer.velocity_z = ftmp;
- if(player.movement_x != 0)
- {
- if(player.movement_x > 0)
- df += v_forward * autocvar_g_vehicle_racer_speed_forward;
- else if(player.movement_x < 0)
- df -= v_forward * autocvar_g_vehicle_racer_speed_forward;
- }
-
- if(player.movement_y != 0)
- {
- if(player.movement_y < 0)
- df -= v_right * autocvar_g_vehicle_racer_speed_strafe;
- else if(player.movement_y > 0)
- df += v_right * autocvar_g_vehicle_racer_speed_strafe;
- }
-
if(vlen(player.movement) != 0)
{
+ if(player.movement_x)
+ df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward);
+
+ if(player.movement_y)
+ df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe);
+
if(self.sound_nexttime < time || self.sounds != 1)
- {
+ {
self.sounds = 1;
self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTN_NORM);
}
}
else
- {
+ {
if(self.sound_nexttime < time || self.sounds != 0)
- {
+ {
self.sounds = 0;
self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTN_NORM);
- }
+ }
}
-
+
// Afterburn
if (player.BUTTON_JUMP && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * frametime))
{
if(time - racer.wait > 0.2)
- pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin, '0 0 0', 1);
-
+ pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin, '0 0 0', 1);
+
racer.wait = time;
racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * frametime;
df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
-
- if(self.invincible_finished < time)
- {
- traceline(self.origin, self.origin - '0 0 256', MOVE_NORMAL, self);
+
+ if(racer.invincible_finished < time)
+ {
+ traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
if(trace_fraction != 1.0)
pointparticles(particleeffectnum("smoke_small"), trace_endpos, '0 0 0', 1);
-
- self.invincible_finished = time + 0.1 + (random() * 0.1);
+
+ racer.invincible_finished = time + 0.1 + (random() * 0.1);
}
- if(self.strength_finished < time)
- {
- //self.sounds = 2;
- self.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
- sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTN_NORM);
- }
+ if(racer.strength_finished < time)
+ {
+ racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
+ sound (racer.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTN_NORM);
+ }
}
else
{
- self.strength_finished = 0;
- sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
+ racer.strength_finished = 0;
+ sound (racer.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
}
-
- racer.velocity += df * frametime;
-
- df = (vlen(racer.velocity) * autocvar_g_vehicle_racer_downforce * v_up) * frametime;
- racer.velocity = racer.velocity - df;
- player.movement = racer.velocity;
+ df -= v_up * (vlen(racer.velocity) * autocvar_g_vehicle_racer_downforce);
+ player.movement = racer.velocity += df * frametime;
if(player.BUTTON_ATCK)
if(time > racer.attack_finished_single)
racer.cnt = 1;
}
racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire;
- //self.owner.vehicle_energy = racer.vehicle_energy / autocvar_g_vehicle_racer_energy;
}
if(autocvar_g_vehicle_racer_rocket_locktarget)
if(time > racer.delay)
if(player.BUTTON_ATCK2)
{
- self.misc_bulletcounter += 1;
+ racer.misc_bulletcounter += 1;
racer.delay = time + 0.3;
- if(self.misc_bulletcounter == 1)
- racer_fire_rocket("tag_rocket_r", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
- else if(self.misc_bulletcounter == 2)
+
+ if(racer.misc_bulletcounter == 1)
+ racer_fire_rocket("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+ else if(racer.misc_bulletcounter == 2)
{
- racer_fire_rocket("tag_rocket_l", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
- self.lock_strength = 0;
- self.lock_target = world;
- self.misc_bulletcounter = 0;
+ racer_fire_rocket("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+ racer.lock_strength = 0;
+ racer.lock_target = world;
+ racer.misc_bulletcounter = 0;
racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
racer.lip = time;
}
player.vehicle_reload1 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
- if(self.vehicle_flags & VHF_SHIELDREGEN)
+ if(racer.vehicle_flags & VHF_SHIELDREGEN)
vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime);
- if(self.vehicle_flags & VHF_HEALTHREGEN)
+ if(racer.vehicle_flags & VHF_HEALTHREGEN)
vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime);
- if(self.vehicle_flags & VHF_ENERGYREGEN)
+ if(racer.vehicle_flags & VHF_ENERGYREGEN)
vehicles_regen(wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime);
VEHICLE_UPDATE_PLAYER(health, racer);
VEHICLE_UPDATE_PLAYER(energy, racer);
- if(self.vehicle_flags & VHF_HASSHIELD)
+ if(racer.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(shield, racer);
-
player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
setorigin(player,racer.origin + '0 0 32');
player.velocity = racer.velocity;
void racer_think()
{
- /*
- float a, b, c;a = autocvar_g_vehicle_racer_anglestabilizer;
- b = autocvar_g_vehicle_racer_springlength;
- c = autocvar_g_vehicle_racer_hoverpower;
-
- autocvar_g_vehicle_racer_anglestabilizer = 36;
- autocvar_g_vehicle_racer_springlength = 96;
- autocvar_g_vehicle_racer_hoverpower = 300;
- */
-
- racer_align4point(); //time - self.nextthink);
-
- /*
- //if(self.velocity_z > 0)
- // self.velocity_z *= 0.95;
-
- autocvar_g_vehicle_racer_anglestabilizer = a;
- autocvar_g_vehicle_racer_springlength = b;
- autocvar_g_vehicle_racer_hoverpower = c;
- */
-
- self.velocity_x *= 0.9;
- self.velocity_y *= 0.9;
- self.velocity_z *= 0.8;
- self.velocity_z += sin(time * 2) * 16;
- self.nextthink = time; // + 0.05;
+ self.nextthink = time;
+
+ float pushdeltatime = time - self.lastpushtime;
+ if (pushdeltatime > 0.15) pushdeltatime = 0;
+ self.lastpushtime = time;
+ if(!pushdeltatime) return;
+
+ tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NORMAL, self);
+
+ vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
+ df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
+
+ self.velocity += df * pushdeltatime;
+ if(self.velocity_z > 0)
+ self.velocity_z *= 1 - autocvar_g_vehicle_racer_upforcedamper * pushdeltatime;
+
+ self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+ self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
}
void racer_enter()
self.movetype = MOVETYPE_BOUNCE;
self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100;
self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100;
-
+
if(self.owner.flagcarried)
setorigin(self.owner.flagcarried, '-190 0 96');
+
+ //targetdrone_spawn(self.origin + '0 0 512' + randomvec() * 256, 1);
}
void racer_exit(float eject)
{
vector spot;
-
+
self.think = racer_think;
self.nextthink = time;
- self.movetype = MOVETYPE_TOSS;
+ self.movetype = MOVETYPE_BOUNCE;
sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM);
-
+
if not (self.owner)
return;
}
else
{
- self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed;
+ if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+ {
+ self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+ self.owner.velocity_z += 200;
+ spot = self.origin + v_forward * 32 + '0 0 32';
+ spot = vehicles_findgoodexit(spot);
+ }
+ else
+ {
+ self.owner.velocity = self.velocity * 0.5;
+ self.owner.velocity_z += 10;
+ spot = self.origin - v_forward * 200 + '0 0 32';
+ spot = vehicles_findgoodexit(spot);
+ }
self.owner.oldvelocity = self.owner.velocity;
- spot = self.origin - v_forward * 200 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
setorigin(self.owner , spot);
}
antilag_clear(self.owner);
self.owner = world;
}
+
void racer_impact()
{
if(autocvar_g_vehicle_racer_bouncepain_x)
setsize(self, RACER_MIN * 0.5, RACER_MAX * 0.5);
self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
- self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
+ self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
self.vehicle_impact = racer_impact;
//self.destvec = autocvar_g_vehicle_racer_bouncepain;
}
self.wait = time;
self.cnt = 1 + random() * 2;
self.touch = racer_deadtouch;
-
- pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
+
+ pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
if(random() < 0.5)
self.avelocity_z = 32;
precache_sound ("weapons/lasergun_fire.wav");
precache_sound ("weapons/rocket_fire.wav");
-
+
precache_sound ("vehicles/racer_idle.wav");
precache_sound ("vehicles/racer_move.wav");
precache_sound ("vehicles/racer_boost.wav");
self.vehicle_flags |= VHF_HEALTHREGEN;
self.think = racer_dinit;
-
+
if(g_assault)
self.nextthink = time + 0.5;
else
// End AuxiliaryXhair
/**
- Notifies the client that he enterd a vehicle, and sends
+ Notifies the client that he enterd a vehicle, and sends
realavent data.
-
+
only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT)
**/
void CSQCVehicleSetup(entity own, float vehicle_id)
.float lock_strength;
.float lock_time;
.float lock_soundtime;
+float DAMAGE_TARGETDRONE = 10;
+
+vector targetdrone_getnewspot()
+{
+
+ vector spot;
+ float i;
+ for(i = 0; i < 100; ++i)
+ {
+ spot = self.origin + randomvec() * 1024;
+ tracebox(spot, self.mins, self.maxs, spot, MOVE_NORMAL, self);
+ if(trace_fraction == 1.0 && trace_startsolid == 0 && trace_allsolid == 0)
+ return spot;
+ }
+ return self.origin;
+}
+void targetdrone_think();
+void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void targetdrone_renwe()
+{
+ self.think = targetdrone_think;
+ self.nextthink = time + 0.1;
+ setorigin(self, targetdrone_getnewspot());
+ self.health = 200;
+ self.takedamage = DAMAGE_TARGETDRONE;
+ self.event_damage = targetdrone_damage;
+ self.solid = SOLID_BBOX;
+ setmodel(self, "models/runematch/rune.mdl");
+ self.effects = EF_LOWPRECISION;
+ self.scale = 10;
+ self.movetype = MOVETYPE_BOUNCEMISSILE;
+ setsize(self, '-100 -100 -100', '100 100 100');
+
+}
+void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ self.health -= damage;
+ if(self.health <= 0)
+ {
+ pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
+
+ if(!self.cnt)
+ remove(self);
+ else
+ {
+ self.think = targetdrone_renwe;
+ self.nextthink = time + 1 + random() * 2;
+ self.solid = SOLID_NOT;
+ setmodel(self, "");
+ }
+ }
+}
+entity targetdrone_getfear()
+{
+ entity fear;
+ float i;
+
+ for(i = 64; i <= 1024; i += 64)
+ {
+ fear = findradius(self.origin, i);
+ while(fear)
+ {
+ if(fear.bot_dodge)
+ return fear;
+
+ fear = fear.chain;
+ }
+ }
+
+ return world;
+}
+void targetdrone_think()
+{
+ self.nextthink = time + 0.1;
+
+ if(self.enemy)
+ if(self.enemy.deadflag != DEAD_NO)
+ self.enemy = targetdrone_getfear();
+
+ if(!self.enemy)
+ self.enemy = targetdrone_getfear();
+
+ vector newdir;
+
+ if(self.enemy)
+ newdir = steerlib_push(self.enemy.origin) + randomvec() * 0.75;
+ else
+ newdir = randomvec() * 0.75;
+
+ newdir = newdir * 0.5 + normalize(self.velocity) * 0.5;
+
+ if(self.enemy)
+ self.velocity = normalize(newdir) * (500 + (1024 / min(vlen(self.enemy.origin - self.origin), 1024)) * 700);
+ else
+ self.velocity = normalize(newdir) * 750;
+
+ tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 2, MOVE_NORMAL, self);
+ if(trace_fraction != 1.0)
+ self.velocity = self.velocity * -1;
+
+ //normalize((normalize(self.velocity) * 0.5 + newdir * 0.5)) * 750;
+}
+
+void targetdrone_spawn(vector _where, float _autorenew)
+{
+ entity drone = spawn();
+ setorigin(drone, _where);
+ drone.think = targetdrone_renwe;
+ drone.nextthink = time + 0.1;
+ drone.cnt = _autorenew;
+}
+
void vehicles_locktarget(float incr, float decr, float _lock_time)
{
if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
self.lock_soundtime = time + 0.5;
play2(self.owner, "vehicles/locked.wav");
}
-
+
return;
}
if(trace_ent.deadflag != DEAD_NO)
trace_ent = world;
- if not (trace_ent.vehicle_flags & VHF_ISVEHICLE || trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+ if not (trace_ent.vehicle_flags & VHF_ISVEHICLE ||
+ trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET ||
+ trace_ent.takedamage == DAMAGE_TARGETDRONE)
trace_ent = world;
}
if(self.lock_target == world && trace_ent != world)
self.lock_target = trace_ent;
-
- if(self.lock_target && trace_ent == self.lock_target)
- {
+
+ if(self.lock_target && trace_ent == self.lock_target)
+ {
if(self.lock_strength != 1 && self.lock_strength + incr >= 1)
{
play2(self.owner, "vehicles/lock.wav");
self.lock_soundtime = time + 0.8;
- }
+ }
else if (self.lock_strength != 1 && self.lock_soundtime < time)
- {
+ {
play2(self.owner, "vehicles/locking.wav");
self.lock_soundtime = time + 0.3;
}
-
- }
-
+
+ }
+
// Have a locking target
// Trace hit current target
if(trace_ent == self.lock_target && trace_ent != world)
{
// Ignore damage from oterh projectiles from my owner (dont mess up volly's)
if(inflictor.owner == self.owner)
- return;
-
+ return;
+
self.health -= damage;
self.velocity += force;
if(self.health < 1)
}
void vehilces_impact(float _minspeed, float _speedfac, float _maxpain)
-{
+{
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
return;
-
+
if(self.play_time < time)
- {
+ {
float wc = vlen(self.velocity - self.oldvelocity);
//dprint("oldvel: ", vtos(self.oldvelocity), "\n");
//dprint("vel: ", vtos(self.velocity), "\n");
if(_minspeed < wc)
{
- float take = take = min(_speedfac * wc, _maxpain);
+ float take = min(_speedfac * wc, _maxpain);
Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0');
self.play_time = time + 0.25;
-
+
//dprint("wc: ", ftos(wc), "\n");
//dprint("take: ", ftos(take), "\n");
}
{
if(vlen(self.velocity) != 0)
Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
-
+
return; // Dont do selfdamage when hitting "soft targets".
}
-
+
if(self.play_time < time)
if(self.vehicle_impact)
self.vehicle_impact();
-
+
return;
}
if(self.team)
if(self.team != other.team)
return;
-
+
RemoveGrapplingHook(other);
self.vehicle_ammo1 = 0;
vehicles_clearrturn();
CSQCVehicleSetup(self.owner, self.hud);
-
+
if(other.flagcarried)
{
if(!autocvar_g_vehicles_allow_flagcarry)
DropFlag(other.flagcarried, world, world);
else
- {
+ {
other.flagcarried.scale = 1;
- setattachment(other.flagcarried, self, "");
+ setattachment(other.flagcarried, self, "");
setorigin(other, '0 0 96');
}
}
-
+
self.vehicle_enter();
antilag_clear(other);
}
{
//vector exitspot;
float mysize;
-
+
tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner);
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
return prefer_spot;
-
+
mysize = vlen(self.maxs - self.mins);
float i;
vector v, v2;
v2 = 0.5 * (self.absmin + self.absmax);
for(i = 0; i < 100; ++i)
- {
+ {
v = randomvec();
v_z = 0;
v = v2 + normalize(v) * mysize;
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
return v;
}
-
+
/*
exitspot = (self.origin + '0 0 48') + v_forward * mysize;
tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
return exitspot;
-
+
exitspot = (self.origin + '0 0 48') - v_forward * mysize;
tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
return exitspot;
-
+
exitspot = (self.origin + '0 0 48') - v_right * mysize;
tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
return exitspot;
*/
-
+
return self.origin;
}
custom code goes in self.vehicle_exit
**/
void vehicles_exit(float eject)
-{
+{
entity oldself;
if(self.flags & FL_CLIENT)
{
oldself = self;
self = self.vehicle;
}
-
+
self.flags |= FL_NOTARGET;
if (self.owner)
self.owner.hud = HUD_NORMAL;
self.owner.switchweapon = self.switchweapon;
//self.owner.BUTTON_USE = 0;
-
+
CSQCVehicleSetup(self.owner, HUD_NORMAL);
}
self.team = 0;
else
self.team = self.tur_head.team;
-
+
if(self.owner.flagcarried)
{
self.owner.flagcarried.scale = 0.6;
- setattachment(self.owner.flagcarried, self.owner, "");
+ setattachment(self.owner.flagcarried, self.owner, "");
setorigin(self.owner.flagcarried, FLAG_CARRY_POS);
}
-
+
sound (self, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTN_NORM);
self.vehicle_exit(eject);
self.owner = world;
vehicles_reset_colors();
-
+
if(oldself)
self = oldself;
}
}
void vehicles_painframe()
-{
+{
if(self.owner.vehicle_health <= 50)
if(self.pain_frame < time)
- {
- float _ftmp;
+ {
+ float _ftmp;
_ftmp = self.owner.vehicle_health / 50;
self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-
+
if(self.vehicle_flags & VHF_DMGSHAKE)
self.velocity += randomvec() * 30;
-
+
if(self.vehicle_flags & VHF_DMGROLL)
if(self.vehicle_flags & VHF_DMGHEADROLL)
self.tur_head.angles += randomvec();
else
self.angles += randomvec();
-
- }
+
+ }
}
void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
self.vehicle_shieldent.colormod = '2 0 0';
self.vehicle_shield = 0;
self.vehicle_shieldent.alpha = 0.75;
-
+
if(sound_allowed(MSG_BROADCAST, attacker))
spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM); // FIXME: PLACEHOLDER
}
{
ret.classname = "";
ret.think = SUB_Remove;
- ret.nextthink = time + 0.1;
-
+ ret.nextthink = time + 0.1;
+
if(ret.waypointsprite_attached)
WaypointSprite_Kill(ret.waypointsprite_attached);
-
+
return;
}
ret = ret.chain;
if(self.waypointsprite_attached)
WaypointSprite_Kill(self.waypointsprite_attached);
-
+
remove(self);
}
{
if(self.waypointsprite_attached)
WaypointSprite_Kill(self.waypointsprite_attached);
-
+
remove(self);
-
+
}
void vehicles_showwp()
{
entity oldself;
vector rgb;
-
+
if(self.cnt)
- {
+ {
self.think = vehicles_return;
self.nextthink = self.cnt;
- }
+ }
else
{
self.think = vehicles_return;
self.nextthink = time +1;
-
+
oldself = self;
self = spawn();
setmodel(self, "null");
self.team = oldself.enemy.team;
self.enemy = oldself.enemy;
setorigin(self, oldself.enemy.pos1);
-
+
self.nextthink = time + 5;
self.think = vehicles_showwp_goaway;
}
-
+
if(teamplay && self.team)
rgb = TeamColor(self.team);
else
rgb = '1 1 1';
WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
if(self.waypointsprite_attached)
- {
- WaypointSprite_UpdateRule(self.waypointsprite_attached, self.enemy.team, SPRITERULE_DEFAULT);
+ {
+ WaypointSprite_UpdateRule(self.waypointsprite_attached, self.enemy.team, SPRITERULE_DEFAULT);
if(oldself == world)
- WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
+ WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
WaypointSprite_Ping(self.waypointsprite_attached);
- }
-
+ }
+
if(oldself != world)
self = oldself;
}
void vehicles_setreturn()
{
entity ret;
-
+
vehicles_clearrturn();
ret = spawn();
ret.classname = "vehicle_return";
- ret.enemy = self;
+ ret.enemy = self;
ret.team = self.team;
ret.think = vehicles_showwp;
-
+
if(self.deadflag != DEAD_NO)
{
ret.cnt = time + self.vehicle_respawntime;
- ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5);
- }
+ ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5);
+ }
else
{
- ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1);
+ ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1);
}
-
+
setmodel(ret, "null");
setorigin(ret, self.pos1 + '0 0 96');
-
+
}
void vehicles_configcheck(string configname, float check_cvar)
if(self.team && !teamplay)
self.team = 0;
-
+
self.vehicle_flags |= VHF_ISVEHICLE;
-
+
setmodel(self, bodymodel);
self.vehicle_viewport = spawn();
self.PlayerPhysplug = physproc;
self.event_damage = vehicles_damage;
self.touch = vehicles_touch;
- self.think = vehicles_spawn;
- self.nextthink = time;
+ self.think = vehicles_spawn;
+ self.nextthink = time;
self.vehicle_respawntime = _respawntime;
self.vehicle_spawn = spawnproc;
self.pos1 = self.origin;
self.pos2 = self.angles;
self.tur_head.team = self.team;
-
+
return TRUE;
}
UpdateCSQCProjectile(self);
}
-float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
+float W_BallisticBullet_LeaveSolid(float eff)
{
// move the entity along its velocity until it's out of solid, then let it resume
-
+ vector vel = self.velocity;
float dt, dst, velfactor, v0, vs;
float maxdist;
float E0_m, Es_m;
+ float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1);
// outside the world? forget it
if(self.origin_x > world.maxs_x || self.origin_y > world.maxs_y || self.origin_z > world.maxs_z || self.origin_x < world.mins_x || self.origin_y < world.mins_y || self.origin_z < world.mins_z)
return 0;
+ // special case for zero density and zero bullet constant:
+
+ if(self.dmg_radius == 0)
+ {
+ if(other.ballistics_density < 0)
+ constant = 0; // infinite travel distance
+ else
+ return 0; // no penetration
+ }
+ else
+ {
+ if(other.ballistics_density < 0)
+ constant = 0; // infinite travel distance
+ else if(other.ballistics_density == 0)
+ constant = self.dmg_radius;
+ else
+ constant = self.dmg_radius * other.ballistics_density;
+ }
+
// E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
v0 = vlen(vel);
E0_m = 0.5 * v0 * v0;
- maxdist = E0_m / constant;
- // maxdist = 0.5 * v0 * v0 / constant
- // dprint("max dist = ", ftos(maxdist), "\n");
- if(maxdist <= autocvar_g_ballistics_mindistance)
- return 0;
+ if(constant)
+ {
+ maxdist = E0_m / constant;
+ // maxdist = 0.5 * v0 * v0 / constant
+ // dprint("max dist = ", ftos(maxdist), "\n");
- traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self);
+ if(maxdist <= autocvar_g_ballistics_mindistance)
+ return 0;
+ }
+ else
+ {
+ maxdist = vlen(other.maxs - other.mins) + 1; // any distance, as long as we leave the entity
+ }
+ traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self, TRUE);
if(trace_fraction == 1) // 1: we never got out of solid
return 0;
self.flags |= FL_ONGROUND; // prevent moving
self.W_BallisticBullet_LeaveSolid_velocity = vel;
+ if(eff >= 0)
+ if(vlen(trace_endpos - self.origin) > 4)
+ {
+ endzcurveparticles();
+ trailparticles(self, eff, self.origin, trace_endpos);
+ }
+
return 1;
}
PROJECTILE_TOUCH;
W_BallisticBullet_Hit ();
+ if(self.dmg_radius < 0) // these NEVER penetrate solid
+ {
+ remove(self);
+ return;
+ }
+
// if we hit "weapclip", bail out
//
// rationale of this check:
return;
}
- density = other.ballistics_density;
- if(density == 0)
- density = 1;
-
// go through solid!
- if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+ if(!W_BallisticBullet_LeaveSolid(-1))
{
remove(self);
return;
proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed);
W_SetupProjectileVelocityEx(proj, dir, v_up, pSpeed, 0, 0, spread, antilagging);
proj.angles = vectoangles(proj.velocity);
- proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+ if(bulletconstant > 0)
+ proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+ else if(bulletconstant == 0)
+ proj.dmg_radius = 0;
+ else
+ proj.dmg_radius = -1;
// so: bulletconstant = bullet mass / area of bullet circle
setorigin(proj, start);
proj.flags = FL_PROJECTILE;
W_BallisticBullet_Hit();
}
+ if(proj.dmg_radius < 0) // these NEVER penetrate solid
+ break;
+
// if we hit "weapclip", bail out
//
// rationale of this check:
if not(trace_dphitcontents & DPCONTENTS_OPAQUE)
break;
- density = other.ballistics_density;
- if(density == 0)
- density = 1;
-
// go through solid!
- if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+ if(!W_BallisticBullet_LeaveSolid((other && (other.solid != SOLID_BSP)) ? eff : -1))
break;
W_BallisticBullet_LeaveSolid_think();
+
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
}
frametime = savetime;
self = oldself;
self.takedamage = DAMAGE_NO;
self.event_damage = SUB_Null;
- if not(g_ca)
+ if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner)
{
self.owner = attacker;
self.realowner = attacker;
ClientData_Touch(self);
}
}
- v_angle_save = self.v_angle;
if(self.porto_v_angle_held)
makevectors(self.porto_v_angle); // override the previously set angles
set g_vehicle_racer_health_regen 0
set g_vehicle_racer_health_regen_pause 0
-set g_vehicle_racer_shield 75
-set g_vehicle_racer_shield_regen 25
+set g_vehicle_racer_shield 70
+set g_vehicle_racer_shield_regen 30
set g_vehicle_racer_shield_regen_pause 1
-set g_vehicle_racer_energy 125
+set g_vehicle_racer_energy 100
set g_vehicle_racer_energy_regen 40
set g_vehicle_racer_energy_regen_pause 1
-set g_vehicle_racer_speed_stop 2000
-set g_vehicle_racer_speed_forward 800
+set g_vehicle_racer_speed_stop 2500
+set g_vehicle_racer_speed_forward 500
set g_vehicle_racer_speed_strafe 500
-set g_vehicle_racer_speed_afterburn 2000
-set g_vehicle_racer_friction 0.4
-set g_vehicle_racer_afterburn_cost 60 // energy consumed per second
+set g_vehicle_racer_speed_afterburn 3000
+set g_vehicle_racer_friction 0.3
+set g_vehicle_racer_afterburn_cost 50 // energy consumed per second
set g_vehicle_racer_hovertype 0 // 0 = hover, != 0 = maglev
-set g_vehicle_racer_hoverpower 5000 // NOTE!! x 4 (4 engines)
+set g_vehicle_racer_hoverpower 7500 // NOTE!! x 4 (4 engines)
set g_vehicle_racer_upforcedamper 10
set g_vehicle_racer_downforce 0.01
-set g_vehicle_racer_springlength 65
+set g_vehicle_racer_springlength 70
set g_vehicle_racer_collision_multiplier 0.05
set g_vehicle_racer_anglestabilizer 1.75
set g_vehicle_racer_turnspeed 200
set g_vehicle_racer_pitchspeed 100
-set g_vehicle_racer_maxpitch 25
-set g_vehicle_racer_turnroll 32
+set g_vehicle_racer_maxpitch 20
+set g_vehicle_racer_turnroll 16
set g_vehicle_racer_cannon_speed 9000
-set g_vehicle_racer_cannon_damage 20
+set g_vehicle_racer_cannon_damage 25
set g_vehicle_racer_cannon_radius 100
set g_vehicle_racer_cannon_refire 0.1
-set g_vehicle_racer_cannon_cost 4
+set g_vehicle_racer_cannon_cost 10
set g_vehicle_racer_cannon_spread 0.0125
set g_vehicle_racer_cannon_force 50
set g_vehicle_racer_rocket_speed 1000
set g_vehicle_racer_rocket_accel 1400
-set g_vehicle_racer_rocket_turnrate 0.17
-set g_vehicle_racer_rocket_damage 160
+set g_vehicle_racer_rocket_turnrate 0.1
+set g_vehicle_racer_rocket_damage 165
set g_vehicle_racer_rocket_force 350
set g_vehicle_racer_rocket_radius 125
set g_vehicle_racer_rocket_refire 6
set g_vehicle_racer_rocket_cost 0
+set g_vehicle_racer_rocket_climbspeed 1750
set g_vehicle_racer_rocket_locktarget 1
set g_vehicle_racer_rocket_locking_time 0.4
-set g_vehicle_racer_rocket_locking_releasetime 1.6
+set g_vehicle_racer_rocket_locking_releasetime 1.5
set g_vehicle_racer_rocket_locked_time 5
-set g_vehicle_racer_rocket_locked_maxangle 1.46
+set g_vehicle_racer_rocket_locked_maxangle 1.75
set g_vehicle_racer_blowup_radius 250
set g_vehicle_racer_blowup_coredamage 250
set g_vehicle_racer_bouncefactor 0.25 // Factor of old velocity to keep after colission
set g_vehicle_racer_bouncestop 0 // if != 0, New veloctiy after bounce = 0 if new velocity < this
-set g_vehicle_racer_bouncepain "35 2 250" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
+set g_vehicle_racer_bouncepain "60 0.75 300" // "minspeed_for_pain speedchange_to_pain_factor max_damage"
set g_vehicle_racer_mass 900