// 0: absolute velocity projectiles (like Quake)
// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
set g_projectiles_newton_style_2_minfactor 0.7
set g_projectiles_newton_style_2_maxfactor 5
set g_projectiles_spread_style 0
// 0: absolute velocity projectiles (like Quake)
// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
set g_projectiles_newton_style_2_minfactor 0.7
set g_projectiles_newton_style_2_maxfactor 5
set g_projectiles_spread_style 7
// 0: absolute velocity projectiles (like Quake)
// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
set g_projectiles_newton_style_2_minfactor 0.8
set g_projectiles_newton_style_2_maxfactor 1.5
set g_projectiles_spread_style 7
// 0: absolute velocity projectiles (like Quake)
// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
set g_projectiles_newton_style_2_minfactor 0.8
set g_projectiles_newton_style_2_maxfactor 1.5
set g_projectiles_spread_style 7
cl_decals 1
-cl_decals_models 1
+cl_decals_models 0
cl_decals_time 10
cl_particles_quality 1
cl_damageeffect 1
PERL ?= perl
FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"' -DCVAR_POPCON
-FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-return_only -Ono-assignments -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
+FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-return_only -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
FTEQCCFLAGS_PROGS ?=
FTEQCCFLAGS_MENU ?=
{
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)
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"))
// 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;
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)
{
void error(...) = #1;
+float id(float x) { return x; }
void Oassignments(float foo) // pass 1
{
{
error("FTEQCC SUCKS");
}
+
+.float fld;
+void Ono_assignments(entity e, float wep) // pass an e with e.fld == 1, and wep == 3. e.fld will be 2 instead of 3. Observe the INDIRECT and the SUB use the same field for storage, wreaking havoc.
+{
+ ((e).fld |= id(wep - 1));
+}
other.parent = me;
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
other.parent = NULL;
- entity n, p, f, l;
- f = me.firstChild;
- l = me.lastChild;
+ entity n, p;
n = other.nextSibling;
p = other.prevSibling;
other.parent = me;
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
other.Container_size = theSize;
me.setAlphaOf(me, other, theAlpha);
- entity f, l;
- f = me.firstChild;
+ entity l;
l = me.lastChild;
if(l)
other.parent = NULL;
- entity n, p, f, l;
- f = me.firstChild;
- l = me.lastChild;
+ entity n, p;
n = other.nextSibling;
p = other.prevSibling;
void Container_moveItemAfter(entity me, entity other, entity dest)
{
// first: remove other from the chain
- entity n, p, f, l;
+ entity n, p;
if(other.parent != me)
error("Can't move in wrong container!");
- f = me.firstChild;
- l = me.lastChild;
n = other.nextSibling;
p = other.prevSibling;
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;
}
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.angles = '0 0 0';
float f;
- f = 0;
if (self.state == WS_RAISE && !intermission_running)
{
f = (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay;
{
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 if(nstyle == 3)
- {
- // pseudo-Newtonian:
- outspeed = mspeed + mdirection * pvelocity;
- outspeed = bound(mspeed * 0.7, outspeed, mspeed * 5.0);
- outvelocity = mdirection * outspeed;
- }
- else if(nstyle == 4)
- {
- // tZorkian:
- outspeed = mspeed + vlen(pvelocity);
- outvelocity = mdirection * outspeed;
- }
- else
- error("g_projectiles_newton_style must be 0 (absolute), 1 (Newtonian), 2 (Newtonian + aimfix), 3 (pseudo Newtonian) or 4 (tZorkian)!");
+ 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
else
e.gravity = 0;
- e.csqcprojectile_type = type;
if(!sound_allowed(MSG_BROADCAST, e))
type |= 0x80;
+ e.csqcprojectile_type = type;
}
void UpdateCSQCProjectile(entity e)
// 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;
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.");
}
.float siren_time; // time delay the siren
//.float stuff_time; // time delay to stuffcmd a cvar
-float test[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-//test[0] = status of dropped keys, test[1 - 16] = player #
+float kh_keystatus[17];
+//kh_keystatus[0] = status of dropped keys, kh_keystatus[1 - 16] = player #
//replace 17 with cvar("maxplayers") or similar !!!!!!!!!
//for(i = 0; i < maxplayers; ++i)
-// test[i] = "0";
+// kh_keystatus[i] = "0";
float kh_Team_ByID(float t)
{
key.kh_next.kh_prev = key;
float i;
- i = test[key.owner.playerid];
+ i = kh_keystatus[key.owner.playerid];
if(key.netname == "^1red key")
i += 1;
if(key.netname == "^4blue key")
i += 4;
if(key.netname == "^6pink key")
i += 8;
- test[key.owner.playerid] = i;
+ kh_keystatus[key.owner.playerid] = i;
kh_Key_Attach(key);
{
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
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");
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