seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point"
seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster"
+seta hud_panel_physics_acceleration_movingaverage 1 "use an averaging method for calculating acceleration instead of the real value"
+seta hud_panel_phisics_update_interval 0.0666 "how often (in seconds) numeric values get updated on screen"
+
// hud panel aliases
alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
alias +hud_panel_radar_maximized "cl_cmd hud radar 1"
alias mobedit "qc_cmd_cmd mobedit ${* ?}" // Edit a monster's properties
alias mobkill "qc_cmd_cmd mobkill ${* ?}" // Kill a monster
alias mobspawn "qc_cmd_cmd mobspawn ${* ?}" // Spawn a monster infront of the player
+alias physics "qc_cmd_cmd physics ${* ?}" // Change physics set
alias spectate "qc_cmd_cmd spectate ${* ?}" // Become an observer
alias suggestmap "qc_cmd_cmd suggestmap ${* ?}" // Suggest a map to the mapvote at match end
//alias tell "qc_cmd_cmd tell ${* ?}" // Send a message directly to a player
exec mutators.cfg
exec notifications.cfg
exec monsters.cfg
+exec physics.cfg
// load console command aliases and settings
exec commands.cfg
// =====================
// gametype vote hooks
// =====================
-// these are called when the mode is switched via gametype vote screen, earlier than gamestart hooks (useful for enabling per-gamemode mutators)
-alias sv_vote_gametype_hook_all
+// These are called when the mode is switched via gametype vote screen,
+// earlier than gamestart hooks (useful for enabling per-gamemode mutators)
+// The _all hook is called before the specific one
+// here it sets g_maxplayers to undo what duel does
+alias sv_vote_gametype_hook_all "set g_maxplayers 0"
alias sv_vote_gametype_hook_as
alias sv_vote_gametype_hook_ca
alias sv_vote_gametype_hook_ctf
alias sv_vote_gametype_hook_rc
alias sv_vote_gametype_hook_tdm
+// Preset to allow duel to be used for the gametype voting screen
+// sv_vote_gametype_*_type Must be set to the name of the gametype the option is based on
+// sv_vote_gametype_*_name Contains a human-readable name of the gametype
+// sv_vote_gametype_*_description Contains a longer description
+set sv_vote_gametype_duel_type dm
+set sv_vote_gametype_duel_name Duel
+set sv_vote_gametype_duel_description "One vs One match"
+alias sv_vote_gametype_hook_duel "set g_maxplayers 2"
+
// ===========
// leadlimit
--- /dev/null
+// ==================================================
+// Main configuration for client selectable physics
+// ==================================================
+
+
+// ==============
+// Main options
+// ==============
+seta cl_physics "default" "client selected physics set"
+
+set g_physics_clientselect 0 "allow clients to select their physics set"
+set g_physics_clientselect_options "xonotic nexuiz quake warsow defrag quake3 vecxis quake2 bones"
+set g_physics_clientselect_default "" "override default physics"
+
+// =========
+// Xonotic
+// =========
+set g_physics_xonotic_airaccel_qw -0.8
+set g_physics_xonotic_airstrafeaccel_qw -0.95
+set g_physics_xonotic_airspeedlimit_nonqw 900
+set g_physics_xonotic_maxspeed 360
+set g_physics_xonotic_jumpvelocity 260
+set g_physics_xonotic_maxairstrafespeed 100
+set g_physics_xonotic_maxairspeed 360
+set g_physics_xonotic_airstrafeaccelerate 18
+set g_physics_xonotic_warsowbunny_turnaccel 0
+set g_physics_xonotic_airaccel_qw_stretchfactor 2
+set g_physics_xonotic_airaccel_sideways_friction 0
+set g_physics_xonotic_aircontrol 100
+set g_physics_xonotic_aircontrol_power 2
+set g_physics_xonotic_aircontrol_penalty 0
+set g_physics_xonotic_warsowbunny_airforwardaccel 1.00001
+set g_physics_xonotic_warsowbunny_topspeed 925
+set g_physics_xonotic_warsowbunny_accel 0.1593
+set g_physics_xonotic_warsowbunny_backtosideratio 0.8
+set g_physics_xonotic_friction 6
+set g_physics_xonotic_accelerate 15
+set g_physics_xonotic_stopspeed 100
+set g_physics_xonotic_airaccelerate 2
+set g_physics_xonotic_airstopaccelerate 3
+
+// ========
+// Nexuiz
+// ========
+set g_physics_nexuiz_airaccel_qw 0.95
+set g_physics_nexuiz_airstrafeaccel_qw 0
+set g_physics_nexuiz_airspeedlimit_nonqw 0
+set g_physics_nexuiz_maxspeed 400
+set g_physics_nexuiz_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_nexuiz_maxairstrafespeed 0
+set g_physics_nexuiz_maxairspeed 220
+set g_physics_nexuiz_airstrafeaccelerate 0
+set g_physics_nexuiz_warsowbunny_turnaccel 0
+set g_physics_nexuiz_airaccel_qw_stretchfactor 0
+set g_physics_nexuiz_airaccel_sideways_friction 0.35
+set g_physics_nexuiz_aircontrol 0
+set g_physics_nexuiz_aircontrol_power 2
+set g_physics_nexuiz_aircontrol_penalty 0
+set g_physics_nexuiz_warsowbunny_airforwardaccel 1.00001
+set g_physics_nexuiz_warsowbunny_topspeed 925
+set g_physics_nexuiz_warsowbunny_accel 0.1593
+set g_physics_nexuiz_warsowbunny_backtosideratio 0.8
+set g_physics_nexuiz_friction 7
+set g_physics_nexuiz_accelerate 8
+set g_physics_nexuiz_stopspeed 100
+set g_physics_nexuiz_airaccelerate 5.5
+set g_physics_nexuiz_airstopaccelerate 0
+
+// =======
+// Quake
+// =======
+set g_physics_quake_airaccel_qw 1
+set g_physics_quake_airstrafeaccel_qw 0
+set g_physics_quake_airspeedlimit_nonqw 0
+set g_physics_quake_maxspeed 320
+set g_physics_quake_jumpvelocity 270
+set g_physics_quake_maxairstrafespeed 0
+set g_physics_quake_maxairspeed 30
+set g_physics_quake_airstrafeaccelerate 0
+set g_physics_quake_warsowbunny_turnaccel 0
+set g_physics_quake_airaccel_qw_stretchfactor 0
+set g_physics_quake_airaccel_sideways_friction 0
+set g_physics_quake_aircontrol 0
+set g_physics_quake_aircontrol_power 2
+set g_physics_quake_aircontrol_penalty 0
+set g_physics_quake_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake_warsowbunny_topspeed 925
+set g_physics_quake_warsowbunny_accel 0.1593
+set g_physics_quake_warsowbunny_backtosideratio 0.8
+set g_physics_quake_friction 4
+set g_physics_quake_accelerate 10
+set g_physics_quake_stopspeed 100
+set g_physics_quake_airaccelerate 106.66666666666666666666
+set g_physics_quake_airstopaccelerate 0
+
+// ========
+// Warsow
+// ========
+set g_physics_warsow_airaccel_qw 1
+set g_physics_warsow_airstrafeaccel_qw 0
+set g_physics_warsow_airspeedlimit_nonqw 0
+set g_physics_warsow_maxspeed 320
+set g_physics_warsow_jumpvelocity 280
+set g_physics_warsow_maxairstrafespeed 30
+set g_physics_warsow_maxairspeed 320
+set g_physics_warsow_airstrafeaccelerate 70
+set g_physics_warsow_warsowbunny_turnaccel 9
+set g_physics_warsow_airaccel_qw_stretchfactor 0
+set g_physics_warsow_airaccel_sideways_friction 0
+set g_physics_warsow_aircontrol 0
+set g_physics_warsow_aircontrol_power 2
+set g_physics_warsow_aircontrol_penalty 0
+set g_physics_warsow_warsowbunny_airforwardaccel 1.00001
+set g_physics_warsow_warsowbunny_topspeed 925
+set g_physics_warsow_warsowbunny_accel 0.1593
+set g_physics_warsow_warsowbunny_backtosideratio 0.8
+set g_physics_warsow_friction 8
+set g_physics_warsow_accelerate 15
+set g_physics_warsow_stopspeed 100
+set g_physics_warsow_airaccelerate 1
+set g_physics_warsow_airstopaccelerate 2.5
+
+// ========
+// DeFrag
+// ========
+set g_physics_defrag_airaccel_qw 0.95
+set g_physics_defrag_airstrafeaccel_qw 1
+set g_physics_defrag_airspeedlimit_nonqw 0
+set g_physics_defrag_maxspeed 320
+set g_physics_defrag_jumpvelocity 270
+set g_physics_defrag_maxairstrafespeed 30
+set g_physics_defrag_maxairspeed 320
+set g_physics_defrag_airstrafeaccelerate 70
+set g_physics_defrag_warsowbunny_turnaccel 0
+set g_physics_defrag_airaccel_qw_stretchfactor 0
+set g_physics_defrag_airaccel_sideways_friction 0
+set g_physics_defrag_aircontrol 150
+set g_physics_defrag_aircontrol_power 2
+set g_physics_defrag_aircontrol_penalty 0
+set g_physics_defrag_warsowbunny_airforwardaccel 1.00001
+set g_physics_defrag_warsowbunny_topspeed 925
+set g_physics_defrag_warsowbunny_accel 0.1593
+set g_physics_defrag_warsowbunny_backtosideratio 0.8
+set g_physics_defrag_friction 5.8
+set g_physics_defrag_accelerate 15
+set g_physics_defrag_stopspeed 100
+set g_physics_defrag_airaccelerate 1
+set g_physics_defrag_airstopaccelerate 2.5
+
+// =========
+// Quake 3
+// =========
+set g_physics_quake3_airaccel_qw 1
+set g_physics_quake3_airstrafeaccel_qw 0
+set g_physics_quake3_airspeedlimit_nonqw 0
+set g_physics_quake3_maxspeed 320
+set g_physics_quake3_jumpvelocity 270
+set g_physics_quake3_maxairstrafespeed 0
+set g_physics_quake3_maxairspeed 320
+set g_physics_quake3_airstrafeaccelerate 0
+set g_physics_quake3_warsowbunny_turnaccel 0
+set g_physics_quake3_airaccel_qw_stretchfactor 0
+set g_physics_quake3_airaccel_sideways_friction 0
+set g_physics_quake3_aircontrol 0
+set g_physics_quake3_aircontrol_power 2
+set g_physics_quake3_aircontrol_penalty 0
+set g_physics_quake3_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake3_warsowbunny_topspeed 925
+set g_physics_quake3_warsowbunny_accel 0.1593
+set g_physics_quake3_warsowbunny_backtosideratio 0.8
+set g_physics_quake3_friction 6
+set g_physics_quake3_accelerate 10
+set g_physics_quake3_stopspeed 100
+set g_physics_quake3_airaccelerate 1
+set g_physics_quake3_airstopaccelerate 0
+
+// ========
+// Vecxis
+// ========
+set g_physics_vecxis_airaccel_qw 0.93
+set g_physics_vecxis_airstrafeaccel_qw 0
+set g_physics_vecxis_airspeedlimit_nonqw 0
+set g_physics_vecxis_maxspeed 400
+set g_physics_vecxis_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_vecxis_maxairstrafespeed 0
+set g_physics_vecxis_maxairspeed 220
+set g_physics_vecxis_airstrafeaccelerate 0
+set g_physics_vecxis_warsowbunny_turnaccel 0
+set g_physics_vecxis_airaccel_qw_stretchfactor 0
+set g_physics_vecxis_airaccel_sideways_friction 0.3
+set g_physics_vecxis_aircontrol 0
+set g_physics_vecxis_aircontrol_power 2
+set g_physics_vecxis_aircontrol_penalty 0
+set g_physics_vecxis_warsowbunny_airforwardaccel 1.00001
+set g_physics_vecxis_warsowbunny_topspeed 925
+set g_physics_vecxis_warsowbunny_accel 0.1593
+set g_physics_vecxis_warsowbunny_backtosideratio 0.8
+set g_physics_vecxis_friction 5
+set g_physics_vecxis_accelerate 5.5
+set g_physics_vecxis_stopspeed 100
+set g_physics_vecxis_airaccelerate 5.5
+set g_physics_vecxis_airstopaccelerate 0
+
+// =========
+// Quake 2
+// =========
+set g_physics_quake2_airaccel_qw 1
+set g_physics_quake2_airstrafeaccel_qw 0
+set g_physics_quake2_airspeedlimit_nonqw 0
+set g_physics_quake2_maxspeed 300
+set g_physics_quake2_jumpvelocity 270
+set g_physics_quake2_maxairstrafespeed 0
+set g_physics_quake2_maxairspeed 300
+set g_physics_quake2_airstrafeaccelerate 0
+set g_physics_quake2_warsowbunny_turnaccel 0
+set g_physics_quake2_airaccel_qw_stretchfactor 0
+set g_physics_quake2_airaccel_sideways_friction 0
+set g_physics_quake2_aircontrol 0
+set g_physics_quake2_aircontrol_power 2
+set g_physics_quake2_aircontrol_penalty 0
+set g_physics_quake2_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake2_warsowbunny_topspeed 925
+set g_physics_quake2_warsowbunny_accel 0.1593
+set g_physics_quake2_warsowbunny_backtosideratio 0.8
+set g_physics_quake2_friction 6
+set g_physics_quake2_accelerate 10
+set g_physics_quake2_stopspeed 100
+set g_physics_quake2_airaccelerate 1
+set g_physics_quake2_airstopaccelerate 0
+
+// =======
+// Bones
+// =======
+set g_physics_bones_airaccel_qw 1
+set g_physics_bones_airstrafeaccel_qw 1
+set g_physics_bones_airspeedlimit_nonqw 0
+set g_physics_bones_maxspeed 320
+set g_physics_bones_jumpvelocity 270
+set g_physics_bones_maxairstrafespeed 30
+set g_physics_bones_maxairspeed 320
+set g_physics_bones_airstrafeaccelerate 70
+set g_physics_bones_warsowbunny_turnaccel 0
+set g_physics_bones_airaccel_qw_stretchfactor 0
+set g_physics_bones_airaccel_sideways_friction 0
+set g_physics_bones_aircontrol 150
+set g_physics_bones_aircontrol_power 2
+set g_physics_bones_aircontrol_penalty 0
+set g_physics_bones_warsowbunny_airforwardaccel 1.00001
+set g_physics_bones_warsowbunny_topspeed 925
+set g_physics_bones_warsowbunny_accel 0.1593
+set g_physics_bones_warsowbunny_backtosideratio 0.8
+set g_physics_bones_friction 5.97
+set g_physics_bones_accelerate 15
+set g_physics_bones_stopspeed 100
+set g_physics_bones_airaccelerate 1
+set g_physics_bones_airstopaccelerate 2.5
float autocvar_hud_panel_notify_time;
float autocvar_hud_panel_notify_icon_aspect;
bool autocvar_hud_panel_physics;
+float autocvar_hud_panel_physics_acceleration_movingaverage = 1;
float autocvar_hud_panel_physics_acceleration_progressbar_mode;
float autocvar_hud_panel_physics_acceleration_progressbar_scale;
float autocvar_hud_panel_physics_acceleration_progressbar_nonlinear;
float autocvar_hud_panel_physics_acceleration_max;
+float autocvar_hud_panel_physics_update_interval;
int autocvar_hud_panel_physics_progressbar;
bool autocvar_hud_panel_physics_acceleration_vertical;
int autocvar_hud_panel_physics_baralign;
//
vector acc_prevspeed;
float acc_prevtime, acc_avg, top_speed, top_speed_time;
+float physics_update_time, discrete_speed, discrete_acceleration;
void HUD_Physics(void)
{
if(!autocvar__hud_configure)
acc_prevspeed = vel;
acc_prevtime = time;
- f = bound(0, f * 10, 1);
- acc_avg = acc_avg * (1 - f) + acceleration * f;
+ if(autocvar_hud_panel_physics_acceleration_movingaverage)
+ {
+ f = bound(0, f * 10, 1);
+ acc_avg = acc_avg * (1 - f) + acceleration * f;
+ acceleration = acc_avg;
+ }
+ }
+
+ int acc_decimals = 2;
+ if(time > physics_update_time)
+ {
+ // workaround for ftos_decimals returning a negative 0
+ if(discrete_acceleration > -1 / pow(10, acc_decimals) && discrete_acceleration < 0)
+ discrete_acceleration = 0;
+ discrete_acceleration = acceleration;
+ discrete_speed = speed;
+ physics_update_time += autocvar_hud_panel_physics_update_interval;
}
//compute layout
//else
//tmp_offset_x = 0;
tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
- drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(discrete_speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
//draw speed unit
if (speed_baralign)
f = acceleration/autocvar_hud_panel_physics_acceleration_max;
if (autocvar_hud_panel_physics_acceleration_progressbar_nonlinear)
- f = sqrt(f);
+ f = (f >= 0 ? sqrt(f) : -sqrt(-f));
if (acceleration_progressbar_scale) // allow progressbar to go out of panel bounds
{
HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset + tmp_offset, tmp_size, "accelbar", f, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
- tmp_size.x = panel_size.x;
- tmp_size.y = panel_size.y * text_scale;
- tmp_offset.x = 0;
- tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
- if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
- drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(acceleration, 2), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ if(autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
+ {
+ tmp_size.x = panel_size.x;
+ tmp_size.y = panel_size.y * text_scale;
+ tmp_offset.x = 0;
+ tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
+
+ drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(discrete_acceleration, acc_decimals), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
draw_endBoldFont();
}
#include "../dpdefs/keycodes.qh"
+
+int mv_num_maps;
+
+float mv_active;
+string mv_maps[MAPVOTE_COUNT];
+string mv_pics[MAPVOTE_COUNT];
+string mv_pk3[MAPVOTE_COUNT]; // map pk3 name or gametype human readable name
+string mv_desc[MAPVOTE_COUNT];
+float mv_preview[MAPVOTE_COUNT];
+float mv_votes[MAPVOTE_COUNT];
+float mv_flags[MAPVOTE_COUNT];
+float mv_flags_start[MAPVOTE_COUNT];
+entity mv_pk3list;
+float mv_abstain;
+float mv_ownvote;
+float mv_detail;
+float mv_timeout;
+float mv_top2_time;
+float mv_top2_alpha;
+
+vector mv_mousepos;
+int mv_selection;
+int mv_columns;
+int mv_mouse_selection;
+int mv_selection_keyboard;
+
+float gametypevote;
+string mapvote_chosenmap;
+vector gtv_text_size;
+vector gtv_text_size_small;
+
+const int NUM_SSDIRS = 4;
+string ssdirs[NUM_SSDIRS];
+int n_ssdirs;
+
string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
{
string pre, post;
{
if(_count == 1)
post = _(" (1 vote)");
- else if(_count >= 0 && mv_avail[id] == GTV_AVAILABLE)
+ else if(_count >= 0 && (mv_flags[id] & GTV_AVAILABLE))
post = sprintf(_(" (%d votes)"), _count);
else
post = "";
return strcat(pre, map, post);
}
-string GameTypeVote_DescriptionByID(int id)
-{
- return MapInfo_Type_Description(MapInfo_Type_FromString(mv_maps[id]));
-}
-
vector MapVote_RGB(int id)
{
- if(mv_avail[id] != GTV_AVAILABLE)
+ if(!(mv_flags[id] & GTV_AVAILABLE))
return '1 1 1';
if(id == mv_ownvote)
return '0 1 0';
void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
{
+ // Find the correct alpha
float alpha;
- float desc_padding = gtv_text_size.x * 3;
+ if(!(mv_flags_start[id] & GTV_AVAILABLE))
+ alpha = 0.2; // The gametype isn't supported by the map
+ else if ( !(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
+ alpha = mv_top2_alpha; // Fade away if not one of the top 2 choice
+ else
+ alpha = 1; // Normal, full alpha
+
+ // Bounding box details
float rect_margin = hud_fontsize.y / 2;
vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
vector rect_size = '1 1 0';
rect_size.x = tsize + rect_margin;
rect_size.y = maxh + rect_margin;
- vector rgb = MapVote_RGB(id);
- vector offset = pos;
- float nlines = 0;
-
- if(mv_avail_start[id] != GTV_AVAILABLE)
- alpha = 0.2;
- else if ( mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
- alpha = mv_top2_alpha;
- else
- alpha = 1;
- if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+ // Highlight selected item
+ if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
{
drawfill(rect_pos, rect_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
}
+
+ // Highlight current vote
+ vector rgb = MapVote_RGB(id);
if(id == mv_ownvote)
{
drawfill(rect_pos, rect_size, rgb, 0.1*alpha, DRAWFLAG_NORMAL);
drawborderlines(autocvar_scoreboard_border_thickness, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
}
- entity title;
- title = spawn();
- title.message = MapVote_FormatMapItem(id, MapInfo_Type_ToText(MapInfo_Type_FromString(gtype)),
- _count, tsize, gtv_text_size);
- title.origin = pos-offset;
-
- pos.y += gtv_text_size_small.y;
- pos.y += gtv_text_size.y/2;
+ vector offset = pos;
- maxh -= gtv_text_size.y;
+ float title_gap = gtv_text_size.y * 1.4; // distance between the title and the description
+ pos.y += title_gap;
+ maxh -= title_gap;
- entity picent = spawn();
- picent.origin = pos-offset;
- picent.maxs = '1 1 0 ' * min(maxh, desc_padding) * 0.8;
+ // Evaluate the image size
+ vector image_size = '1 1 0' * gtv_text_size.x * 3;
+ if ( maxh < image_size.y )
+ image_size = '1 1 0' * maxh;
+ image_size *= 0.8;
+ float desc_padding = gtv_text_size.x * 0.6;
+ pos.x += image_size.x + desc_padding;
+ tsize -= image_size.x + desc_padding;
- pos.x += desc_padding;
- tsize -= desc_padding;
+ // Split the description into lines
+ entity title;
+ title = spawn();
+ title.message = MapVote_FormatMapItem(id, mv_pk3[id], _count, tsize, gtv_text_size);
- string thelabel = GameTypeVote_DescriptionByID(id), ts;
+ string thelabel = mv_desc[id], ts;
entity last = title;
entity next = world;
+ float nlines = 0;
if( thelabel != "")
{
float i,n = tokenizebyseparator(thelabel, "\n");
}
}
- maxh -= max(nlines*gtv_text_size_small.y,picent.maxs.y);
+ // Center the contents in the bounding box
+ maxh -= max(nlines*gtv_text_size_small.y,image_size.y);
if ( maxh > 0 )
offset.y += maxh/2;
- drawstring(title.origin+offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
+ // Draw the title
+ drawstring(offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
+
+ // Draw the icon
if(pic != "")
- drawpic(picent.origin+offset, pic, picent.maxs, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ drawpic('0 1 0'*title_gap+'0.5 0 0'*desc_padding+offset, pic, image_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ // Draw the description
for ( last = title.chain; last ; )
{
drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
remove(next);
}
- remove(picent);
+ // Cleanup
remove(title);
}
text_size = stringwidth(label, false, hud_fontsize);
float theAlpha;
- if (mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
+ if (!(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
theAlpha = mv_top2_alpha;
else
theAlpha = 1;
else
drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', theAlpha, DRAWFLAG_NORMAL);
- if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+ if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
drawfill(pos, img_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
}
mask = ReadLong();
for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
- mv_avail[i] = (mask & power) ? GTV_AVAILABLE : GTV_FORBIDDEN;
+ {
+ if ( mask & power )
+ mv_flags[i] |= GTV_AVAILABLE;
+ else
+ mv_flags[i] &= ~GTV_AVAILABLE;
+ }
}
else
{
for(i = 0; i < mv_num_maps; ++i )
- mv_avail[i] = ReadByte();
+ mv_flags[i] = ReadByte();
}
}
-void MapVote_Init()
+void MapVote_ReadOption(int i)
+{
+ string map = strzone(ReadString());
+ string pk3 = strzone(ReadString());
+ int j = bound(0, ReadByte(), n_ssdirs - 1);
+
+ mv_maps[i] = map;
+ mv_pk3[i] = pk3;
+ mv_flags[i] = GTV_AVAILABLE;
+
+ string pic = strzone(strcat(ssdirs[j], "/", map));
+ mv_pics[i] = pic;
+ mv_preview[i] = false;
+ MapVote_CheckPic(pic, pk3, i);
+}
+
+void GameTypeVote_ReadOption(int i)
{
- int i, j;
- string map, pk3, s;
+ string gt = strzone(ReadString());
+
+ mv_maps[i] = gt;
+ mv_flags[i] = ReadByte();
+ string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, gt);
+ if(precache_pic(mv_picpath) == "")
+ mv_picpath = strcat("gfx/menu/default/gametype_", gt);
+ string pic = strzone(mv_picpath);
+ mv_pics[i] = pic;
+ mv_preview[i] = PreviewExists(pic);
+
+ if ( mv_flags[i] & GTV_CUSTOM )
+ {
+ string name = ReadString();
+ if ( strlen(name) < 1 )
+ name = gt;
+ mv_pk3[i] = strzone(name);
+ mv_desc[i] = strzone(ReadString());
+ }
+ else
+ {
+ int type = MapInfo_Type_FromString(gt);
+ mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
+ mv_desc[i] = MapInfo_Type_Description(type);
+ }
+}
+
+void MapVote_Init()
+{
precache_sound ("misc/invshot.wav");
mv_active = 1;
mv_selection = -1;
mv_selection_keyboard = 0;
+ string s;
for(n_ssdirs = 0; ; ++n_ssdirs)
{
s = ReadString();
}
MapVote_ReadMask();
+ int i;
for(i = 0; i < mv_num_maps; ++i )
- mv_avail_start[i] = mv_avail[i];
+ mv_flags_start[i] = mv_flags[i];
// Assume mv_pk3list is world, there should only be 1 mapvote per round
mv_pk3list = world; // I'm still paranoid!
{
mv_votes[i] = 0;
- map = strzone(ReadString());
- pk3 = strzone(ReadString());
- j = bound(0, ReadByte(), n_ssdirs - 1);
-
- mv_maps[i] = map;
- mv_pk3[i] = pk3;
- mv_avail[i] = ReadByte();
-
- if(gametypevote)
- {
- //map = strzone(strcat("gfx/menu/default/gametype_", map));
- //map = strzone(sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map));
- string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map);
- if(precache_pic(mv_picpath) == "")
- mv_picpath = strcat("gfx/menu/default/gametype_", map);
- map = strzone(mv_picpath);
- mv_pics[i] = map;
- mv_preview[i] = PreviewExists(map);
- }
+ if ( gametypevote )
+ GameTypeVote_ReadOption(i);
else
- {
- map = strzone(strcat(ssdirs[j], "/", map));
- mv_pics[i] = map;
- mv_preview[i] = false;
- MapVote_CheckPic(map, pk3, i);
- }
+ MapVote_ReadOption(i);
}
for(i = 0; i < n_ssdirs; ++i)
imp = mv_num_maps - 1;
else
imp = pos < 1 ? mv_num_maps - 1 : pos - 1;
- if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
imp = MapVote_MoveLeft(imp);
return imp;
}
imp = 0;
else
imp = pos >= mv_num_maps - 1 ? 0 : pos + 1;
- if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
imp = MapVote_MoveRight(imp);
return imp;
}
imp -= mv_columns;
}
}
- if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
imp = MapVote_MoveUp(imp);
return imp;
}
if ( imp >= mv_num_maps )
imp = imp % mv_columns;
}
- if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
imp = MapVote_MoveDown(imp);
return imp;
}
int i;
for(i = 0; i < mv_num_maps; ++i)
{
- if(mv_avail[i] == GTV_AVAILABLE)
+ if(mv_flags[i] & GTV_AVAILABLE)
{
if(mv_detail)
mv_votes[i] = ReadByte();
#define MAPVOTING_H
#include "../common/constants.qh"
-
-int mv_num_maps;
-
-float mv_active;
-string mv_maps[MAPVOTE_COUNT];
-string mv_pics[MAPVOTE_COUNT];
-string mv_pk3[MAPVOTE_COUNT];
-float mv_preview[MAPVOTE_COUNT];
-float mv_votes[MAPVOTE_COUNT];
-float mv_avail[MAPVOTE_COUNT];
-float mv_avail_start[MAPVOTE_COUNT];
-entity mv_pk3list;
-float mv_abstain;
-float mv_ownvote;
-float mv_detail;
-float mv_timeout;
-float mv_top2_time;
-float mv_top2_alpha;
-
-vector mv_mousepos;
-int mv_selection;
-int mv_columns;
-int mv_mouse_selection;
-int mv_selection_keyboard;
-
-float gametypevote;
-string mapvote_chosenmap;
-vector gtv_text_size;
-vector gtv_text_size_small;
-
-string MapVote_FormatMapItem(int id, string map, float count, float maxwidth, vector fontsize);
-
-string GameTypeVote_DescriptionByID(int id);
-
-vector MapVote_RGB(int id);
-
-void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float count, int id);
-
-void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float count, int id);
-
-void MapVote_DrawAbstain(vector pos, float isize, float tsize, float count, int id);
-
-vector MapVote_GridVec(vector gridspec, int i, int m);
-
-float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns);
-
void MapVote_Draw();
void Cmd_MapVote_MapDownload(float argc);
-void MapVote_CheckPK3(string pic, string pk3, int id);
-
-void MapVote_CheckPic(string pic, string pk3, int id);
-
-void MapVote_ReadMask();
-
-const int NUM_SSDIRS = 4;
-string ssdirs[NUM_SSDIRS];
-int n_ssdirs;
-void MapVote_Init();
-
-void MapVote_SendChoice(float index);
-
-int MapVote_MoveLeft(int pos);
-int MapVote_MoveRight(int pos);
-int MapVote_MoveUp(int pos);
-
-int MapVote_MoveDown(int pos);
-
float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary);
-void MapVote_UpdateMask();
-
-void MapVote_UpdateVotes();
-
void Ent_MapVote();
void Net_MapVote_Picture();
.float scale;
.vector movedir;
+void Ent_Wall_PreDraw()
+{
+ if (self.inactive)
+ {
+ self.alpha = 0;
+ }
+ else
+ {
+ vector org = getpropertyvec(VF_ORIGIN);
+ if(!checkpvs(org, self))
+ self.alpha = 0;
+ else if(self.fade_start || self.fade_end) {
+ vector offset = '0 0 0';
+ offset_z = self.fade_vertical_offset;
+ float player_dist = vlen(org - self.origin - 0.5 * (self.mins + self.maxs) + offset);
+ if (self.fade_end == self.fade_start)
+ {
+ if (player_dist >= self.fade_start)
+ self.alpha = 0;
+ else
+ self.alpha = 1;
+ }
+ else
+ {
+ self.alpha = (self.alpha_min + self.alpha_max * bound(0,
+ (self.fade_end - player_dist)
+ / (self.fade_end - self.fade_start), 1)) / 100.0;
+ }
+ }
+ else
+ {
+ self.alpha = 1;
+ }
+ }
+ if(self.alpha <= 0)
+ self.drawmask = 0;
+ else
+ self.drawmask = MASK_NORMAL;
+}
+
void Ent_Wall_Draw()
{
float f;
self.movedir_z = ReadCoord();
self.lip = ReadByte() / 255.0;
}
+ self.fade_start = ReadShort();
+ self.fade_end = ReadShort();
+ self.alpha_max = ReadShort();
+ self.alpha_min = ReadShort();
+ self.inactive = ReadShort();
+ self.fade_vertical_offset = ReadShort();
BGMScript_InitEntity(self);
}
self.entremove = Ent_Wall_Remove;
self.draw = Ent_Wall_Draw;
+ self.predraw = Ent_Wall_PreDraw;
}
class(Wall) .float loddistance1, loddistance2;
class(Wall) .vector saved;
+// Needed for interactive clientwalls
+.float inactive; // Clientwall disappears when inactive
+.float alpha_max, alpha_min;
+// If fade_start > fade_end, fadeout will be inverted
+// fade_vertical_offset is a vertival offset for player position
+.float fade_start, fade_end, fade_vertical_offset;
+.float default_solid;
+
void Ent_Wall_Draw();
void Ent_Wall_Remove();
const int URI_GET_URLLIB = 128;
const int URI_GET_URLLIB_END = 191;
-// gametype votes
-const int GTV_AVAILABLE = 0;
-// for later use in per-map gametype filtering
-const int GTV_FORBIDDEN = 2;
+// gametype vote flags
+const int GTV_FORBIDDEN = 0; // Cannot be voted
+const int GTV_AVAILABLE = 1; // Can be voted
+const int GTV_CUSTOM = 2; // Custom entry
#endif
+/** If you register a new item, make sure to add it to this list */
#include "item/ammo.qc"
#include "item/armor.qc"
#include "item/buff.qc"
#include "item/jetpack.qc"
#include "item/pickup.qc"
#include "item/powerup.qc"
+#include "../../server/mutators/mutator_instagib_items.qc"
int ITEM_COUNT;
+/** If you register a new item, make sure to add it to all.inc */
#define REGISTER_ITEM(id, class, body) \
entity ITEM_##id; \
void RegisterItems_##id() { \
#include "../server/miscfunctions.qh"
+// client side physics
+bool Physics_Valid(string thecvar)
+{
+ if(!autocvar_g_physics_clientselect) { return false; }
+
+ string l = strcat(" ", autocvar_g_physics_clientselect_options, " ");
+
+ if(strstrofs(l, strcat(" ", thecvar, " "), 0) >= 0)
+ return true;
+
+ return false;
+}
+
+float Physics_ClientOption(entity pl, string option)
+{
+ if(Physics_Valid(pl.cvar_cl_physics))
+ {
+ string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+ if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(var);
+ }
+ if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
+ {
+ string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+ if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(var);
+ }
+ return cvar(strcat("sv_", option));
+}
+
void Physics_AddStats()
{
// static view offset and hitbox vectors
addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick);
addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump);
+ // new properties
+ addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
+ addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
+ addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
+ addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
+ addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
+ addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
+ addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
+ addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
+ addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
+ addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
+ addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
+ addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
+ addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
+ addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
+
addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground);
}
self.stat_pl_crouch_min = PL_CROUCH_MIN;
self.stat_pl_crouch_max = PL_CROUCH_MAX;
- self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod);
- if (autocvar_sv_airstrafeaccel_qw)
- self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod);
+
+ self.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airaccel_qw"), maxspd_mod);
+ if(Physics_ClientOption(self, "airstrafeaccel_qw"))
+ self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airstrafeaccel_qw"), maxspd_mod);
else
self.stat_sv_airstrafeaccel_qw = 0;
- self.stat_sv_airspeedlimit_nonqw = autocvar_sv_airspeedlimit_nonqw * maxspd_mod;
- self.stat_sv_maxspeed = autocvar_sv_maxspeed * maxspd_mod; // also slow walking
+ self.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(self, "airspeedlimit_nonqw") * maxspd_mod;
+ self.stat_sv_maxspeed = Physics_ClientOption(self, "maxspeed") * maxspd_mod; // also slow walking
self.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this!
self.stat_doublejump = PHYS_DOUBLEJUMP;
self.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP;
+
+ // old stats
+ // fix some new settings
+ self.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(self, "airaccel_qw_stretchfactor");
+ self.stat_sv_maxairstrafespeed = Physics_ClientOption(self, "maxairstrafespeed");
+ self.stat_sv_maxairspeed = Physics_ClientOption(self, "maxairspeed");
+ self.stat_sv_airstrafeaccelerate = Physics_ClientOption(self, "airstrafeaccelerate");
+ self.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(self, "warsowbunny_turnaccel");
+ self.stat_sv_airaccel_sideways_friction = Physics_ClientOption(self, "airaccel_sideways_friction");
+ self.stat_sv_aircontrol = Physics_ClientOption(self, "aircontrol");
+ self.stat_sv_aircontrol_power = Physics_ClientOption(self, "aircontrol_power");
+ self.stat_sv_aircontrol_penalty = Physics_ClientOption(self, "aircontrol_penalty");
+ self.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(self, "warsowbunny_airforwardaccel");
+ self.stat_sv_warsowbunny_topspeed = Physics_ClientOption(self, "warsowbunny_topspeed");
+ self.stat_sv_warsowbunny_accel = Physics_ClientOption(self, "warsowbunny_accel");
+ self.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(self, "warsowbunny_backtosideratio");
+ self.stat_sv_friction = Physics_ClientOption(self, "friction");
+ self.stat_sv_accelerate = Physics_ClientOption(self, "accelerate");
+ self.stat_sv_stopspeed = Physics_ClientOption(self, "stopspeed");
+ self.stat_sv_airaccelerate = Physics_ClientOption(self, "airaccelerate");
+ self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
+ self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
+
self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
}
#endif
if (k <= 0)
return;
- k *= bound(0, wishspeed / PHYS_MAXAIRSPEED, 1);
+ k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(self), 1);
float zspeed = self.velocity_z;
self.velocity_z = 0;
if (time >= self.spider_slowness)
return;
PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
- self.stat_sv_airspeedlimit_nonqw *= 0.5;
+ PHYS_MAXAIRSPEED(self) *= 0.5;
+ PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
+ PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
#endif
}
vector wishvel = v_forward * self.movement_x
+ v_right * self.movement_y;
// add remaining speed as Z component
- float maxairspd = PHYS_MAXAIRSPEED * max(1, maxspd_mod);
+ float maxairspd = PHYS_MAXAIRSPEED(self) * max(1, maxspd_mod);
// fix speedhacks :P
wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
// add the unused velocity as up component
if (pmove_waterjumptime <= 0)
#endif
{
- float maxairspd = PHYS_MAXAIRSPEED * min(maxspd_mod, 1);
+ float maxairspd = PHYS_MAXAIRSPEED(self) * min(maxspd_mod, 1);
// apply air speed limit
float airaccelqw = PHYS_AIRACCEL_QW(self);
// log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
float strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
if (PHYS_MAXAIRSTRAFESPEED)
- wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod));
- if (PHYS_AIRSTRAFEACCELERATE)
- airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE*maxspd_mod);
+ wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(self)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod));
+ if (PHYS_AIRSTRAFEACCELERATE(self))
+ airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(self)*maxspd_mod);
if (PHYS_AIRSTRAFEACCEL_QW(self))
airaccelqw =
(((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(self) : PHYS_AIRACCEL_QW(self)) >= 0) ? +1 : -1)
maxspeed_mod = self.spectatorspeed;
}
- float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED) * maxspeed_mod;
+ float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED(self)) * maxspeed_mod;
if(self.speed != spd)
{
self.speed = spd;
#define PHYS_AIRSPEEDLIMIT_NONQW(s) getstatf(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW)
#define PHYS_AIRSTOPACCELERATE getstatf(STAT_MOVEVARS_AIRSTOPACCELERATE)
#define PHYS_AIRSTRAFEACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCEL_QW)
- #define PHYS_AIRSTRAFEACCELERATE getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
+ #define PHYS_AIRSTRAFEACCELERATE(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
#define PHYS_ENTGRAVITY(s) getstatf(STAT_MOVEVARS_ENTGRAVITY)
#define PHYS_FRICTION getstatf(STAT_MOVEVARS_FRICTION)
#define PHYS_FRICTION_SLICK getstatf(STAT_MOVEVARS_FRICTION_SLICK)
#define PHYS_GRAVITY getstatf(STAT_MOVEVARS_GRAVITY)
#define PHYS_HIGHSPEED getstatf(STAT_MOVEVARS_HIGHSPEED)
#define PHYS_JUMPVELOCITY getstatf(STAT_MOVEVARS_JUMPVELOCITY)
- #define PHYS_MAXAIRSPEED getstatf(STAT_MOVEVARS_MAXAIRSPEED)
+ #define PHYS_MAXAIRSPEED(s) getstatf(STAT_MOVEVARS_MAXAIRSPEED)
#define PHYS_MAXAIRSTRAFESPEED getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
#define PHYS_MAXSPEED(s) getstatf(STAT_MOVEVARS_MAXSPEED)
#define PHYS_STEPHEIGHT getstatf(STAT_MOVEVARS_STEPHEIGHT)
#elif defined(SVQC)
+ bool Physics_Valid(string thecvar);
+
.vector stat_pl_view_ofs;
.vector stat_pl_crouch_view_ofs;
.float stat_bugrigs_reverse_spinning;
.float stat_bugrigs_reverse_stopping;
+ // new properties
+ .float stat_sv_jumpvelocity;
+ .float stat_sv_airaccel_qw_stretchfactor;
+ .float stat_sv_maxairstrafespeed;
+ .float stat_sv_maxairspeed;
+ .float stat_sv_airstrafeaccelerate;
+ .float stat_sv_warsowbunny_turnaccel;
+ .float stat_sv_airaccel_sideways_friction;
+ .float stat_sv_aircontrol;
+ .float stat_sv_aircontrol_power;
+ .float stat_sv_aircontrol_penalty;
+ .float stat_sv_warsowbunny_airforwardaccel;
+ .float stat_sv_warsowbunny_topspeed;
+ .float stat_sv_warsowbunny_accel;
+ .float stat_sv_warsowbunny_backtosideratio;
+ .float stat_sv_friction;
+ .float stat_sv_accelerate;
+ .float stat_sv_stopspeed;
+ .float stat_sv_airaccelerate;
+ .float stat_sv_airstopaccelerate;
+
.float stat_nostep;
.float stat_jumpstep;
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS autocvar_sv_jumpspeedcap_max_disable_on_ramps
#define PHYS_TRACK_CANJUMP(s) s.cvar_cl_movement_track_canjump
- #define PHYS_ACCELERATE autocvar_sv_accelerate
+ #define PHYS_ACCELERATE self.stat_sv_accelerate
#define PHYS_AIRACCEL_QW(s) s.stat_sv_airaccel_qw
- #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) autocvar_sv_airaccel_qw_stretchfactor
- #define PHYS_AIRACCEL_SIDEWAYS_FRICTION autocvar_sv_airaccel_sideways_friction
- #define PHYS_AIRACCELERATE autocvar_sv_airaccelerate
- #define PHYS_AIRCONTROL autocvar_sv_aircontrol
- #define PHYS_AIRCONTROL_PENALTY autocvar_sv_aircontrol_penalty
- #define PHYS_AIRCONTROL_POWER autocvar_sv_aircontrol_power
+ #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) self.stat_sv_airaccel_qw_stretchfactor
+ #define PHYS_AIRACCEL_SIDEWAYS_FRICTION self.stat_sv_airaccel_sideways_friction
+ #define PHYS_AIRACCELERATE self.stat_sv_airaccelerate
+ #define PHYS_AIRCONTROL self.stat_sv_aircontrol
+ #define PHYS_AIRCONTROL_PENALTY self.stat_sv_aircontrol_penalty
+ #define PHYS_AIRCONTROL_POWER self.stat_sv_aircontrol_power
#define PHYS_AIRSPEEDLIMIT_NONQW(s) s.stat_sv_airspeedlimit_nonqw
- #define PHYS_AIRSTOPACCELERATE autocvar_sv_airstopaccelerate
+ #define PHYS_AIRSTOPACCELERATE self.stat_sv_airstopaccelerate
#define PHYS_AIRSTRAFEACCEL_QW(s) s.stat_sv_airstrafeaccel_qw
- #define PHYS_AIRSTRAFEACCELERATE autocvar_sv_airstrafeaccelerate
+ #define PHYS_AIRSTRAFEACCELERATE(s) s.stat_sv_airstrafeaccelerate
#define PHYS_ENTGRAVITY(s) s.gravity
- #define PHYS_FRICTION autocvar_sv_friction
+ #define PHYS_FRICTION self.stat_sv_friction
#define PHYS_FRICTION_SLICK autocvar_sv_friction_slick
#define PHYS_FRICTION_ONLAND autocvar_sv_friction_on_land
#define PHYS_GRAVITY autocvar_sv_gravity
#define PHYS_HIGHSPEED autocvar_g_movement_highspeed
- #define PHYS_JUMPVELOCITY autocvar_sv_jumpvelocity
- #define PHYS_MAXAIRSPEED autocvar_sv_maxairspeed
- #define PHYS_MAXAIRSTRAFESPEED autocvar_sv_maxairstrafespeed
+ #define PHYS_JUMPVELOCITY self.stat_sv_jumpvelocity
+ #define PHYS_MAXAIRSPEED(s) self.stat_sv_maxairspeed
+ #define PHYS_MAXAIRSTRAFESPEED self.stat_sv_maxairstrafespeed
#define PHYS_MAXSPEED(s) s.stat_sv_maxspeed
#define PHYS_STEPHEIGHT autocvar_sv_stepheight
- #define PHYS_STOPSPEED autocvar_sv_stopspeed
- #define PHYS_WARSOWBUNNY_ACCEL autocvar_sv_warsowbunny_accel
- #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO autocvar_sv_warsowbunny_backtosideratio
- #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL autocvar_sv_warsowbunny_airforwardaccel
- #define PHYS_WARSOWBUNNY_TOPSPEED autocvar_sv_warsowbunny_topspeed
- #define PHYS_WARSOWBUNNY_TURNACCEL autocvar_sv_warsowbunny_turnaccel
+ #define PHYS_STOPSPEED self.stat_sv_stopspeed
+ #define PHYS_WARSOWBUNNY_ACCEL self.stat_sv_warsowbunny_accel
+ #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO self.stat_sv_warsowbunny_backtosideratio
+ #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL self.stat_sv_warsowbunny_airforwardaccel
+ #define PHYS_WARSOWBUNNY_TOPSPEED self.stat_sv_warsowbunny_topspeed
+ #define PHYS_WARSOWBUNNY_TURNACCEL self.stat_sv_warsowbunny_turnaccel
#define PHYS_WALLFRICTION cvar("sv_wallfriction")
}
if (s != "")
{
+ // Flag to set func_clientwall state
+ // 1 == deactivate, 2 == activate, 0 == do nothing
+ float aw_flag = self.antiwall_flag;
for(t = world; (t = find(t, targetname, s)); )
if(t.use)
{
}
else
{
+ if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
+ t.antiwall_flag = aw_flag;
self = t;
other = stemp;
activator = act;
.void() trigger_touch;
+.float antiwall_flag; // Variable to define what to do with func_clientwall
+// 0 == do nothing, 1 == deactivate, 2 == activate
+
.float height;
.float nottargeted;
// note: include only those that should be in the menu!
#define GAMETYPES \
- GAMETYPE(MAPINFO_TYPE_ASSAULT) \
+ GAMETYPE(MAPINFO_TYPE_DEATHMATCH) \
+ GAMETYPE(MAPINFO_TYPE_TEAM_DEATHMATCH) \
GAMETYPE(MAPINFO_TYPE_CTF) \
GAMETYPE(MAPINFO_TYPE_CA) \
- GAMETYPE(MAPINFO_TYPE_DEATHMATCH) \
- GAMETYPE(MAPINFO_TYPE_DOMINATION) \
GAMETYPE(MAPINFO_TYPE_FREEZETAG) \
GAMETYPE(MAPINFO_TYPE_KEEPAWAY) \
GAMETYPE(MAPINFO_TYPE_KEYHUNT) \
GAMETYPE(MAPINFO_TYPE_LMS) \
+ GAMETYPE(MAPINFO_TYPE_DOMINATION) \
GAMETYPE(MAPINFO_TYPE_NEXBALL) \
GAMETYPE(MAPINFO_TYPE_ONSLAUGHT) \
+ GAMETYPE(MAPINFO_TYPE_ASSAULT) \
if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_RACE) \
GAMETYPE(MAPINFO_TYPE_CTS) \
- GAMETYPE(MAPINFO_TYPE_TEAM_DEATHMATCH) \
//GAMETYPE(MAPINFO_TYPE_INVASION) \
/* nothing */
float autocvar_snd_soundradius;
int autocvar_spawn_debug;
bool autocvar_speedmeter;
-float autocvar_sv_accelerate;
float autocvar_sv_accuracy_data_share = 1;
string autocvar_sv_adminnick;
-float autocvar_sv_airaccel_qw;
-float autocvar_sv_airaccel_qw_stretchfactor;
-float autocvar_sv_airaccel_sideways_friction;
-float autocvar_sv_airaccelerate;
-float autocvar_sv_aircontrol;
-float autocvar_sv_aircontrol_penalty;
-float autocvar_sv_aircontrol_power;
-float autocvar_sv_airspeedlimit_nonqw;
-float autocvar_sv_airstopaccelerate;
-float autocvar_sv_airstrafeaccel_qw;
-float autocvar_sv_airstrafeaccelerate;
bool autocvar_sv_autoscreenshot;
int autocvar_sv_cheats;
float autocvar_sv_clientcommand_antispam_time;
string autocvar_sv_eventlog_files_nameprefix;
string autocvar_sv_eventlog_files_namesuffix;
bool autocvar_sv_eventlog_files_timestamps;
-float autocvar_sv_friction;
float autocvar_sv_friction_on_land;
var float autocvar_sv_friction_slick = 0.5;
float autocvar_sv_gameplayfix_q2airaccelerate;
string autocvar_sv_logscores_filename;
float autocvar_sv_mapchange_delay;
float autocvar_sv_maxairspeed;
-float autocvar_sv_maxairstrafespeed;
float autocvar_sv_maxspeed;
string autocvar_sv_motd;
bool autocvar_sv_precacheplayermodels;
float autocvar_sv_spectator_speed_multiplier;
bool autocvar_sv_status_privacy;
float autocvar_sv_stepheight;
-float autocvar_sv_stopspeed;
float autocvar_sv_strengthsound_antispam_refire_threshold;
float autocvar_sv_strengthsound_antispam_time;
bool autocvar_sv_teamnagger;
float autocvar_sv_vote_timeout;
float autocvar_sv_vote_wait;
bool autocvar_sv_vote_gamestart;
-float autocvar_sv_warsowbunny_accel;
-float autocvar_sv_warsowbunny_airforwardaccel;
-float autocvar_sv_warsowbunny_backtosideratio;
-float autocvar_sv_warsowbunny_topspeed;
-float autocvar_sv_warsowbunny_turnaccel;
float autocvar_sv_waypointsprite_deadlifetime;
float autocvar_sv_waypointsprite_deployed_lifetime;
float autocvar_sv_waypointsprite_limitedrange;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
+bool autocvar_g_physics_clientselect;
+string autocvar_g_physics_clientselect_options;
+string autocvar_g_physics_clientselect_default;
float autocvar_g_buffs_waypoint_distance;
bool autocvar_g_buffs_randomize;
float autocvar_g_buffs_random_lifetime;
+++ /dev/null
-#include "_all.qh"
-#include "bot/bot.qh"
-#include "g_damage.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../dpdefs/progsdefs.qh"
- #include "../dpdefs/dpextensions.qh"
- #include "../warpzonelib/mathlib.qh"
- #include "../warpzonelib/server.qh"
- #include "../common/constants.qh"
- #include "../common/util.qh"
- #include "../common/animdecide.qh"
- #include "../common/monsters/sv_monsters.qh"
- #include "../common/weapons/all.qh"
- #include "t_items.qh"
- #include "autocvars.qh"
- #include "defs.qh"
- #include "../common/notifications.qh"
- #include "mutators/mutators_include.qh"
- #include "../common/mapinfo.qh"
- #include "../csqcmodellib/sv_model.qh"
- #include "anticheat.qh"
- #include "cheats.qh"
- #include "g_hook.qh"
- #include "race.qh"
- #include "playerdemo.qh"
-#endif
-
-.float race_penalty;
-.float restart_jump;
-
-.float ladder_time;
-.entity ladder_entity;
-.float gravity;
-.float swamp_slowdown;
-.int lastflags;
-.float lastground;
-.float wasFlying;
-.float spectatorspeed;
-
-/*
-=============
-PlayerJump
-
-When you press the jump key
-returns true if handled
-=============
-*/
-float PlayerJump (void)
-{
- if(self.frozen)
- return true; // no jumping in freezetag when frozen
-
- if(self.player_blocked)
- return true; // no jumping while blocked
-
- float doublejump = false;
- float mjumpheight = autocvar_sv_jumpvelocity;
-
- player_multijump = doublejump;
- player_jumpheight = mjumpheight;
- if(MUTATOR_CALLHOOK(PlayerJump))
- return true;
-
- doublejump = player_multijump;
- mjumpheight = player_jumpheight;
-
- if (autocvar_sv_doublejump)
- {
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
- if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
- {
- doublejump = true;
-
- // we MUST clip velocity here!
- float f;
- f = self.velocity * trace_plane_normal;
- if(f < 0)
- self.velocity -= f * trace_plane_normal;
- }
- }
-
- if (self.waterlevel >= WATERLEVEL_SWIMMING)
- {
- self.velocity_z = self.stat_sv_maxspeed * 0.7;
- return true;
- }
-
- if (!doublejump)
- if (!(self.flags & FL_ONGROUND))
- return !(self.flags & FL_JUMPRELEASED);
-
- if(self.cvar_cl_movement_track_canjump)
- if (!(self.flags & FL_JUMPRELEASED))
- return true;
-
- // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
- // velocity bounds. Final velocity is bound between (jumpheight *
- // min + jumpheight) and (jumpheight * max + jumpheight);
-
- if(autocvar_sv_jumpspeedcap_min != "")
- {
- float minjumpspeed;
-
- minjumpspeed = mjumpheight * stof(autocvar_sv_jumpspeedcap_min);
-
- if (self.velocity.z < minjumpspeed)
- mjumpheight += minjumpspeed - self.velocity.z;
- }
-
- if(autocvar_sv_jumpspeedcap_max != "")
- {
- // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
-
- if(!(trace_fraction < 1 && trace_plane_normal.z < 0.98 && autocvar_sv_jumpspeedcap_max_disable_on_ramps))
- {
- float maxjumpspeed;
-
- maxjumpspeed = mjumpheight * stof(autocvar_sv_jumpspeedcap_max);
-
- if (self.velocity.z > maxjumpspeed)
- mjumpheight -= self.velocity.z - maxjumpspeed;
- }
- }
-
- if(!(self.lastflags & FL_ONGROUND))
- {
- if(autocvar_speedmeter)
- dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
- if(self.lastground < time - 0.3)
- {
- self.velocity_x *= (1 - autocvar_sv_friction_on_land);
- self.velocity_y *= (1 - autocvar_sv_friction_on_land);
- }
- if(self.jumppadcount > 1)
- dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
- self.jumppadcount = 0;
- }
-
- self.velocity_z = self.velocity.z + mjumpheight;
- self.oldvelocity_z = self.velocity.z;
-
- self.flags &= ~FL_ONGROUND;
- self.flags &= ~FL_JUMPRELEASED;
-
- animdecide_setaction(self, ANIMACTION_JUMP, true);
-
- if(autocvar_g_jump_grunt)
- PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-
- self.restart_jump = -1; // restart jump anim next time
- // value -1 is used to not use the teleport bit (workaround for tiny hitch when re-jumping)
- return true;
-}
-void CheckWaterJump()
-{
- vector start, end;
-
-// check for a jump-out-of-water
- makevectors (self.angles);
- start = self.origin;
- start.z = start.z + 8;
- v_forward.z = 0;
- normalize(v_forward);
- end = start + v_forward*24;
- traceline (start, end, true, self);
- if (trace_fraction < 1)
- { // solid at waist
- start.z = start.z + self.maxs.z - 8;
- end = start + v_forward*24;
- self.movedir = trace_plane_normal * -50;
- traceline (start, end, true, self);
- if (trace_fraction == 1)
- { // open at eye level
- self.flags |= FL_WATERJUMP;
- self.velocity_z = 225;
- self.flags &= ~FL_JUMPRELEASED;
- self.teleport_time = time + 2; // safety net
- return;
- }
- }
-}
-
-.float jetpack_stopped;
-// Hack: shouldn't need to know about this
-.float multijump_count;
-void CheckPlayerJump()
-{
- float was_flying = self.items & IT_USING_JETPACK;
-
- if (self.cvar_cl_jetpack_jump < 2)
- self.items &= ~IT_USING_JETPACK;
-
- if (self.BUTTON_JUMP || self.BUTTON_JETPACK)
- {
- float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects
- float activate = self.cvar_cl_jetpack_jump && air_jump && self.BUTTON_JUMP || self.BUTTON_JETPACK;
- float has_fuel = !autocvar_g_jetpack_fuel || self.ammo_fuel || self.items & IT_UNLIMITED_WEAPON_AMMO;
- if (!(self.items & IT_JETPACK)) { }
- else if (self.jetpack_stopped) { }
- else if (!has_fuel)
- {
- if (was_flying) // TODO: ran out of fuel message
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
- else if (activate)
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
- self.jetpack_stopped = true;
- self.items &= ~IT_USING_JETPACK;
- }
- else if (activate && !self.frozen)
- self.items |= IT_USING_JETPACK;
- }
- else
- {
- self.jetpack_stopped = false;
- self.items &= ~IT_USING_JETPACK;
- }
- if (!self.BUTTON_JUMP)
- self.flags |= FL_JUMPRELEASED;
-
- if (self.waterlevel == WATERLEVEL_SWIMMING)
- CheckWaterJump ();
-}
-
-float racecar_angle(float forward, float down)
-{
- float ret, angle_mult;
-
- if(forward < 0)
- {
- forward = -forward;
- down = -down;
- }
-
- ret = vectoyaw('0 1 0' * down + '1 0 0' * forward);
-
- angle_mult = forward / (800 + forward);
-
- if(ret > 180)
- return ret * angle_mult + 360 * (1 - angle_mult);
- else
- return ret * angle_mult;
-}
-
-void RaceCarPhysics()
-{
- // using this move type for "big rigs"
- // the engine does not push the entity!
-
- float accel, steer, f, myspeed, steerfactor;
- vector angles_save, rigvel;
-
- angles_save = self.angles;
- accel = bound(-1, self.movement.x / self.stat_sv_maxspeed, 1);
- steer = bound(-1, self.movement.y / self.stat_sv_maxspeed, 1);
-
- if(g_bugrigs_reverse_speeding)
- {
- if(accel < 0)
- {
- // back accel is DIGITAL
- // to prevent speedhack
- if(accel < -0.5)
- accel = -1;
- else
- accel = 0;
- }
- }
-
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles); // new forward direction!
-
- if(self.flags & FL_ONGROUND || g_bugrigs_air_steering)
- {
- float upspeed, accelfactor;
-
- myspeed = self.velocity * v_forward;
- upspeed = self.velocity * v_up;
-
- // responsiveness factor for steering and acceleration
- f = 1 / (1 + pow(max(-myspeed, myspeed) / g_bugrigs_speed_ref, g_bugrigs_speed_pow));
- //MAXIMA: f(v) := 1 / (1 + (v / g_bugrigs_speed_ref) ^ g_bugrigs_speed_pow);
-
- if(myspeed < 0 && g_bugrigs_reverse_spinning)
- steerfactor = -myspeed * g_bugrigs_steer;
- else
- steerfactor = -myspeed * f * g_bugrigs_steer;
-
- if(myspeed < 0 && g_bugrigs_reverse_speeding)
- accelfactor = g_bugrigs_accel;
- else
- accelfactor = f * g_bugrigs_accel;
- //MAXIMA: accel(v) := f(v) * g_bugrigs_accel;
-
- if(accel < 0)
- {
- if(myspeed > 0)
- {
- myspeed = max(0, myspeed - frametime * (g_bugrigs_friction_floor - g_bugrigs_friction_brake * accel));
- }
- else
- {
- if(!g_bugrigs_reverse_speeding)
- myspeed = min(0, myspeed + frametime * g_bugrigs_friction_floor);
- }
- }
- else
- {
- if(myspeed >= 0)
- {
- myspeed = max(0, myspeed - frametime * g_bugrigs_friction_floor);
- }
- else
- {
- if(g_bugrigs_reverse_stopping)
- myspeed = 0;
- else
- myspeed = min(0, myspeed + frametime * (g_bugrigs_friction_floor + g_bugrigs_friction_brake * accel));
- }
- }
- // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
- //MAXIMA: friction(v) := g_bugrigs_friction_floor;
-
- self.angles_y += steer * frametime * steerfactor; // apply steering
- makevectors(self.angles); // new forward direction!
-
- myspeed += accel * accelfactor * frametime;
-
- rigvel = myspeed * v_forward + '0 0 1' * upspeed;
- }
- else
- {
- myspeed = vlen(self.velocity);
-
- // responsiveness factor for steering and acceleration
- f = 1 / (1 + pow(max(0, myspeed / g_bugrigs_speed_ref), g_bugrigs_speed_pow));
- steerfactor = -myspeed * f;
- self.angles_y += steer * frametime * steerfactor; // apply steering
-
- rigvel = self.velocity;
- makevectors(self.angles); // new forward direction!
- }
-
- rigvel = rigvel * max(0, 1 - vlen(rigvel) * g_bugrigs_friction_air * frametime);
- //MAXIMA: airfriction(v) := v * v * g_bugrigs_friction_air;
- //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
- //MAXIMA: solve(total_acceleration(v) = 0, v);
-
- if(g_bugrigs_planar_movement)
- {
- vector rigvel_xy, neworigin, up;
- float mt;
-
- rigvel.z -= frametime * autocvar_sv_gravity; // 4x gravity plays better
- rigvel_xy = vec2(rigvel);
-
- if(g_bugrigs_planar_movement_car_jumping)
- mt = MOVE_NORMAL;
- else
- mt = MOVE_NOMONSTERS;
-
- tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 1024', mt, self);
- up = trace_endpos - self.origin;
-
- // BUG RIGS: align the move to the surface instead of doing collision testing
- // can we move?
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos + rigvel_xy * frametime, mt, self);
-
- // align to surface
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos - up + '0 0 1' * rigvel.z * frametime, mt, self);
-
- if(trace_fraction < 0.5)
- {
- trace_fraction = 1;
- neworigin = self.origin;
- }
- else
- neworigin = trace_endpos;
-
- if(trace_fraction < 1)
- {
- // now set angles_x so that the car points parallel to the surface
- self.angles = vectoangles(
- '1 0 0' * v_forward.x * trace_plane_normal.z
- +
- '0 1 0' * v_forward.y * trace_plane_normal.z
- +
- '0 0 1' * -(v_forward.x * trace_plane_normal.x + v_forward.y * trace_plane_normal.y)
- );
- self.flags |= FL_ONGROUND;
- }
- else
- {
- // now set angles_x so that the car points forward, but is tilted in velocity direction
- self.flags &= ~FL_ONGROUND;
- }
-
- self.velocity = (neworigin - self.origin) * (1.0 / frametime);
- self.movetype = MOVETYPE_NOCLIP;
- }
- else
- {
- rigvel.z -= frametime * autocvar_sv_gravity; // 4x gravity plays better
- self.velocity = rigvel;
- self.movetype = MOVETYPE_FLY;
- }
-
- trace_fraction = 1;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
- if(trace_fraction != 1)
- {
- self.angles = vectoangles2(
- '1 0 0' * v_forward.x * trace_plane_normal.z
- +
- '0 1 0' * v_forward.y * trace_plane_normal.z
- +
- '0 0 1' * -(v_forward.x * trace_plane_normal.x + v_forward.y * trace_plane_normal.y),
- trace_plane_normal
- );
- }
- else
- {
- vector vel_local;
-
- vel_local.x = v_forward * self.velocity;
- vel_local.y = v_right * self.velocity;
- vel_local.z = v_up * self.velocity;
-
- self.angles_x = racecar_angle(vel_local.x, vel_local.z);
- self.angles_z = racecar_angle(-vel_local.y, vel_local.z);
- }
-
- // smooth the angles
- vector vf1, vu1, smoothangles;
- makevectors(self.angles);
- f = bound(0, frametime * g_bugrigs_angle_smoothing, 1);
- if(f == 0)
- f = 1;
- vf1 = v_forward * f;
- vu1 = v_up * f;
- makevectors(angles_save);
- vf1 = vf1 + v_forward * (1 - f);
- vu1 = vu1 + v_up * (1 - f);
- smoothangles = vectoangles2(vf1, vu1);
- self.angles_x = -smoothangles.x;
- self.angles_z = smoothangles.z;
-}
-
-float IsMoveInDirection(vector mv, float angle) // key mix factor
-{
- if(mv.x == 0 && mv.y == 0)
- return 0; // avoid division by zero
- angle -= RAD2DEG * atan2(mv.y, mv.x);
- angle = remainder(angle, 360) / 45;
- if(angle > 1)
- return 0;
- if(angle < -1)
- return 0;
- return 1 - fabs(angle);
-}
-
-float GeomLerp(float a, float lerp, float b)
-{
- if(a == 0)
- {
- if(lerp < 1)
- return 0;
- else
- return b;
- }
- if(b == 0)
- {
- if(lerp > 0)
- return 0;
- else
- return a;
- }
- return a * pow(fabs(b / a), lerp);
-}
-
-void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
- float zspeed, xyspeed, dot, k;
-
-#if 0
- // this doesn't play well with analog input
- if(self.movement_x == 0 || self.movement.y != 0)
- return; // can't control movement if not moving forward or backward
- k = 32;
-#else
- k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
- if(k <= 0)
- return;
-#endif
-
- k *= bound(0, wishspeed / autocvar_sv_maxairspeed, 1);
-
- zspeed = self.velocity.z;
- self.velocity_z = 0;
- xyspeed = vlen(self.velocity); self.velocity = normalize(self.velocity);
-
- dot = self.velocity * wishdir;
-
- if(dot > 0) // we can't change direction while slowing down
- {
- k *= pow(dot, autocvar_sv_aircontrol_power)*frametime;
- xyspeed = max(0, xyspeed - autocvar_sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32);
- k *= autocvar_sv_aircontrol;
- self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
- }
-
- self.velocity = self.velocity * xyspeed;
- self.velocity_z = zspeed;
-}
-
-float AdjustAirAccelQW(float accelqw, float factor)
-{
- return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
-}
-
-// example config for alternate speed clamping:
-// sv_airaccel_qw 0.8
-// sv_airaccel_sideways_friction 0
-// prvm_globalset server speedclamp_mode 1
-// (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
- float vel_straight;
- float velZ;
- vector vel_perpend;
- float step;
-
- vector vel_xy;
- float vel_xy_current;
- float vel_xy_backward, vel_xy_forward;
- float speedclamp;
-
- if(stretchfactor > 0)
- speedclamp = stretchfactor;
- else if(accelqw < 0)
- speedclamp = 1; // full clamping, no stretch
- else
- speedclamp = -1; // no clamping
-
- if(accelqw < 0)
- accelqw = -accelqw;
-
- if(autocvar_sv_gameplayfix_q2airaccelerate)
- wishspeed0 = wishspeed;
-
- vel_straight = self.velocity * wishdir;
- velZ = self.velocity.z;
- vel_xy = vec2(self.velocity);
- vel_perpend = vel_xy - vel_straight * wishdir;
-
- step = accel * frametime * wishspeed0;
-
- vel_xy_current = vlen(vel_xy);
- if(speedlimit)
- accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
- vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
- vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
- if(vel_xy_backward < 0)
- vel_xy_backward = 0; // not that it REALLY occurs that this would cause wrong behaviour afterwards
-
- vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
-
- if(sidefric < 0 && (vel_perpend*vel_perpend))
- // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
- {
- float f, fminimum;
- f = max(0, 1 + frametime * wishspeed * sidefric);
- fminimum = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / (vel_perpend*vel_perpend);
- // this cannot be > 1
- if(fminimum <= 0)
- vel_perpend = vel_perpend * max(0, f);
- else
- {
- fminimum = sqrt(fminimum);
- vel_perpend = vel_perpend * max(fminimum, f);
- }
- }
- else
- vel_perpend = vel_perpend * max(0, 1 - frametime * wishspeed * sidefric);
-
- vel_xy = vel_straight * wishdir + vel_perpend;
-
- if(speedclamp >= 0)
- {
- float vel_xy_preclamp;
- vel_xy_preclamp = vlen(vel_xy);
- if(vel_xy_preclamp > 0) // prevent division by zero
- {
- vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
- if(vel_xy_current < vel_xy_preclamp)
- vel_xy = vel_xy * (vel_xy_current / vel_xy_preclamp);
- }
- }
-
- self.velocity = vel_xy + velZ * '0 0 1';
-}
-
-void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
- vector curvel, wishvel, acceldir, curdir;
- float addspeed, accelspeed, curspeed, f;
- float dot;
-
- if(wishspeed == 0)
- return;
-
- curvel = self.velocity;
- curvel.z = 0;
- curspeed = vlen(curvel);
-
- if(wishspeed > curspeed * 1.01)
- {
- wishspeed = min(wishspeed, curspeed + autocvar_sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime);
- }
- else
- {
- f = max(0, (autocvar_sv_warsowbunny_topspeed - curspeed) / (autocvar_sv_warsowbunny_topspeed - self.stat_sv_maxspeed));
- wishspeed = max(curspeed, self.stat_sv_maxspeed) + autocvar_sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime;
- }
- wishvel = wishdir * wishspeed;
- acceldir = wishvel - curvel;
- addspeed = vlen(acceldir);
- acceldir = normalize(acceldir);
-
- accelspeed = min(addspeed, autocvar_sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime);
-
- if(autocvar_sv_warsowbunny_backtosideratio < 1)
- {
- curdir = normalize(curvel);
- dot = acceldir * curdir;
- if(dot < 0)
- acceldir = acceldir - (1 - autocvar_sv_warsowbunny_backtosideratio) * dot * curdir;
- }
-
- self.velocity += accelspeed * acceldir;
-}
-
-.vector movement_old;
-.float buttons_old;
-.vector v_angle_old;
-.string lastclassname;
-
-.float() PlayerPhysplug;
-
-string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
-.float specialcommand_pos;
-void SpecialCommand()
-{
-#ifdef TETRIS
- TetrisImpulse();
-#else
- if(!CheatImpulse(99))
- print("A hollow voice says \"Plugh\".\n");
-#endif
-}
-
-string GetMapname(void);
-float speedaward_lastupdate;
-float speedaward_lastsent;
-void SV_PlayerPhysics()
-{
- vector wishvel, wishdir, v;
- float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons;
- string temps;
- int buttons_prev;
- float not_allowed_to_move;
- string c;
-
- WarpZone_PlayerPhysics_FixVAngle();
-
- maxspd_mod = 1;
- if(self.ballcarried)
- if(g_keepaway)
- maxspd_mod *= autocvar_g_keepaway_ballcarrier_highspeed;
-
- maxspd_mod *= autocvar_g_movement_highspeed;
-
- // fix physics stats for g_movement_highspeed
- // TODO maybe rather use maxairspeed? needs testing
- self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod);
- if(autocvar_sv_airstrafeaccel_qw)
- self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod);
- else
- self.stat_sv_airstrafeaccel_qw = 0;
- self.stat_sv_airspeedlimit_nonqw = autocvar_sv_airspeedlimit_nonqw * maxspd_mod;
- self.stat_sv_maxspeed = autocvar_sv_maxspeed * maxspd_mod; // also slow walking
-
- if(self.PlayerPhysplug)
- if(self.PlayerPhysplug())
- return;
-
- self.race_movetime_frac += frametime;
- f = floor(self.race_movetime_frac);
- self.race_movetime_frac -= f;
- self.race_movetime_count += f;
- self.race_movetime = self.race_movetime_frac + self.race_movetime_count;
-
- anticheat_physics();
-
- buttons = self.BUTTON_ATCK + 2 * self.BUTTON_JUMP + 4 * self.BUTTON_ATCK2 + 8 * self.BUTTON_ZOOM + 16 * self.BUTTON_CROUCH + 32 * self.BUTTON_HOOK + 64 * self.BUTTON_USE + 128 * (self.movement.x < 0) + 256 * (self.movement.x > 0) + 512 * (self.movement.y < 0) + 1024 * (self.movement.y > 0);
-
- if(!buttons)
- c = "x";
- else if(buttons == 1)
- c = "1";
- else if(buttons == 2)
- c = " ";
- else if(buttons == 128)
- c = "s";
- else if(buttons == 256)
- c = "w";
- else if(buttons == 512)
- c = "a";
- else if(buttons == 1024)
- c = "d";
- else
- c = "?";
-
- if(c == substring(specialcommand, self.specialcommand_pos, 1))
- {
- self.specialcommand_pos += 1;
- if(self.specialcommand_pos >= strlen(specialcommand))
- {
- self.specialcommand_pos = 0;
- SpecialCommand();
- return;
- }
- }
- else if(self.specialcommand_pos && (c != substring(specialcommand, self.specialcommand_pos - 1, 1)))
- self.specialcommand_pos = 0;
-
- if(sv_maxidle > 0)
- {
- if(buttons != self.buttons_old || self.movement != self.movement_old || self.v_angle != self.v_angle_old)
- self.parm_idlesince = time;
- }
- buttons_prev = self.buttons_old;
- self.buttons_old = buttons;
- self.movement_old = self.movement;
- self.v_angle_old = self.v_angle;
-
- if(time < self.nickspamtime)
- if(self.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
- {
- // slight annoyance for nick change scripts
- self.movement = -1 * self.movement;
- self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = self.BUTTON_ZOOM = self.BUTTON_CROUCH = self.BUTTON_HOOK = self.BUTTON_USE = 0;
-
- if(self.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
- {
- self.angles_x = random() * 360;
- self.angles_y = random() * 360;
- // at least I'm not forcing retardedview by also assigning to angles_z
- self.fixangle = true;
- }
- }
-
- if (self.punchangle != '0 0 0')
- {
- f = vlen(self.punchangle) - 10 * frametime;
- if (f > 0)
- self.punchangle = normalize(self.punchangle) * f;
- else
- self.punchangle = '0 0 0';
- }
-
- if (self.punchvector != '0 0 0')
- {
- f = vlen(self.punchvector) - 30 * frametime;
- if (f > 0)
- self.punchvector = normalize(self.punchvector) * f;
- else
- self.punchvector = '0 0 0';
- }
-
- if (IS_BOT_CLIENT(self))
- {
- if(playerdemo_read())
- return;
- bot_think();
- }
-
- if(IS_PLAYER(self))
- {
- if(self.race_penalty)
- if(time > self.race_penalty)
- self.race_penalty = 0;
-
- not_allowed_to_move = 0;
- if(self.race_penalty)
- not_allowed_to_move = 1;
- if(time < game_starttime)
- not_allowed_to_move = 1;
-
- if(not_allowed_to_move)
- {
- self.velocity = '0 0 0';
- self.movetype = MOVETYPE_NONE;
- self.disableclientprediction = 2;
- }
- else if(self.disableclientprediction == 2)
- {
- if(self.movetype == MOVETYPE_NONE)
- self.movetype = MOVETYPE_WALK;
- self.disableclientprediction = 0;
- }
- }
-
- if (self.movetype == MOVETYPE_NONE)
- return;
-
- // when we get here, disableclientprediction cannot be 2
- self.disableclientprediction = 0;
- if(time < self.ladder_time)
- self.disableclientprediction = 1;
-
- if(time < self.spider_slowness)
- {
- self.stat_sv_maxspeed *= 0.5; // half speed while slow from spider
- self.stat_sv_airspeedlimit_nonqw *= 0.5;
- }
-
- if(self.frozen)
- {
- if(autocvar_sv_dodging_frozen && IS_REAL_CLIENT(self))
- {
- self.movement_x = bound(-5, self.movement.x, 5);
- self.movement_y = bound(-5, self.movement.y, 5);
- self.movement_z = bound(-5, self.movement.z, 5);
- }
- else
- self.movement = '0 0 0';
- self.disableclientprediction = 1;
-
- vector midpoint = ((self.absmin + self.absmax) * 0.5);
- if(pointcontents(midpoint) == CONTENT_WATER)
- {
- self.velocity = self.velocity * 0.5;
-
- if(pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
- { self.velocity_z = 200; }
- }
- }
-
- MUTATOR_CALLHOOK(PlayerPhysics);
-
- if(self.player_blocked)
- {
- self.movement = '0 0 0';
- self.disableclientprediction = 1;
- }
-
- maxspd_mod = 1;
-
- swampspd_mod = 1;
- if(self.in_swamp) {
- swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
- }
-
- // conveyors: first fix velocity
- if(self.conveyor.state)
- self.velocity -= self.conveyor.movedir;
-
- if (!IS_PLAYER(self))
- {
- maxspd_mod = autocvar_sv_spectator_speed_multiplier;
- if(!self.spectatorspeed)
- self.spectatorspeed = maxspd_mod;
- if(self.impulse && self.impulse <= 19 || (self.impulse >= 200 && self.impulse <= 209) || (self.impulse >= 220 && self.impulse <= 229))
- {
- if(self.lastclassname != "player")
- {
- if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209))
- self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
- else if(self.impulse == 11)
- self.spectatorspeed = maxspd_mod;
- else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || (self.impulse >= 220 && self.impulse <= 229))
- self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
- else if(self.impulse >= 1 && self.impulse <= 9)
- self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
- } // otherwise just clear
- self.impulse = 0;
- }
- maxspd_mod = self.spectatorspeed;
- }
-
- spd = max(self.stat_sv_maxspeed, autocvar_sv_maxairspeed) * maxspd_mod * swampspd_mod;
- if(self.speed != spd)
- {
- self.speed = spd;
- temps = ftos(spd);
- stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
- stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
- }
-
- maxspd_mod *= swampspd_mod; // only one common speed modder please!
- swampspd_mod = 1;
-
- // if dead, behave differently
- if (self.deadflag)
- goto end;
-
- if (!self.fixangle && !g_bugrigs)
- {
- self.angles_x = 0;
- self.angles_y = self.v_angle.y;
- self.angles_z = 0;
- }
-
- if(self.flags & FL_ONGROUND)
- if(IS_PLAYER(self)) // no fall sounds for observers thank you very much
- if(self.wasFlying)
- {
- self.wasFlying = 0;
-
- if(self.waterlevel < WATERLEVEL_SWIMMING)
- if(time >= self.ladder_time)
- if (!self.hook)
- {
- self.nextstep = time + 0.3 + random() * 0.1;
- trace_dphitq3surfaceflags = 0;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
- if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
- {
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
- GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- else
- GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- }
- }
- }
-
- if(IsFlying(self))
- self.wasFlying = 1;
-
- if(IS_PLAYER(self))
- CheckPlayerJump();
-
- if (self.flags & FL_WATERJUMP )
- {
- self.velocity_x = self.movedir.x;
- self.velocity_y = self.movedir.y;
- if (time > self.teleport_time || self.waterlevel == WATERLEVEL_NONE)
- {
- self.flags &= ~FL_WATERJUMP;
- self.teleport_time = 0;
- }
- }
- else if (g_bugrigs && IS_PLAYER(self))
- {
- RaceCarPhysics();
- }
- else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY)
- {
- // noclipping or flying
- self.flags &= ~FL_ONGROUND;
-
- self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
- wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
- // acceleration
- wishdir = normalize(wishvel);
- wishspeed = vlen(wishvel);
- if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
- wishspeed = self.stat_sv_maxspeed*maxspd_mod;
- if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
- }
- else if (self.waterlevel >= WATERLEVEL_SWIMMING)
- {
- // swimming
- self.flags &= ~FL_ONGROUND;
-
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
- wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
- if (wishvel == '0 0 0')
- wishvel = '0 0 -60'; // drift towards bottom
-
- wishdir = normalize(wishvel);
- wishspeed = vlen(wishvel);
- if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
- wishspeed = self.stat_sv_maxspeed*maxspd_mod;
- wishspeed = wishspeed * 0.7;
-
- // water friction
- self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
-
- // water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
- }
- else if (time < self.ladder_time)
- {
- // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
- self.flags &= ~FL_ONGROUND;
-
- float g;
- g = autocvar_sv_gravity * frametime;
- if(self.gravity)
- g *= self.gravity;
- if(autocvar_sv_gameplayfix_gravityunaffectedbyticrate)
- {
- g *= 0.5;
- self.velocity_z += g;
- }
-
- self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
- wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
- self.velocity_z += g;
- if (self.ladder_entity.classname == "func_water")
- {
- f = vlen(wishvel);
- if (f > self.ladder_entity.speed)
- wishvel = wishvel * (self.ladder_entity.speed / f);
-
- self.watertype = self.ladder_entity.skin;
- f = self.ladder_entity.origin.z + self.ladder_entity.maxs.z;
- if ((self.origin.z + self.view_ofs.z) < f)
- self.waterlevel = WATERLEVEL_SUBMERGED;
- else if ((self.origin.z + (self.mins.z + self.maxs.z) * 0.5) < f)
- self.waterlevel = WATERLEVEL_SWIMMING;
- else if ((self.origin.z + self.mins.z + 1) < f)
- self.waterlevel = WATERLEVEL_WETFEET;
- else
- {
- self.waterlevel = WATERLEVEL_NONE;
- self.watertype = CONTENT_EMPTY;
- }
- }
- // acceleration
- wishdir = normalize(wishvel);
- wishspeed = vlen(wishvel);
- if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
- wishspeed = self.stat_sv_maxspeed*maxspd_mod;
- if (time >= self.teleport_time)
- {
- // water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
- }
- }
- else if (self.items & IT_USING_JETPACK)
- {
- //makevectors(self.v_angle_y * '0 1 0');
- makevectors(self.v_angle);
- wishvel = v_forward * self.movement.x + v_right * self.movement.y;
- // add remaining speed as Z component
- maxairspd = autocvar_sv_maxairspeed*max(1, maxspd_mod);
- // fix speedhacks :P
- wishvel = normalize(wishvel) * min(vlen(wishvel) / maxairspd, 1);
- // add the unused velocity as up component
- wishvel.z = 0;
-
- // if(self.BUTTON_JUMP)
- wishvel.z = sqrt(max(0, 1 - wishvel * wishvel));
-
- // it is now normalized, so...
- float a_side, a_up, a_add, a_diff;
- a_side = autocvar_g_jetpack_acceleration_side;
- a_up = autocvar_g_jetpack_acceleration_up;
- a_add = autocvar_g_jetpack_antigravity * autocvar_sv_gravity;
-
- wishvel.x *= a_side;
- wishvel.y *= a_side;
- wishvel.z *= a_up;
- wishvel.z += a_add;
-
- float best;
- best = 0;
- //////////////////////////////////////////////////////////////////////////////////////
- // finding the maximum over all vectors of above form
- // with wishvel having an absolute value of 1
- //////////////////////////////////////////////////////////////////////////////////////
- // we're finding the maximum over
- // f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
- // for z in the range from -1 to 1
- //////////////////////////////////////////////////////////////////////////////////////
- // maximum is EITHER attained at the single extreme point:
- a_diff = a_side * a_side - a_up * a_up;
- if(a_diff != 0)
- {
- f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
- if(f > -1 && f < 1) // can it be attained?
- {
- best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
- //print("middle\n");
- }
- }
- // OR attained at z = 1:
- f = (a_up + a_add) * (a_up + a_add);
- if(f > best)
- {
- best = f;
- //print("top\n");
- }
- // OR attained at z = -1:
- f = (a_up - a_add) * (a_up - a_add);
- if(f > best)
- {
- best = f;
- //print("bottom\n");
- }
- best = sqrt(best);
- //////////////////////////////////////////////////////////////////////////////////////
-
- //print("best possible acceleration: ", ftos(best), "\n");
-
- float fxy, fz;
- fxy = bound(0, 1 - (self.velocity * normalize(wishvel.x * '1 0 0' + wishvel.y * '0 1 0')) / autocvar_g_jetpack_maxspeed_side, 1);
- if(wishvel.z - autocvar_sv_gravity > 0)
- fz = bound(0, 1 - self.velocity.z / autocvar_g_jetpack_maxspeed_up, 1);
- else
- fz = bound(0, 1 + self.velocity.z / autocvar_g_jetpack_maxspeed_up, 1);
-
- wishvel.x *= fxy;
- wishvel.y *= fxy;
- wishvel.z = (wishvel.z - autocvar_sv_gravity) * fz + autocvar_sv_gravity;
-
- float fvel;
- fvel = min(1, vlen(wishvel) / best);
- if(autocvar_g_jetpack_fuel && !(self.items & IT_UNLIMITED_WEAPON_AMMO))
- f = min(1, self.ammo_fuel / (autocvar_g_jetpack_fuel * frametime * fvel));
- else
- f = 1;
-
- //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
-
- if (f > 0 && wishvel != '0 0 0')
- {
- self.velocity = self.velocity + wishvel * f * frametime;
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
- self.ammo_fuel -= autocvar_g_jetpack_fuel * frametime * fvel * f;
- self.flags &= ~FL_ONGROUND;
- self.items |= IT_USING_JETPACK;
-
- // jetpack also inhibits health regeneration, but only for 1 second
- self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
- }
- }
- else if (self.flags & FL_ONGROUND)
- {
- // we get here if we ran out of ammo
- if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-
- // walking
- makevectors(self.v_angle.y * '0 1 0');
- wishvel = v_forward * self.movement.x + v_right * self.movement.y;
-
- if(!(self.lastflags & FL_ONGROUND))
- {
- if(autocvar_speedmeter)
- dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
- if(self.lastground < time - 0.3)
- self.velocity = self.velocity * (1 - autocvar_sv_friction_on_land);
- if(self.jumppadcount > 1)
- dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
- self.jumppadcount = 0;
- }
-
- v = self.velocity;
- v.z = 0;
- f = vlen(v);
- if(f > 0)
- {
- if (f < autocvar_sv_stopspeed)
- f = 1 - frametime * (autocvar_sv_stopspeed / f) * autocvar_sv_friction;
- else
- f = 1 - frametime * autocvar_sv_friction;
- if (f > 0)
- self.velocity = self.velocity * f;
- else
- self.velocity = '0 0 0';
- /*
- Mathematical analysis time!
-
- Our goal is to invert this mess.
-
- For the two cases we get:
- v = v0 * (1 - frametime * (autocvar_sv_stopspeed / v0) * autocvar_sv_friction)
- = v0 - frametime * autocvar_sv_stopspeed * autocvar_sv_friction
- v0 = v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction
- and
- v = v0 * (1 - frametime * autocvar_sv_friction)
- v0 = v / (1 - frametime * autocvar_sv_friction)
-
- These cases would be chosen ONLY if:
- v0 < autocvar_sv_stopspeed
- v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction < autocvar_sv_stopspeed
- v < autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction)
- and, respectively:
- v0 >= autocvar_sv_stopspeed
- v / (1 - frametime * autocvar_sv_friction) >= autocvar_sv_stopspeed
- v >= autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction)
- */
- }
-
- // acceleration
- wishdir = normalize(wishvel);
- wishspeed = vlen(wishvel);
- if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
- wishspeed = self.stat_sv_maxspeed*maxspd_mod;
- if (self.crouch)
- wishspeed = wishspeed * 0.5;
- if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
- }
- else
- {
- float wishspeed0;
- // we get here if we ran out of ammo
- if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-
- if(maxspd_mod < 1)
- {
- maxairspd = autocvar_sv_maxairspeed*maxspd_mod;
- airaccel = autocvar_sv_airaccelerate*maxspd_mod;
- }
- else
- {
- maxairspd = autocvar_sv_maxairspeed;
- airaccel = autocvar_sv_airaccelerate;
- }
- // airborn
- makevectors(self.v_angle.y * '0 1 0');
- wishvel = v_forward * self.movement.x + v_right * self.movement.y;
- // acceleration
- wishdir = normalize(wishvel);
- wishspeed = wishspeed0 = vlen(wishvel);
- if (wishspeed0 > self.stat_sv_maxspeed*maxspd_mod)
- wishspeed0 = self.stat_sv_maxspeed*maxspd_mod;
- if (wishspeed > maxairspd)
- wishspeed = maxairspd;
- if (self.crouch)
- wishspeed = wishspeed * 0.5;
- if (time >= self.teleport_time)
- {
- float accelerating;
- float wishspeed2;
- float airaccelqw;
- float strafity;
-
- airaccelqw = self.stat_sv_airaccel_qw;
- accelerating = (self.velocity * wishdir > 0);
- wishspeed2 = wishspeed;
-
- // CPM
- if(autocvar_sv_airstopaccelerate)
- {
- vector curdir;
- curdir = self.velocity;
- curdir.z = 0;
- curdir = normalize(curdir);
- airaccel = airaccel + (autocvar_sv_airstopaccelerate*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
- }
- // note that for straight forward jumping:
- // step = accel * frametime * wishspeed0;
- // accel = bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
- // -->
- // dv/dt = accel * maxspeed (when slow)
- // dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
- // log dv/dt = logaccel + logmaxspeed (when slow)
- // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
- strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
- if(autocvar_sv_maxairstrafespeed)
- wishspeed = min(wishspeed, GeomLerp(autocvar_sv_maxairspeed*maxspd_mod, strafity, autocvar_sv_maxairstrafespeed*maxspd_mod));
- if(autocvar_sv_airstrafeaccelerate)
- airaccel = GeomLerp(airaccel, strafity, autocvar_sv_airstrafeaccelerate*maxspd_mod);
- if(self.stat_sv_airstrafeaccel_qw)
- airaccelqw = copysign(1-GeomLerp(1-fabs(self.stat_sv_airaccel_qw), strafity, 1-fabs(self.stat_sv_airstrafeaccel_qw)), ((strafity > 0.5) ? self.stat_sv_airstrafeaccel_qw : self.stat_sv_airaccel_qw));
- // !CPM
-
- if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement.x != 0)
- PM_AirAccelerate(wishdir, wishspeed);
- else
- PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw);
-
- if(autocvar_sv_aircontrol)
- CPM_PM_Aircontrol(wishdir, wishspeed2);
- }
- }
-
- if((g_cts || g_race) && !IS_OBSERVER(self))
- {
- if(vlen(self.velocity - self.velocity.z * '0 0 1') > speedaward_speed)
- {
- speedaward_speed = vlen(self.velocity - self.velocity.z * '0 0 1');
- speedaward_holder = self.netname;
- speedaward_uid = self.crypto_idfp;
- speedaward_lastupdate = time;
- }
- if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
- {
- string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
- race_send_speedaward(MSG_ALL);
- speedaward_lastsent = speedaward_speed;
- if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
- {
- speedaward_alltimebest = speedaward_speed;
- speedaward_alltimebest_holder = speedaward_holder;
- speedaward_alltimebest_uid = speedaward_uid;
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest));
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid);
- race_send_speedaward_alltimebest(MSG_ALL);
- }
- }
- }
-
- // WEAPONTODO
- float xyspeed;
- xyspeed = vlen('1 0 0' * self.velocity.x + '0 1 0' * self.velocity.y);
- if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
- {
- // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
- xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
- f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
- // add the extra charge
- self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * frametime);
- }
-:end
- if(self.flags & FL_ONGROUND)
- self.lastground = time;
-
- // conveyors: then break velocity again
- if(self.conveyor.state)
- self.velocity += self.conveyor.movedir;
-
- self.lastflags = self.flags;
- self.lastclassname = self.classname;
-}
}
}
+void ClientCommand_physics(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string command = strtolower(argv(1));
+
+ if(!autocvar_g_physics_clientselect)
+ {
+ sprint(self, "Client physics selection is currently disabled.\n");
+ return;
+ }
+
+ if(command == "list" || command == "help")
+ {
+ sprint(self, strcat("Available physics sets: \n\n", autocvar_g_physics_clientselect_options, " default\n"));
+ return;
+ }
+
+ if(Physics_Valid(command) || command == "default")
+ {
+ stuffcmd(self, strcat("\nseta cl_physics ", command, "\nsendcvar cl_physics\n"));
+ sprint(self, strcat("^2Physics set successfully changed to ^3", command, "\n"));
+ return;
+ }
+ }
+
+ default:
+ sprint(self, strcat("Current physics set: ^3", self.cvar_cl_physics, "\n"));
+ case CMD_REQUEST_USAGE:
+ {
+ sprint(self, "\nUsage:^3 cmd physics <physics>\n");
+ sprint(self, " See 'cmd physics list' for available physics sets.\n");
+ sprint(self, " Argument 'default' resets to standard physics.\n");
+ return;
+ }
+ }
+}
+
void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness
{
switch(request)
CLIENT_COMMAND("mobedit", ClientCommand_mobedit(request, arguments), "Edit your monster's properties") \
CLIENT_COMMAND("mobkill", ClientCommand_mobkill(request), "Kills your monster") \
CLIENT_COMMAND("mobspawn", ClientCommand_mobspawn(request, arguments), "Spawn monsters infront of yourself") \
+ CLIENT_COMMAND("physics", ClientCommand_physics(request, arguments), "Change physics set") \
CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
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") \
// count the total amount of players and total amount of teams
t_players = 0;
t_teams = 0;
- FOR_EACH_PLAYER(tmp_player)
+ FOR_EACH_CLIENT(tmp_player)
+ if(IS_PLAYER(tmp_player) || tmp_player.caplayer)
{
CheckAllowedTeams(tmp_player);
}
// build a list of the players in a random order
- FOR_EACH_PLAYER(tmp_player)
+ FOR_EACH_CLIENT(tmp_player)
+ if(IS_PLAYER(tmp_player) || tmp_player.caplayer)
{
for (;;)
{
//.string map;
//.float worldtype;
+// Needed for dynamic clientwalls
+.float inactive; // Clientwall disappears when inactive
+.float alpha_max, alpha_min;
+.float fade_start, fade_end, fade_vertical_offset;
+.float default_solid; // Variable to store default self.solid for clientwalls
.float pain_finished; //Added by Supajoe
.float pain_frame; //"
.float elos;
.float ranks;
+.string cvar_cl_physics;
+
.float init_for_player_needed;
.void(entity) init_for_player;
void g_clientmodel_setcolormaptoactivator (void)
{
g_model_setcolormaptoactivator();
- self.SendFlags |= 1;
+ self.SendFlags |= (8 | 1);
+}
+
+void g_clientmodel_use(void)
+{
+ if (self.antiwall_flag == 1)
+ {
+ self.inactive = 1;
+ self.solid = SOLID_NOT;
+ }
+ else if (self.antiwall_flag == 2)
+ {
+ self.inactive = 0;
+ self.solid = self.default_solid;
+ }
+ g_clientmodel_setcolormaptoactivator();
}
void g_model_dropbyspawnflags()
sf = sf & 0x0F;
if(self.angles != '0 0 0')
sf |= 0x10;
- if(self.solid && (self.mins != '0 0 0' || self.maxs != '0 0 0'))
+ if(self.mins != '0 0 0' || self.maxs != '0 0 0')
sf |= 0x20;
if(self.colormap != 0)
sf |= 0x40;
WriteCoord(MSG_ENTITY, self.movedir.z);
WriteByte(MSG_ENTITY, floor(self.lip * 255));
}
+ WriteShort(MSG_ENTITY, self.fade_start);
+ WriteShort(MSG_ENTITY, self.fade_end);
+ WriteShort(MSG_ENTITY, self.alpha_max);
+ WriteShort(MSG_ENTITY, self.alpha_min);
+ WriteShort(MSG_ENTITY, self.inactive);
+ WriteShort(MSG_ENTITY, self.fade_vertical_offset);
}
return true;
if(self.geomtype) if(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) self.movetype = MOVETYPE_PHYSICS; \
if(!self.scale) self.scale = self.modelscale; \
SetBrushEntityModel(); \
- self.use = g_clientmodel_setcolormaptoactivator; \
+ self.use = g_clientmodel_use; \
InitializeEntity(self, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
if(!self.solid) self.solid = (sol); else if(self.solid < 0) self.solid = SOLID_NOT; \
if(!self.bgmscriptsustain) self.bgmscriptsustain = 1; else if(self.bgmscriptsustain < 0) self.bgmscriptsustain = 0; \
- Net_LinkEntity(self, true, 0, g_clientmodel_genericsendentity);
+ Net_LinkEntity(self, true, 0, g_clientmodel_genericsendentity); \
+ self.default_solid = sol;
// non-solid model entities:
void spawnfunc_misc_gamemodel() { self.angles_x = -self.angles.x; G_MODEL_INIT (SOLID_NOT) } // model entity
BADCVAR("g_domination_default_teams");
BADCVAR("g_freezetag");
BADCVAR("g_freezetag_teams");
+ BADCVAR("g_invasion_teams");
BADCVAR("g_keepaway");
BADCVAR("g_keyhunt");
BADCVAR("g_keyhunt_teams");
BADCVAR("g_ca_teams_override");
BADCVAR("g_ctf_ignore_frags");
BADCVAR("g_domination_point_limit");
+ BADCVAR("g_domination_teams_override");
BADCVAR("g_freezetag_teams_override");
BADCVAR("g_friendlyfire");
BADCVAR("g_fullbrightitems");
BADCVAR("g_nexball_goallimit");
BADCVAR("g_powerups");
BADCVAR("g_start_delay");
+ BADCVAR("g_tdm_teams_override");
BADCVAR("g_warmup");
BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
BADCVAR("hostname");
// physics
Physics_AddStats();
+ // new properties
+ addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
+ addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
+ addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
+ addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
+ addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
+ addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
+ addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
+ addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
+ addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
+ addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
+ addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
+ addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
+ addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
+ addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
+ addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
+
// secrets
addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
#include "../common/playerstats.qh"
#include "../common/util.qh"
-float GameTypeVote_AvailabilityStatus(string gtname)
+
+// definitions
+
+float mapvote_nextthink;
+float mapvote_keeptwotime;
+float mapvote_timeout;
+string mapvote_message;
+const float MAPVOTE_SCREENSHOT_DIRS_COUNT = 4;
+string mapvote_screenshot_dirs[MAPVOTE_SCREENSHOT_DIRS_COUNT];
+float mapvote_screenshot_dirs_count;
+
+float mapvote_count;
+float mapvote_count_real;
+string mapvote_maps[MAPVOTE_COUNT];
+float mapvote_maps_screenshot_dir[MAPVOTE_COUNT];
+string mapvote_maps_pakfile[MAPVOTE_COUNT];
+float mapvote_maps_suggested[MAPVOTE_COUNT];
+string mapvote_suggestions[MAPVOTE_COUNT];
+float mapvote_suggestion_ptr;
+float mapvote_voters;
+float mapvote_selections[MAPVOTE_COUNT];
+float mapvote_maps_flags[MAPVOTE_COUNT];
+float mapvote_run;
+float mapvote_detail;
+float mapvote_abstain;
+.float mapvote;
+
+entity mapvote_ent;
+
+/**
+ * Returns the gamtype ID from its name, if type_name isn't a real gametype it
+ * checks for sv_vote_gametype_(type_name)_type
+ */
+float GameTypeVote_Type_FromString(string type_name)
+{
+ float type = MapInfo_Type_FromString(type_name);
+ if ( type == 0 )
+ type = MapInfo_Type_FromString(cvar_string(
+ strcat("sv_vote_gametype_",type_name,"_type")));
+ return type;
+}
+
+int GameTypeVote_AvailabilityStatus(string type_name)
{
- float type = MapInfo_Type_FromString(gtname);
+ int flag = GTV_FORBIDDEN;
+
+ float type = MapInfo_Type_FromString(type_name);
+ if ( type == 0 )
+ {
+ type = MapInfo_Type_FromString(cvar_string(
+ strcat("sv_vote_gametype_",type_name,"_type")));
+ flag |= GTV_CUSTOM;
+ }
+
if( type == 0 )
- return GTV_FORBIDDEN;
+ return flag;
if ( autocvar_nextmap != "" )
{
if ( !MapInfo_Get_ByName(autocvar_nextmap, false, 0) )
- return GTV_FORBIDDEN;
+ return flag;
if (!(MapInfo_Map_supportedGametypes & type))
- return GTV_FORBIDDEN;
+ return flag;
}
- return GTV_AVAILABLE;
+ return flag | GTV_AVAILABLE;
}
float GameTypeVote_GetMask()
n = min(MAPVOTE_COUNT, n);
gametype_mask = 0;
for(j = 0; j < n; ++j)
- gametype_mask |= MapInfo_Type_FromString(argv(j));
+ gametype_mask |= GameTypeVote_Type_FromString(argv(j));
return gametype_mask;
}
mapvote_maps_screenshot_dir[mapvote_count] = i;
mapvote_maps_pakfile[mapvote_count] = strzone(pakfile);
- mapvote_maps_availability[mapvote_count] = GTV_AVAILABLE;
+ mapvote_maps_flags[mapvote_count] = GTV_AVAILABLE;
mapvote_count += 1;
}
float mask,power;
mask = 0;
for(i = 0, power = 1; i < mapvote_count; ++i, power *= 2)
- if(mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if(mapvote_maps_flags[i] & GTV_AVAILABLE )
mask |= power;
if(mapvote_count < 8)
else
{
for ( i = 0; i < mapvote_count; ++i )
- WriteByte(MSG_ENTITY, mapvote_maps_availability[i]);
+ WriteByte(MSG_ENTITY, mapvote_maps_flags[i]);
+ }
+}
+
+/*
+ * Sends a single map vote option to the client
+ */
+void MapVote_SendOption(int i)
+{
+ // abstain
+ if(mapvote_abstain && i == mapvote_count - 1)
+ {
+ WriteString(MSG_ENTITY, ""); // abstain needs no text
+ WriteString(MSG_ENTITY, ""); // abstain needs no pack
+ WriteByte(MSG_ENTITY, 0); // abstain needs no screenshot dir
+ }
+ else
+ {
+ WriteString(MSG_ENTITY, mapvote_maps[i]);
+ WriteString(MSG_ENTITY, mapvote_maps_pakfile[i]);
+ WriteByte(MSG_ENTITY, mapvote_maps_screenshot_dir[i]);
+ }
+}
+
+/*
+ * Sends a single gametype vote option to the client
+ */
+void GameTypeVote_SendOption(int i)
+{
+ // abstain
+ if(mapvote_abstain && i == mapvote_count - 1)
+ {
+ WriteString(MSG_ENTITY, ""); // abstain needs no text
+ WriteByte(MSG_ENTITY, GTV_AVAILABLE);
+ }
+ else
+ {
+ string type_name = mapvote_maps[i];
+ WriteString(MSG_ENTITY, type_name);
+ WriteByte(MSG_ENTITY, mapvote_maps_flags[i]);
+ if ( mapvote_maps_flags[i] & GTV_CUSTOM )
+ {
+ WriteString(MSG_ENTITY, cvar_string(
+ strcat("sv_vote_gametype_",type_name,"_name")));
+ WriteString(MSG_ENTITY, cvar_string(
+ strcat("sv_vote_gametype_",type_name,"_description")));
+ }
}
}
}
else if ( autocvar_sv_vote_gametype )
{
- // map vote but gametype has been chosen via voting screen
+ // map vote but gametype has been chosen via voting screen
WriteByte(MSG_ENTITY, 2);
WriteString(MSG_ENTITY, MapInfo_Type_ToText(MapInfo_CurrentGametype()));
}
MapVote_WriteMask();
+ // Send data for the vote options
for(i = 0; i < mapvote_count; ++i)
{
- if(mapvote_abstain && i == mapvote_count - 1)
- {
- WriteString(MSG_ENTITY, ""); // abstain needs no text
- WriteString(MSG_ENTITY, ""); // abstain needs no pack
- WriteByte(MSG_ENTITY, 0); // abstain needs no screenshot dir
- WriteByte(MSG_ENTITY, GTV_AVAILABLE);
- }
+ if(gametypevote)
+ GameTypeVote_SendOption(i);
else
- {
- WriteString(MSG_ENTITY, mapvote_maps[i]);
- WriteString(MSG_ENTITY, mapvote_maps_pakfile[i]);
- WriteByte(MSG_ENTITY, mapvote_maps_screenshot_dir[i]);
- WriteByte(MSG_ENTITY, mapvote_maps_availability[i]);
- }
+ MapVote_SendOption(i);
}
}
{
if(mapvote_detail)
for(i = 0; i < mapvote_count; ++i)
- if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
WriteByte(MSG_ENTITY, mapvote_selections[i]);
WriteByte(MSG_ENTITY, to.mapvote);
result = strcat(result, ":", ftos(mapvote_selections[mappos]), "::");
didntvote = mapvote_voters;
for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if(mapvote_maps_flags[i] & GTV_AVAILABLE )
{
didntvote -= mapvote_selections[i];
if(i != mappos)
float i;
for(i = 0; i < mapvote_count; ++i)
- if( mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if( mapvote_maps_flags[i] & GTV_AVAILABLE )
{
//dprint("Map ", ftos(i), ": "); dprint(mapvote_maps[i], "\n");
mapvote_selections[i] = 0;
currentPlace = 0;
currentVotes = -1;
for(i = 0; i < mapvote_count_real; ++i)
- if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
{
RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
if ( gametypevote && mapvote_maps[i] == MapInfo_Type_ToString(MapInfo_CurrentGametype()) )
RandomSelection_Init();
for(i = 0; i < mapvote_count_real; ++i)
if(i != firstPlace)
- if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+ if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
secondPlace = RandomSelection_chosen_float;
secondPlaceVotes = RandomSelection_best_priority;
result = strcat(result, ":", ftos(mapvote_selections[i]));
if(i < mapvote_count_real)
{
- mapvote_maps_availability[i] = GTV_FORBIDDEN;
+ mapvote_maps_flags[i] &= ~GTV_AVAILABLE;
}
}
}
}
// clear possibly invalid votes
- if ( mapvote_maps_availability[other.mapvote-1] != GTV_AVAILABLE )
+ if ( !(mapvote_maps_flags[other.mapvote-1] & GTV_AVAILABLE) )
other.mapvote = 0;
// use impulses as new vote
if(other.impulse >= 1 && other.impulse <= mapvote_count)
- if( mapvote_maps_availability[other.impulse - 1] == GTV_AVAILABLE )
+ if( mapvote_maps_flags[other.impulse - 1] & GTV_AVAILABLE )
{
other.mapvote = other.impulse;
MapVote_TouchVotes(other);
if(!gametypevote || gametypevote_finished)
return false;
- if ( !GameTypeVote_SetGametype(MapInfo_Type_FromString(mapvote_maps[pos])) )
+ if ( !GameTypeVote_SetGametype(GameTypeVote_Type_FromString(mapvote_maps[pos])) )
{
dprint("Selected gametype is not supported by any map");
}
float GameTypeVote_AddVotable(string nextMode)
{
float j;
- if ( nextMode == "" || MapInfo_Type_FromString(nextMode) == 0 )
+ if ( nextMode == "" || GameTypeVote_Type_FromString(nextMode) == 0 )
return false;
for(j = 0; j < mapvote_count; ++j)
if(mapvote_maps[j] == nextMode)
mapvote_maps_screenshot_dir[mapvote_count] = 0;
mapvote_maps_pakfile[mapvote_count] = strzone("");
- mapvote_maps_availability[mapvote_count] = GameTypeVote_AvailabilityStatus(nextMode);
+ mapvote_maps_flags[mapvote_count] = GameTypeVote_AvailabilityStatus(nextMode);
mapvote_count += 1;
for(j = 0; j < n; ++j)
{
if ( GameTypeVote_AddVotable(argv(j)) )
- if ( mapvote_maps_availability[j] == GTV_AVAILABLE )
+ if ( mapvote_maps_flags[j] & GTV_AVAILABLE )
{
really_available++;
which_available = j;
#ifndef MAPVOTING_H
#define MAPVOTING_H
-#include "../common/constants.qh"
-
// definitions for functions used outside mapvoting.qc
void MapVote_Start();
void MapVote_Spawn();
float GameTypeVote_Finished(float pos);
string GameTypeVote_MapInfo_FixName(string m);
-// definitions
float gametypevote;
string getmapname_stored;
float mapvote_initialized;
-
-float mapvote_nextthink;
-float mapvote_keeptwotime;
-float mapvote_timeout;
-string mapvote_message;
-const float MAPVOTE_SCREENSHOT_DIRS_COUNT = 4;
-string mapvote_screenshot_dirs[MAPVOTE_SCREENSHOT_DIRS_COUNT];
-float mapvote_screenshot_dirs_count;
-
-float mapvote_count;
-float mapvote_count_real;
-string mapvote_maps[MAPVOTE_COUNT];
-float mapvote_maps_screenshot_dir[MAPVOTE_COUNT];
-string mapvote_maps_pakfile[MAPVOTE_COUNT];
-float mapvote_maps_suggested[MAPVOTE_COUNT];
-string mapvote_suggestions[MAPVOTE_COUNT];
-float mapvote_suggestion_ptr;
-float mapvote_voters;
-float mapvote_selections[MAPVOTE_COUNT];
-float mapvote_maps_availability[MAPVOTE_COUNT];
-float mapvote_run;
-float mapvote_detail;
-float mapvote_abstain;
-.float mapvote;
-
-entity mapvote_ent;
#endif
GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
+ GetCvars_handleString(s, f, cvar_cl_physics, "cl_physics");
GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
GetCvars_handleFloat(s, f, cvar_cl_clippedspectating, "cl_clippedspectating");
GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
s = cvar_string("g_weaponarena");
if (s == "0" || s == "")
{
- if(g_ca)
+ if(g_ca || g_freezetag)
s = "most";
}
warmup_start_weapons_default = start_weapons_default;
warmup_start_weapons_defaultmask = start_weapons_defaultmask;
- if (!g_weaponarena && !g_ca)
+ if (!g_weaponarena && !g_ca && !g_freezetag)
{
warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
#else
string cvar_string_normal(string n)
{
- if (!(cvar_type(n) & 1))
+ if (!(cvar_type(n) & CVAR_TYPEFLAG_EXISTS))
backtrace(strcat("Attempt to access undefined cvar: ", n));
return builtin_cvar_string(n);
}
return 1;
}
+MUTATOR_HOOKFUNCTION(freezetag_SetStartItems)
+{
+ start_items &= ~IT_UNLIMITED_AMMO;
+ //start_health = warmup_start_health = cvar("g_lms_start_health");
+ //start_armorvalue = warmup_start_armorvalue = cvar("g_lms_start_armor");
+ start_ammo_shells = warmup_start_ammo_shells = cvar("g_lms_start_ammo_shells");
+ start_ammo_nails = warmup_start_ammo_nails = cvar("g_lms_start_ammo_nails");
+ start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
+ start_ammo_cells = warmup_start_ammo_cells = cvar("g_lms_start_ammo_cells");
+ start_ammo_plasma = warmup_start_ammo_plasma = cvar("g_lms_start_ammo_plasma");
+ start_ammo_fuel = warmup_start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
+
+ return 0;
+}
+
MUTATOR_HOOKFUNCTION(freezetag_BotRoles)
{
if (!self.deadflag)
MUTATOR_HOOK(reset_map_players, freezetag_reset_map_players, CBC_ORDER_ANY);
MUTATOR_HOOK(GiveFragsForKill, freezetag_GiveFragsForKill, CBC_ORDER_FIRST);
MUTATOR_HOOK(PlayerPreThink, freezetag_PlayerPreThink, CBC_ORDER_FIRST);
+ MUTATOR_HOOK(SetStartItems, freezetag_SetStartItems, CBC_ORDER_ANY);
MUTATOR_HOOK(HavocBot_ChooseRole, freezetag_BotRoles, CBC_ORDER_ANY);
MUTATOR_HOOK(GetTeamCount, freezetag_GetTeamCount, CBC_ORDER_EXCLUSIVE);
{
if(self.buffs & BUFF_JUMP)
player_jumpheight = autocvar_g_buffs_jump_height;
- self.stat_jumpheight = player_jumpheight;
return false;
}
precache_sound("keepaway/respawn.wav");
addstat(STAT_BUFFS, AS_INT, buffs);
- addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_jumpheight);
InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET);
}
.float buff_invisible_prev_alpha;
// flight
.float buff_flight_prev_gravity;
-// jump
-.float stat_jumpheight;
-//const float STAT_MOVEVARS_JUMPVELOCITY = 250; // engine hack
// disability
.float buff_disability_time;
.float buff_disability_effect_time;
#include "../cl_client.qh"
#include "../../common/buffs.qh"
-#include "../../common/items/item.qh"
-
-#define WITH(it) this.m_##it;
-#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
-
-float instagib_respawntime_ammo = 45;
-float instagib_respawntimejitter_ammo = 0;
-GETTER(float, instagib_respawntime_ammo)
-GETTER(float, instagib_respawntimejitter_ammo)
-
-REGISTER_ITEM(VaporizerCells, Pickup, APPLY(UNWORDS
- ,APPLY(CONFIGURE
- , model = "models/items/a_cells.md3"
- , sound = "misc/itempickup.wav"
- , name = "Vaporizer Ammo"
- )
- ,IF(SV, CONFIGURE
- , botvalue = 100
- , itemid = IT_CELLS
- , respawntime = GET(instagib_respawntime_ammo)
- , respawntimejitter = GET(instagib_respawntimejitter_ammo)
- )
-))
-
-REGISTER_ITEM(ExtraLife, Pickup, APPLY(UNWORDS
- ,APPLY(CONFIGURE
- , model = "models/items/g_h100.md3"
- , sound = "misc/megahealth.wav"
- , name = "Extralife"
- )
- ,IF(SV, CONFIGURE
- , botvalue = BOT_PICKUP_RATING_HIGH
- , itemflags = FL_POWERUP
- , itemid = IT_NAILS
- , respawntime = GET(g_pickup_respawntime_powerup)
- , respawntimejitter = GET(g_pickup_respawntimejitter_powerup)
- )
-))
-
-#undef WITH
-#undef CONFIGURE
+#include "../../common/items/all.qc"
void spawnfunc_item_minst_cells (void)
{
--- /dev/null
+#include "../../common/items/item.qh"
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+
+float instagib_respawntime_ammo = 45;
+float instagib_respawntimejitter_ammo = 0;
+GETTER(float, instagib_respawntime_ammo)
+GETTER(float, instagib_respawntimejitter_ammo)
+
+REGISTER_ITEM(VaporizerCells, Pickup, APPLY(UNWORDS
+ ,APPLY(CONFIGURE
+ , model = "models/items/a_cells.md3"
+ , sound = "misc/itempickup.wav"
+ , name = "Vaporizer Ammo"
+ )
+ ,IF(SV, CONFIGURE
+ , botvalue = 100
+ , itemid = IT_CELLS
+ , respawntime = GET(instagib_respawntime_ammo)
+ , respawntimejitter = GET(instagib_respawntimejitter_ammo)
+ )
+))
+
+REGISTER_ITEM(ExtraLife, Pickup, APPLY(UNWORDS
+ ,APPLY(CONFIGURE
+ , model = "models/items/g_h100.md3"
+ , sound = "misc/megahealth.wav"
+ , name = "Extralife"
+ )
+ ,IF(SV, CONFIGURE
+ , botvalue = BOT_PICKUP_RATING_HIGH
+ , itemflags = FL_POWERUP
+ , itemid = IT_NAILS
+ , respawntime = GET(g_pickup_respawntime_powerup)
+ , respawntimejitter = GET(g_pickup_respawntimejitter_powerup)
+ )
+))
+
+#undef WITH
+#undef CONFIGURE
**Extended Team
Antonio "terencehill" Piu
Archer
+BuddyFriendGuy
Debugger
GATTS
Halogene
IDWMaster
Jan "zykure" Behrens
JH0nny
+Luigi
Łukasz "kuniu the frogg" Polek
Matthias "matthiaskrgr" Krüger
Mattia "Melanosuchus" Basaglia
nifrek
*Level Design
+Amadeusz "amade/proraide" Sławiński
Ben "MooKow" Banker
Calinou
Cortez
Debugger
Jakob "tZork" Markström Gröhn
Konrad "Justin" Slawinski
+Maddin
+L0
Łukasz "kuniu the frogg" Polek
Maik "SavageX" Merten
Marvin "Mirio" Beck
Rasmus "FruitieX" Eskola
Ruszkai "CuBe0wL" Ákos
Severin "sev" Meyer
+ShadoW
*Music / Sound FX
AquaNova (Archer)
**Other Active Contributors
-BuddyFriendGuy
Erik "Ablu" Schilling
-Jope "Sless" Withers
Mircea "Taoki" Kitsune
-Robert "ai" Kuroto
**Translators
Innovati
Jitspoe
Jody Gallagher
+Jope "Sless" Withers
Juergen "LowDragon" Timm
KadaverJack
Kevin "Tyrann" Shanahan
Qantourisc
Oleh "BlaXpirit" Prypin
Rick "Rat" Kelley
+Robert "ai" Kuroto
Ronan
Sajt
Saulo "mand1nga" Gil