Merge branch 'master' into DefaultUser/armormega 387/head
authorMario <mario@smbclan.net>
Sat, 10 Dec 2016 06:09:41 +0000 (16:09 +1000)
committerMario <mario@smbclan.net>
Sat, 10 Dec 2016 06:09:41 +0000 (16:09 +1000)
# Conflicts:
# mutators.cfg
# qcsrc/common/mutators/mutator/nix/sv_nix.qc

111 files changed:
.gitlab-ci.yml
_hud_common.cfg
bal-wep-xonotic.cfg
bal-wep-xpm.cfg
defaultXonotic.cfg
minigames.cfg
monsters.cfg
mutators.cfg
physics.cfg
qcsrc/client/autocvars.qh
qcsrc/client/hud/hud.qc
qcsrc/client/hud/hud.qh
qcsrc/client/hud/panel/healtharmor.qc
qcsrc/client/hud/panel/infomessages.qc
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/shownames.qc
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/client/view.qc
qcsrc/common/_all.inc
qcsrc/common/constants.qh
qcsrc/common/ent_cs.qc
qcsrc/common/items/item.qh
qcsrc/common/items/item/armor.qh
qcsrc/common/items/item/health.qh
qcsrc/common/items/item/powerup.qh
qcsrc/common/minigames/minigame/bd.qc
qcsrc/common/minigames/minigame/snake.qc
qcsrc/common/monsters/monster.qh
qcsrc/common/monsters/monster/zombie.qh
qcsrc/common/monsters/sv_spawn.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qh
qcsrc/common/mutators/mutator/damagetext/damagetext.qc
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/player.qc
qcsrc/common/physics/player.qh
qcsrc/common/playerstats.qc
qcsrc/common/playerstats.qh
qcsrc/common/state.qc
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/common/triggers/func/train.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/turrets/config.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qh
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qh
qcsrc/common/vehicles/vehicle/raptor_weapons.qh
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/vehicles/vehicle/spiderbot_weapons.qh
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/ecs/lib.qh
qcsrc/ecs/systems/physics.qc
qcsrc/ecs/systems/sv_physics.qc
qcsrc/lib/_all.inc
qcsrc/lib/math.qh
qcsrc/lib/self.qh
qcsrc/lib/spawnfunc.qh
qcsrc/lib/warpzone/mathlib.qc
qcsrc/lib/warpzone/mathlib.qh
qcsrc/menu/item/image.qc
qcsrc/menu/item/listbox.qc
qcsrc/menu/xonotic/checkbox.qc
qcsrc/menu/xonotic/credits.qc
qcsrc/menu/xonotic/dialog_multiplayer_create.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_uid2name.qh
qcsrc/menu/xonotic/screenshotimage.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/serverlist.qh
qcsrc/menu/xonotic/slider_decibels.qc
qcsrc/server/_all.qh
qcsrc/server/anticheat.qc
qcsrc/server/anticheat.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/scripting.qc
qcsrc/server/client.qc
qcsrc/server/command/cmd.qh
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_ca.qh
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_freezetag.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/mutators/mutator/gamemode_lms.qh
qcsrc/server/pathlib/main.qc
qcsrc/server/player.qc
qcsrc/server/round_handler.qc
qcsrc/server/weapons/selection.qc

index 3c251dc..63130f8 100644 (file)
@@ -30,7 +30,7 @@ test_sv_game:
     - wget -O data/maps/g-23.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.cache
     - wget -O data/maps/g-23.waypoints.hardwired https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.hardwired
     - make
-    - EXPECT=0a9ea83e32e148da989cbbadc7421ea0
+    - EXPECT=b58f9c7587f1a14e5c52176d4e62a9fb
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index f01f51d..6e88873 100644 (file)
@@ -108,7 +108,7 @@ seta hud_panel_infomessages_group_time 6 "number of seconds a message of a group
 seta hud_panel_infomessages_group_fadetime 0.4 "group message fade in/out time"
 
 seta hud_panel_scoreboard_namesize 15 "size limit of player names and relative column (multiplied by fontsize)"
-seta hud_panel_scoreboard_maxheight 0.5 "max height of the scoreboard; a few players that wouldn't fit into the scoreboard are listed in the last row"
+seta hud_panel_scoreboard_maxheight 0.6 "max height of the scoreboard; a few players that wouldn't fit into the scoreboard are listed in the last row"
 seta hud_panel_scoreboard_others_showscore 1 "show scores of players listed in the last row when the scoreboard reaches the max height"
 seta hud_panel_scoreboard_spectators_showping 1 "show ping of spectators"
 seta hud_panel_scoreboard_spectators_aligned 0 "align spectators in columns"
index 9e1f4cb..57b632b 100644 (file)
@@ -456,7 +456,7 @@ set g_balance_vaporizer_switchdelay_raise 0.2
 set g_balance_vaporizer_weaponreplace ""
 set g_balance_vaporizer_weaponstart 0
 set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 0
+set g_balance_vaporizer_weaponthrowable 1
 // }}}
 // {{{ #13: Grappling Hook
 set g_balance_hook_primary_ammo 5
index 9e1f4cb..57b632b 100644 (file)
@@ -456,7 +456,7 @@ set g_balance_vaporizer_switchdelay_raise 0.2
 set g_balance_vaporizer_weaponreplace ""
 set g_balance_vaporizer_weaponstart 0
 set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 0
+set g_balance_vaporizer_weaponthrowable 1
 // }}}
 // {{{ #13: Grappling Hook
 set g_balance_hook_primary_ammo 5
index 5df6d59..bf35a41 100644 (file)
@@ -36,6 +36,8 @@ alias +hook +button6
 alias -hook -button6
 alias +jetpack +button10
 alias -jetpack -button10
+alias +dodge +button11
+alias -dodge -button11
 alias use "impulse 21"
 
 // for backwards compatibility
@@ -235,6 +237,11 @@ seta cl_eventchase_maxs "12 12 8" "max size of eventchase camera bbox"
 seta cl_eventchase_mins "-12 -12 -8" "min size of eventchase camera bbox"
 seta cl_eventchase_viewoffset "0 0 20" "viewoffset of eventchase camera"
 seta cl_eventchase_generator_viewoffset "0 0 80" "viewoffset of eventchase camera while viewing generator explosion"
+seta cl_eventchase_vehicle 1 "camera goes into 3rd person mode when inside a vehicle"
+seta cl_eventchase_vehicle_viewoffset "0 0 80"
+seta cl_eventchase_vehicle_distance 250
+
+set _vehicles_shownchasemessage 0
 
 //nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining
 set teamplay_lockonrestart 0 "lock teams once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)"
@@ -382,10 +389,10 @@ set bot_ai_navigation_jetpack 0 "Enable bots to navigate maps using the jetpack"
 set bot_ai_navigation_jetpack_mindistance 3500 "Bots will try fly to objects located farther than this distance"
 // Better don't touch these, there are hard to tweak!
 set bot_ai_aimskill_order_mix_1st 0.01 "Amount of the 1st filter output to apply to the aiming angle"
-set bot_ai_aimskill_order_mix_2nd 0.1 "Amount of the 1st filter output to apply to the aiming angle"
-set bot_ai_aimskill_order_mix_3th 0.01 "Amount of the 1st filter output to apply to the aiming angle"
-set bot_ai_aimskill_order_mix_4th 0.05 "Amount of the 1st filter output to apply to the aiming angle"
-set bot_ai_aimskill_order_mix_5th 0.01 "Amount of the 1st filter output to apply to the aiming angle"
+set bot_ai_aimskill_order_mix_2nd 0.1 "Amount of the 2nd filter output to apply to the aiming angle"
+set bot_ai_aimskill_order_mix_3th 0.01 "Amount of the 3th filter output to apply to the aiming angle"
+set bot_ai_aimskill_order_mix_4th 0.05 "Amount of the 4th filter output to apply to the aiming angle"
+set bot_ai_aimskill_order_mix_5th 0.01 "Amount of the 5th filter output to apply to the aiming angle"
 set bot_ai_aimskill_order_filter_1st 0.4 "Position filter"
 set bot_ai_aimskill_order_filter_2nd 0.4 "Movement filter"
 set bot_ai_aimskill_order_filter_3th 0.2 "Acceleration filter"
@@ -782,7 +789,8 @@ seta g_waypointsprite_turrets_maxdist 5000 "max distace for turret sprites"
 seta g_waypointsprite_tactical 1 "tactical overlay on turrets when in a vehicle"
 
 seta cl_damagetext "1" "Draw damage dealt where you hit the enemy"
-seta cl_damagetext_format "-{total}" "How to format the damage text. {health}, {armor}, {total}"
+seta cl_damagetext_format "-{total}" "How to format the damage text. {health}, {armor}, {total}, {potential}: full damage not capped to target's health, {potential_health}: health damage not capped to target's health"
+seta cl_damagetext_format_verbose 0 "{health} shows {potential_health} too when they differ; {total} shows {potential} too when they differ"
 seta cl_damagetext_color "1 1 0" "Damage text color"
 seta cl_damagetext_color_per_weapon "0" "Damage text uses weapon color"
 seta cl_damagetext_size "8" "Damage text font size"
@@ -795,7 +803,14 @@ seta cl_damagetext_accumulate_alpha_rel "0.65" "Only update existing damage text
 seta cl_damagetext_friendlyfire "1" "Show damage text for friendlyfire too"
 seta cl_damagetext_friendlyfire_color "1 0 0" "Damage text color for friendlyfire"
 
-set sv_itemstime 1 "enable networking of left time until respawn for items such as mega health and large armor"
+seta cl_vehicles_alarm 1 "Play an alarm sound when the vehicle you are driving is heavily damaged"
+seta cl_vehicles_hud_tactical 1
+seta cl_vehicles_hudscale 0.5
+seta cl_vehicles_notify_time 15
+seta cl_vehicles_crosshair_size 0.5
+seta cl_vehicles_crosshair_colorize 1
+
+set sv_itemstime 1 "enable networking of time left until respawn for items such as mega health/armor and powerups"
 
 // so it can be stuffcmd-ed still
 set cl_gravity 800     "but ignored anyway"
@@ -1220,6 +1235,10 @@ set _campaign_testrun 0 "To verify the campaign file, set this to 1, then start
 // debug
 set _independent_players 0 "DO NOT TOUCH"
 set _notarget 0 "NO, REALLY, DON'T"
+set debugdraw 0
+set debugdraw_filter ""
+set debugdraw_filterout ""
+set debugtrace 0
 
 // define some engine cvars that we need even on dedicated server
 set r_showbboxes 0
@@ -1375,8 +1394,12 @@ set g_frozen_revive_falldamage_health 40 "Amount of health player has if they re
 set g_frozen_damage_trigger 1 "if 1, frozen players falling into the void will die instead of teleporting to spawn"
 set g_frozen_force 0.6 "How much to multiply the force on a frozen player with"
 
-// player statistics server URI
+// player statistics
 set g_playerstats_gamereport_uri "http://stats.xonotic.org/stats/submit" "Output player statistics information to either: URL (with ://), console (with a dash like this: -), or supply a filename to output to data directory."
+set g_playerstats_gamereport_ladder ""
+set g_playerstats_playerbasic_uri "http://stats.xonotic.org"
+set g_playerstats_playerdetail_uri "http://stats.xonotic.org/player/me"
+set g_playerstats_playerdetail_autoupdatetime 1800 // automatically update every 30 minutes anyway
 
 // autoscreenshots
 set g_max_info_autoscreenshot 3 "how many info_autoscreenshot entities are allowed"
index 4be8cf6..8e70653 100644 (file)
@@ -20,3 +20,7 @@ set sv_minigames_snake_delay_initial 0.7 "Initial delay between snake movement"
 set sv_minigames_snake_delay_multiplier 50 "Multiplier of incremental of movement speed (player_score / cvar)"
 set sv_minigames_snake_delay_min 0.1 "Minimum delay between snake movement (at fastest rate)"
 set sv_minigames_snake_lives 3
+
+
+// Bulldozer
+set sv_minigames_bulldozer_startlevel "level1"
index 1c87a71..ac60390 100644 (file)
@@ -111,4 +111,7 @@ set g_monsters_respawn_delay 20
 set g_monsters_max 20
 set g_monsters_max_perplayer 0
 set g_monsters_armor_blockpercent 0.5
+set g_monsters_damageforcescale 0.8
+set g_monsters_quake_resize 1
+set g_monsters_healthbars 0
 // }}}
index a736f3e..7813776 100644 (file)
@@ -125,8 +125,9 @@ seta cl_spawn_near_teammate 1 "toggle for spawning near teammates (only effectiv
 set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate"
 set g_spawn_near_teammate_distance 640 "max distance to consider a spawn to be near a team mate"
 set g_spawn_near_teammate_ignore_spawnpoint 0 "ignore spawnpoints and spawn right at team mates, if 2, clients can ignore this option"
+set g_spawn_near_teammate_ignore_spawnpoint_max 10 "if set, test at most this many of the available teammates"
 set g_spawn_near_teammate_ignore_spawnpoint_delay 2.5 "how long to wait before its OK to spawn at a player after someone just spawned at this player"
-set g_spawn_near_teammate_ignore_spawnpoint_delay_death 0 "how long to wait before its OK to spawn at a player after death"
+set g_spawn_near_teammate_ignore_spawnpoint_delay_death 3 "how long to wait before its OK to spawn at a player after death"
 set g_spawn_near_teammate_ignore_spawnpoint_check_health 1 "only allow spawn at this player if their health is full"
 set g_spawn_near_teammate_ignore_spawnpoint_closetodeath 1 "spawn as close to death location as possible"
 
@@ -427,6 +428,8 @@ seta cl_multijump 1 "allow multijump mutator"
 set g_multijump 0      "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
 set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
 set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
+set g_multijump_maxspeed 0
+set g_multijump_dodging 1
 
 
 // ===========
@@ -437,3 +440,12 @@ set g_walljump_delay 1 "Minimum delay between wall jumps"
 set g_walljump_force 300 "How far to bounce/jump off the wall"
 set g_walljump_velocity_xy_factor 1.15 "How much to slow down along horizontal axis, higher value = higher deceleration, if factor is < 1, you accelerate by wall jumping"
 set g_walljump_velocity_z_factor 0.5 "Upwards velocity factor, multiplied by normal jump velocity"
+
+
+// ===============
+//  global forces
+// ===============
+set g_globalforces 0 "Global forces: knockback affects everyone"
+set g_globalforces_noself 1 "Global forces: ignore self damage"
+set g_globalforces_self 1 "Global forces: knockback self scale"
+set g_globalforces_range 1000 "Global forces: max range of effect"
index 92fccaa..1a38a7f 100644 (file)
@@ -272,3 +272,32 @@ set g_physics_bones_stopspeed 100
 set g_physics_bones_airaccelerate 1
 set g_physics_bones_airstopaccelerate 2.5
 set g_physics_bones_track_canjump 0
+
+// ==========
+//  Overkill
+// ==========
+set g_physics_overkill_airaccel_qw -0.8
+set g_physics_overkill_airstrafeaccel_qw -0.95
+set g_physics_overkill_airspeedlimit_nonqw 900
+set g_physics_overkill_maxspeed 400
+set g_physics_overkill_jumpvelocity 260
+set g_physics_overkill_maxairstrafespeed 100
+set g_physics_overkill_maxairspeed 360
+set g_physics_overkill_airstrafeaccelerate 24
+set g_physics_overkill_warsowbunny_turnaccel 0
+set g_physics_overkill_airaccel_qw_stretchfactor 2
+set g_physics_overkill_airaccel_sideways_friction 0
+set g_physics_overkill_aircontrol 125
+set g_physics_overkill_aircontrol_power 2
+set g_physics_overkill_aircontrol_backwards 0
+set g_physics_overkill_aircontrol_penalty 180
+set g_physics_overkill_warsowbunny_airforwardaccel 1.00001
+set g_physics_overkill_warsowbunny_topspeed 925
+set g_physics_overkill_warsowbunny_accel 0.1593
+set g_physics_overkill_warsowbunny_backtosideratio 0.8
+set g_physics_overkill_friction 8
+set g_physics_overkill_accelerate 15
+set g_physics_overkill_stopspeed 100
+set g_physics_overkill_airaccelerate 2
+set g_physics_overkill_airstopaccelerate 3
+set g_physics_overkill_track_canjump 0
index 33d1bc2..193b7ef 100644 (file)
@@ -122,7 +122,7 @@ string autocvar_crosshair_hitindication_per_weapon_color;
 float autocvar_crosshair_hitindication_speed;
 bool autocvar_crosshair_hittest;
 bool autocvar_crosshair_hittest_blur;
-float autocvar_crosshair_hittest_scale = 1.25;
+//float autocvar_crosshair_hittest_scale = 1.25;
 bool autocvar_crosshair_hittest_showimpact;
 bool autocvar_crosshair_per_weapon;
 float autocvar_crosshair_pickup;
@@ -208,7 +208,7 @@ bool autocvar_hud_panel_engineinfo_dynamichud   = true;
 bool autocvar_hud_panel_infomessages_dynamichud = false;
 bool autocvar_hud_panel_physics_dynamichud      = true;
 bool autocvar_hud_panel_centerprint_dynamichud  = true;
-bool autocvar_hud_panel_itemstime_dynamichud    = true;
+//bool autocvar_hud_panel_itemstime_dynamichud    = true;
 bool autocvar_hud_panel_healtharmor_hide_ondeath  = false;
 bool autocvar_hud_panel_ammo_hide_ondeath         = false;
 bool autocvar_hud_panel_powerups_hide_ondeath     = false;
@@ -442,13 +442,5 @@ float autocvar_cl_deathglow;
 bool autocvar_developer_csqcentities;
 float autocvar_g_jetpack_attenuation;
 bool autocvar_cl_showspectators;
-string autocvar_crosshair_hmg = "";
-vector autocvar_crosshair_hmg_color = '0.2 1.0 0.2';
-float autocvar_crosshair_hmg_alpha = 1;
-float autocvar_crosshair_hmg_size = 1;
-string autocvar_crosshair_rpc = "";
-vector autocvar_crosshair_rpc_color = '0.2 1.0 0.2';
-float autocvar_crosshair_rpc_alpha = 1;
-float autocvar_crosshair_rpc_size = 1;
 int autocvar_cl_nade_timer;
 bool autocvar_r_drawviewmodel;
index c89fe08..ee94af7 100644 (file)
@@ -22,34 +22,34 @@ Misc HUD functions
 ==================
 */
 
-vector HUD_Get_Num_Color (float x, float maxvalue)
+vector HUD_Get_Num_Color (float hp, float maxvalue)
 {
        float blinkingamt;
        vector color;
-       if(x >= maxvalue) {
+       if(hp >= maxvalue) {
                color.x = sin(2*M_PI*time);
                color.y = 1;
                color.z = sin(2*M_PI*time);
        }
-       else if(x > maxvalue * 0.75) {
-               color.x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0
-               color.y = 0.9 + (x-150)*0.02 * 0.1; // green value between 0.9 -> 1
+       else if(hp > maxvalue * 0.75) {
+               color.x = 0.4 - (hp-150)*0.02 * 0.4; //red value between 0.4 -> 0
+               color.y = 0.9 + (hp-150)*0.02 * 0.1; // green value between 0.9 -> 1
                color.z = 0;
        }
-       else if(x > maxvalue * 0.5) {
-               color.x = 1 - (x-100)*0.02 * 0.6; //red value between 1 -> 0.4
-               color.y = 1 - (x-100)*0.02 * 0.1; // green value between 1 -> 0.9
-               color.z = 1 - (x-100)*0.02; // blue value between 1 -> 0
+       else if(hp > maxvalue * 0.5) {
+               color.x = 1 - (hp-100)*0.02 * 0.6; //red value between 1 -> 0.4
+               color.y = 1 - (hp-100)*0.02 * 0.1; // green value between 1 -> 0.9
+               color.z = 1 - (hp-100)*0.02; // blue value between 1 -> 0
        }
-       else if(x > maxvalue * 0.25) {
+       else if(hp > maxvalue * 0.25) {
                color.x = 1;
                color.y = 1;
-               color.z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1
+               color.z = 0.2 + (hp-50)*0.02 * 0.8; // blue value between 0.2 -> 1
        }
-       else if(x > maxvalue * 0.1) {
+       else if(hp > maxvalue * 0.1) {
                color.x = 1;
-               color.y = (x-20)*90/27/100; // green value between 0 -> 1
-               color.z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
+               color.y = (hp-20)*90/27/100; // green value between 0 -> 1
+               color.z = (hp-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
        }
        else {
                color.x = 1;
@@ -57,7 +57,7 @@ vector HUD_Get_Num_Color (float x, float maxvalue)
                color.z = 0;
        }
 
-       blinkingamt = (1 - x/maxvalue/0.25);
+       blinkingamt = (1 - hp/maxvalue/0.25);
        if(blinkingamt > 0)
        {
                color.x = color.x - color.x * blinkingamt * sin(2*M_PI*time);
@@ -303,7 +303,7 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA
        drawsubpic(pos + eX * mySize.x - eX * min(mySize.x * 0.5, mySize.y), eX * min(mySize.x * 0.5, mySize.y) + eY * mySize.y, pic, '0.75 0 0', '0.25 1 0', color, theAlpha, drawflag);
 }
 
-void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp)
+void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp)
 {
     TC(bool, vertical); TC(int, icon_right_align);
        vector newPos = '0 0 0', newSize = '0 0 0';
@@ -345,7 +345,7 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bo
                // reduce only y to draw numbers with different number of digits with the same y size
                numpos.y += newSize.y * ((1 - 0.7) / 2);
                newSize.y *= 0.7;
-               drawstring_aspect(numpos, ftos(x), newSize, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(numpos, ftos(theTime), newSize, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
                return;
        }
 
@@ -379,14 +379,14 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bo
 
        // NOTE: newSize_x is always equal to 3 * mySize_y so we can use
        // '2 1 0' * newSize_y instead of eX * (2/3) * newSize_x + eY * newSize_y
-       drawstring_aspect_expanding(numpos, ftos(x), '2 1 0' * newSize.y, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
+       drawstring_aspect_expanding(numpos, ftos(theTime), '2 1 0' * newSize.y, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
        drawpic_aspect_skin_expanding(picpos, icon, '1 1 0' * newSize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
 }
 
-void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, int icon_right_align, vector color, float theAlpha)
+void DrawNumIcon(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha)
 {
     TC(bool, vertical); TC(int, icon_right_align);
-       DrawNumIcon_expanding(myPos, mySize, x, icon, vertical, icon_right_align, color, theAlpha, 0);
+       DrawNumIcon_expanding(myPos, mySize, theTime, icon, vertical, icon_right_align, color, theAlpha, 0);
 }
 
 /*
index 4cd0ee8..06a3491 100644 (file)
@@ -48,9 +48,9 @@ float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary);
 void HUD_Radar_Hide_Maximized();
 
 float HUD_GetRowCount(int item_count, vector size, float item_aspect);
-vector HUD_Get_Num_Color (float x, float maxvalue);
-void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha);
-void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp);
+vector HUD_Get_Num_Color (float hp, float maxvalue);
+void DrawNumIcon(vector myPos, vector mySize, float theTime, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha);
+void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp);
 void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag);
 vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspect);
 
index 7f5e4c1..4fad2c7 100644 (file)
@@ -86,8 +86,7 @@ void HUD_HealthArmor()
                vector v;
                v = healtharmor_maxdamage(health, armor, armorblockpercent, DEATH_WEAPON.m_id);
 
-               float x;
-               x = floor(v.x + 1);
+               float hp = floor(v.x + 1);
 
         float maxtotal = maxhealth + maxarmor;
                string biggercount;
@@ -95,7 +94,7 @@ void HUD_HealthArmor()
                {
                        biggercount = "health";
                        if(autocvar_hud_panel_healtharmor_progressbar)
-                               HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_health, x/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+                               HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_health, hp/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        if(armor)
             if(autocvar_hud_panel_healtharmor_text)
                                drawpic_aspect_skin(pos + eX * mySize.x - eX * 0.5 * mySize.y, "armor", '0.5 0.5 0' * mySize.y, '1 1 1', panel_fg_alpha * armor / health, DRAWFLAG_NORMAL);
@@ -104,13 +103,13 @@ void HUD_HealthArmor()
                {
                        biggercount = "armor";
                        if(autocvar_hud_panel_healtharmor_progressbar)
-                               HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, x/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_armor_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+                               HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, hp/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_armor_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        if(health)
             if(autocvar_hud_panel_healtharmor_text)
                                drawpic_aspect_skin(pos + eX * mySize.x - eX * 0.5 * mySize.y, "health", '0.5 0.5 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
         if(autocvar_hud_panel_healtharmor_text)
-                       DrawNumIcon(pos, mySize, x, biggercount, 0, iconalign, HUD_Get_Num_Color(x, maxtotal), 1);
+                       DrawNumIcon(pos, mySize, hp, biggercount, 0, iconalign, HUD_Get_Num_Color(hp, maxtotal), 1);
 
                if(fuel)
                        HUD_Panel_DrawProgressBar(pos, eX * mySize.x + eY * 0.2 * mySize.y, "progressbar", fuel/100, 0, (baralign == 1 || baralign == 3), autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
index cd49f09..db102e6 100644 (file)
@@ -114,7 +114,7 @@ void HUD_InfoMessages()
                                InfoMessage(s);
                        }
 
-                       if(gametype == MAPINFO_TYPE_LMS)
+                       if(!warmup_stage && gametype == MAPINFO_TYPE_LMS)
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
index ef68e21..35de219 100644 (file)
@@ -31,14 +31,14 @@ float sbt_highlight_alpha_self;
 
 // provide basic panel cvars to old clients
 // TODO remove them after a future release (0.8.2+)
-string autocvar_hud_panel_scoreboard_pos = "0.150000 0.150000";
-string autocvar_hud_panel_scoreboard_size = "0.700000 0.700000";
-string autocvar_hud_panel_scoreboard_bg = "border_default";
-string autocvar_hud_panel_scoreboard_bg_color = "0 0.3 0.5";
-string autocvar_hud_panel_scoreboard_bg_color_team = "";
-string autocvar_hud_panel_scoreboard_bg_alpha = "0.7";
-string autocvar_hud_panel_scoreboard_bg_border = "";
-string autocvar_hud_panel_scoreboard_bg_padding = "";
+noref string autocvar_hud_panel_scoreboard_pos = "0.150000 0.150000";
+noref string autocvar_hud_panel_scoreboard_size = "0.700000 0.700000";
+noref string autocvar_hud_panel_scoreboard_bg = "border_default";
+noref string autocvar_hud_panel_scoreboard_bg_color = "0 0.3 0.5";
+noref string autocvar_hud_panel_scoreboard_bg_color_team = "";
+noref string autocvar_hud_panel_scoreboard_bg_alpha = "0.7";
+noref string autocvar_hud_panel_scoreboard_bg_border = "";
+noref string autocvar_hud_panel_scoreboard_bg_padding = "";
 
 float autocvar_hud_panel_scoreboard_fadeinspeed = 10;
 float autocvar_hud_panel_scoreboard_fadeoutspeed = 5;
@@ -59,7 +59,7 @@ bool autocvar_hud_panel_scoreboard_accuracy_nocolors = false;
 
 bool autocvar_hud_panel_scoreboard_dynamichud = false;
 
-float autocvar_hud_panel_scoreboard_maxheight = 0.5;
+float autocvar_hud_panel_scoreboard_maxheight = 0.6;
 bool autocvar_hud_panel_scoreboard_others_showscore = true;
 bool autocvar_hud_panel_scoreboard_spectators_showping = true;
 bool autocvar_hud_panel_scoreboard_spectators_aligned = false;
@@ -670,7 +670,7 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
                case SP_DMG: case SP_DMGTAKEN:
                        return sprintf("%.1f k", pl.(scores(field)) / 1000);
 
-               default:
+               default: case SP_SCORE:
                        tmp = pl.(scores(field));
                        f = scores_flags(field);
                        if(field == ps_primary)
@@ -951,7 +951,7 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
                                field = Scoreboard_GetField(pl, SP_PING);
                }
                else if(autocvar_hud_panel_scoreboard_others_showscore)
-                       field = ftos(pl.(scores(ps_primary)));
+                       field = Scoreboard_GetField(pl, SP_SCORE);
 
                string str = textShortenToWidth(entcs_GetName(pl.sv_entnum), namesize, hud_fontsize, stringwidth_colors);
                float column_width = stringwidth(str, true, hud_fontsize);
@@ -1009,10 +1009,16 @@ vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
        int max_players = 999;
        if(autocvar_hud_panel_scoreboard_maxheight > 0)
        {
-               max_players = autocvar_hud_panel_scoreboard_maxheight * vid_conheight;
+               float height = autocvar_hud_panel_scoreboard_maxheight * vid_conheight;
                if(teamplay)
-                       max_players = (max_players - hud_fontsize.y * 1.25 - panel_bg_padding * 2) / 2;
-               max_players = floor(max_players / (hud_fontsize.y * 1.25));
+               {
+                       height -= (panel_bg_padding * 2 + hud_fontsize.y * 1.25) * team_count; // - padding and header
+                       height -= hud_fontsize.y * (team_count - 1); // - spacing between tables
+                       height /= team_count;
+               }
+               else
+                       height -= panel_bg_padding * 2; // - padding
+               max_players = floor(height / (hud_fontsize.y * 1.25));
                if(max_players <= 1)
                        max_players = 1;
                if(max_players == tm.team_size)
@@ -1121,11 +1127,11 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
                WepSet set = it.m_wepset;
-               if (weapon_stats < 0)
+               if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
                {
-                       if (!(weapons_stat & set) && (it.spawnflags & WEP_FLAG_HIDDEN || it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
-                               nHidden += 1;
-                       else if (!(weapons_stat & set || weapons_inmap & set))
+                       if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)))
+                               ++nHidden;
+                       else
                                ++disownedcnt;
                }
        });
@@ -1199,7 +1205,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
                WepSet set = it.m_wepset;
-               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
+               if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
                        continue;
 
                float weapon_alpha;
index 0e88cd5..a0d7b87 100644 (file)
@@ -389,15 +389,15 @@ void PolyDrawModel(entity e)
 
 void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag)
 {
-       float x, y, q, d;
+       float d;
        vector ringsize, v, t;
        ringsize = radi * '1 1 0';
 
-       x = cos(f * 2 * M_PI);
-       y = sin(f * 2 * M_PI);
-       q = fabs(x) + fabs(y);
-       x /= q;
-       y /= q;
+       float co = cos(f * 2 * M_PI);
+       float si = sin(f * 2 * M_PI);
+       float q = fabs(co) + fabs(si);
+       co /= q;
+       si /= q;
 
        if(f >= 1)
        {
@@ -530,8 +530,8 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        if(d > 0)
        {
                        v = centre;                     t = '0.5 0.5 0';
-                       v.x += x * 0.5 * ringsize.x;    t += x * '0.5 0.5 0';
-                       v.y += y * 0.5 * ringsize.y;    t += y * '0.5 -0.5 0';
+                       v.x += co * 0.5 * ringsize.x;   t += co * '0.5 0.5 0';
+                       v.y += si * 0.5 * ringsize.y;   t += si * '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
        }
index 6a4515a..e46a97c 100644 (file)
@@ -49,34 +49,41 @@ void Draw_ShowNames(entity this)
                hit = !(trace_fraction < 1 && (trace_networkentity != this.sv_entnum && trace_ent.entnum != this.sv_entnum));
        }
        // handle tag fading
-       bool overlap = false;
+       int overlap = -1;
        vector o = project_3d_to_2d(this.origin + eZ * autocvar_hud_shownames_offset);
+       if (autocvar_hud_shownames_crosshairdistance)
+       {
+               float d = autocvar_hud_shownames_crosshairdistance;
+               float w = o.x - vid_conwidth / 2;
+               float h = o.y - vid_conheight / 2;
+               if (d * d > w * w + h * h) this.pointtime = time;
+               if (this.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time)
+                       overlap = 1;
+               else if(!autocvar_hud_shownames_crosshairdistance_antioverlap)
+                       overlap = 0;
+       }
+
        float dist = vlen(this.origin - view_origin);
-       if (autocvar_hud_shownames_antioverlap)
+       if (overlap == -1 && autocvar_hud_shownames_antioverlap)
        {
                // fade tag out if another tag that is closer to you overlaps
-               LL_EACH(shownames_ent, it != this && entcs_receiver(i), {
+               entity entcs = NULL;
+               LL_EACH(shownames_ent, it != this, {
+                       entcs = entcs_receiver(i);
+                       if (!(entcs && entcs.has_sv_origin))
+                               continue;
                        vector eo = project_3d_to_2d(it.origin);
                        if (eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight) continue;
                        eo.z = 0;
                        if (vdist(((eX * o.x + eY * o.y) - eo), <, autocvar_hud_shownames_antioverlap_distance)
                            && vdist((it.origin - view_origin), <, dist))
                        {
-                               overlap = true;
+                               overlap = 1;
                                break;
                        }
                });
        }
        bool onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
-       if (autocvar_hud_shownames_crosshairdistance)
-       {
-               float d = autocvar_hud_shownames_crosshairdistance;
-               float w = o.x - vid_conwidth / 2;
-               float h = o.y - vid_conheight / 2;
-               if (d * d > w * w + h * h) this.pointtime = time;
-               if (this.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time) overlap = true;
-               else overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : false); // override what antioverlap says unless allowed by cvar.
-       }
        if (!this.fadedelay) this.fadedelay = time + SHOWNAMES_FADEDELAY;
        if (this.csqcmodel_isdead)                                                                   // dead player, fade out slowly
        {
@@ -87,7 +94,7 @@ void Draw_ShowNames(entity this)
                this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
                this.fadedelay = 0;                         // reset fade in delay, enemy has left the view
        }
-       else if (overlap)                               // tag overlap detected, fade out
+       else if (overlap > 0) // tag overlap detected, fade out
        {
                this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
        }
index 9c4544b..abd700e 100644 (file)
@@ -49,12 +49,12 @@ vector teamradar_2dcoord_to_texcoord(vector in)
        return out;
 }
 
-vector teamradar_texcoord_to_3dcoord(vector in,float z)
+vector teamradar_texcoord_to_3dcoord(vector in,float oz)
 {
        vector out;
        out_x = in_x * (mi_picmax_x - mi_picmin_x) + mi_picmin_x;
        out_y = in_y * (mi_picmax_y - mi_picmin_y) + mi_picmin_y;
-       out_z = z;
+       out_z = oz;
        return out;
 }
 
index 0b1884c..251c1a5 100644 (file)
@@ -32,7 +32,7 @@ vector teamradar_3dcoord_to_texcoord(vector in);
 
 vector teamradar_texcoord_to_2dcoord(vector in);
 
-vector teamradar_texcoord_to_3dcoord(vector in,float z);
+vector teamradar_texcoord_to_3dcoord(vector in,float oz);
 
 void draw_teamradar_background(float fg);
 
index 12f4c6a..2ca5311 100644 (file)
@@ -125,7 +125,6 @@ void calc_followmodel_ofs(entity view)
        float frac;
        vector gunorg = '0 0 0';
        static vector vel_average;
-       static vector gunorg_prev = '0 0 0';
        static vector gunorg_adjustment_highpass;
        static vector gunorg_adjustment_lowpass;
 
@@ -314,12 +313,9 @@ void viewmodel_draw(entity this)
        {
                static string name_last;
                string name = wep.mdl;
-               if(wep == WEP_TUBA)
-               {
-                       name = (this.tuba_instrument == 0) ? "tuba" :
-                          (this.tuba_instrument == 1) ? "akordeon" :
-                                                    "kleinbottle";
-               }
+               string newname = wep.wr_viewmodel(wep, this);
+               if(newname)
+                       name = newname;
                bool swap = name != name_last;
                // if (swap)
                {
@@ -826,8 +822,8 @@ void HitSound()
                        float a = autocvar_cl_hitsound_max_pitch;
                        float b = autocvar_cl_hitsound_min_pitch;
                        float c = autocvar_cl_hitsound_nom_damage;
-                       float x = unaccounted_damage;
-                       float pitch_shift = (b*x*(a-1) + a*c*(1-b)) / (x*(a-1) + c*(1-b));
+                       float d = unaccounted_damage;
+                       float pitch_shift = (b*d*(a-1) + a*c*(1-b)) / (d*(a-1) + c*(1-b));
 
                        // if sound variation is disabled, set pitch_shift to 1
                        if (autocvar_cl_hitsound == 1)
@@ -879,7 +875,7 @@ vector crosshair_getcolor(entity this, float health_stat)
 
                case 2: // crosshair_color_by_health
                {
-                       float x = health_stat;
+                       float hp = health_stat;
 
                        //x = red
                        //y = green
@@ -887,33 +883,33 @@ vector crosshair_getcolor(entity this, float health_stat)
 
                        wcross_color.z = 0;
 
-                       if(x > 200)
+                       if(hp > 200)
                        {
                                wcross_color.x = 0;
                                wcross_color.y = 1;
                        }
-                       else if(x > 150)
+                       else if(hp > 150)
                        {
-                               wcross_color.x = 0.4 - (x-150)*0.02 * 0.4;
-                               wcross_color.y = 0.9 + (x-150)*0.02 * 0.1;
+                               wcross_color.x = 0.4 - (hp-150)*0.02 * 0.4;
+                               wcross_color.y = 0.9 + (hp-150)*0.02 * 0.1;
                        }
-                       else if(x > 100)
+                       else if(hp > 100)
                        {
-                               wcross_color.x = 1 - (x-100)*0.02 * 0.6;
-                               wcross_color.y = 1 - (x-100)*0.02 * 0.1;
-                               wcross_color.z = 1 - (x-100)*0.02;
+                               wcross_color.x = 1 - (hp-100)*0.02 * 0.6;
+                               wcross_color.y = 1 - (hp-100)*0.02 * 0.1;
+                               wcross_color.z = 1 - (hp-100)*0.02;
                        }
-                       else if(x > 50)
+                       else if(hp > 50)
                        {
                                wcross_color.x = 1;
                                wcross_color.y = 1;
-                               wcross_color.z = 0.2 + (x-50)*0.02 * 0.8;
+                               wcross_color.z = 0.2 + (hp-50)*0.02 * 0.8;
                        }
-                       else if(x > 20)
+                       else if(hp > 20)
                        {
                                wcross_color.x = 1;
-                               wcross_color.y = (x-20)*90/27/100;
-                               wcross_color.z = (x-20)*90/27/100 * 0.2;
+                               wcross_color.y = (hp-20)*90/27/100;
+                               wcross_color.z = (hp-20)*90/27/100 * 0.2;
                        }
                        else
                        {
index 5177c9d..988413f 100644 (file)
@@ -1,4 +1,4 @@
-float autocvar_net_connecttimeout = 30;
+noref float autocvar_net_connecttimeout = 30;
 
 #ifdef GAMEQC
 #include "anim.qc"
index f3acfed..910f34e 100644 (file)
@@ -233,7 +233,7 @@ const int SPECIES_RESERVED = 15;
 const int FRAGS_PLAYER = 0;
 const int FRAGS_SPECTATOR = -666;
 const int FRAGS_LMS_LOSER = -616;
-const int FRAGS_PLAYER_NONSOLID = -616;
+const int FRAGS_PLAYER_NONSOLID = FRAGS_LMS_LOSER;
 // we can use this frags value for both
 
 // water levels
@@ -247,6 +247,7 @@ const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
 const int SERVERFLAG_TEAMPLAY = 2;
 const int SERVERFLAG_PLAYERSTATS = 4;
 
+#ifdef SVQC
 // FIXME/EXPLAINME: why? Mario: because
 vector autocvar_sv_player_maxs = '16 16 45';
 vector autocvar_sv_player_mins = '-16 -16 -24';
@@ -254,7 +255,8 @@ vector autocvar_sv_player_viewoffset = '0 0 20';
 vector autocvar_sv_player_crouch_maxs = '16 16 25';
 vector autocvar_sv_player_crouch_mins = '-16 -16 -24';
 vector autocvar_sv_player_crouch_viewoffset = '0 0 20';
-vector autocvar_sv_player_headsize = '24 24 12';
+//vector autocvar_sv_player_headsize = '24 24 12';
+#endif
 
 
 // a bit more constant
index a89e84a..71052bd 100644 (file)
@@ -73,6 +73,11 @@ MACRO_END
                entity player = this.owner;
                sf |= BIT(0); // assume private
                do {
+                       if (!(IS_PLAYER(player)))
+                       {
+                               sf &= ENTCS_PUBLICMASK; // no private updates
+                               break;
+                       }
                        if (radar_showennemies) break;
                        if (SAME_TEAM(to, player)) break;
                        if (!(IS_PLAYER(to) || to.caplayer) && time > game_starttime) break;
@@ -175,33 +180,26 @@ MACRO_END
        {
                int n = ReadByte();
                entity e = entcs_receiver(n);
-               #define X(e) { \
-                       setthink(e, entcs_think); \
-                       entcs_receiver(n, e); \
-               }
                if (e == NULL)
                {
                        if (!this)
-                       {
                                // initial = temp
                                e = new_pure(entcs_receiver);
-                               X(e);
-                       }
                        else
-                       {
                                // initial = linked
                                e = this;
-                               X(e);
-                       }
+                       setthink(e, entcs_think);
+                       entcs_receiver(n, e);
                }
                else if (e != this && this)
                {
                        // upgrade to linked
                        delete(e);
                        e = this;
-                       X(e);
+                       setthink(e, entcs_think);
+                       entcs_receiver(n, e);
                }
-               #undef X
+
                InterpolateOrigin_Undo(e);
                e.sv_entnum = n;
                int sf = ReadShort();
index e46df6b..bac1270 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+#include <common/t_items.qh>
 
 const int IT_UNLIMITED_WEAPON_AMMO             =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
 const int IT_UNLIMITED_SUPERWEAPONS            =  BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
@@ -45,6 +46,10 @@ CLASS(GameItem, Object)
     ATTRIB(GameItem, m_color, vector, '1 1 1');
     ATTRIB(GameItem, m_waypoint, string);
     ATTRIB(GameItem, m_waypointblink, int, 1);
+#ifdef GAMEQC
+    ATTRIB(GameItem, m_glow, bool, false);
+    ATTRIB(GameItem, m_respawnsound, Sound, SND_ITEMRESPAWN);
+#endif
     METHOD(GameItem, display, void(GameItem this, void(string name, string icon) returns))
     {
         TC(GameItem, this);
index a8981e8..93e76bf 100644 (file)
@@ -91,6 +91,7 @@ REGISTER_ITEM(ArmorMega, Armor) {
     this.m_waypoint             =   _("Mega armor");
     this.m_waypointblink        =   2;
 #ifdef SVQC
+    this.m_maxs                 =   '16 16 70';
     this.m_botvalue             =   BOT_PICKUP_RATING_HIGH;
     this.m_itemid               =   IT_ARMOR;
     this.m_respawntime          =   GET(g_pickup_respawntime_long);
index 0b5458a..bd2f61f 100644 (file)
@@ -91,6 +91,7 @@ REGISTER_ITEM(HealthMega, Health) {
     this.m_waypoint             =   _("Mega health");
     this.m_waypointblink        =   2;
 #ifdef SVQC
+    this.m_maxs                 =   '16 16 70';
     this.m_botvalue             =   BOT_PICKUP_RATING_HIGH;
     this.m_itemid               =   IT_HEALTH;
     this.m_respawntime          =   GET(g_pickup_respawntime_long);
index 002be54..df9315e 100644 (file)
@@ -9,7 +9,7 @@
 CLASS(Powerup, Pickup)
 #ifdef SVQC
     ATTRIB(Powerup, m_mins, vector, '-16 -16 0');
-    ATTRIB(Powerup, m_maxs, vector, '16 16 48');
+    ATTRIB(Powerup, m_maxs, vector, '16 16 80');
     ATTRIB(Powerup, m_botvalue, int, 100000);
     ATTRIB(Powerup, m_itemflags, int, FL_POWERUP);
     ATTRIB(Powerup, m_respawntime, float(), GET(g_pickup_respawntime_powerup));
@@ -26,6 +26,8 @@ REGISTER_ITEM(Strength, Powerup) {
 #ifdef GAMEQC
     this.m_model            =   MDL_Strength_ITEM;
     this.m_sound            =   SND_Strength;
+    this.m_glow             =   true;
+    this.m_respawnsound     =   SND_STRENGTH_RESPAWN;
 #endif
     this.m_name             =   "Strength Powerup";
     this.m_icon             =   "strength";
@@ -44,6 +46,8 @@ REGISTER_ITEM(Shield, Powerup) {
 #ifdef GAMEQC
     this.m_model            =   MDL_Shield_ITEM;
     this.m_sound            =   SND_Shield;
+    this.m_glow             =   true;
+    this.m_respawnsound     =   SND_SHIELD_RESPAWN;
 #endif
     this.m_name             =   "Shield";
     this.m_icon             =   "shield";
index 911d19d..09fae55 100644 (file)
@@ -47,7 +47,9 @@ const int BD_DIR_DN = 1;
 const int BD_DIR_LF = 2;
 const int BD_DIR_RT = 3;
 
+#ifdef SVQC
 string autocvar_sv_minigames_bulldozer_startlevel = "level1";
+#endif
 
 // find same game piece given its tile name
 entity bd_find_piece(entity minig, string tile, bool check_target)
index 7f0fdb2..3aedeb0 100644 (file)
@@ -21,7 +21,9 @@ bool autocvar_sv_minigames_snake_wrap = false;
 float autocvar_sv_minigames_snake_delay_initial = 0.7;
 float autocvar_sv_minigames_snake_delay_multiplier = 50;
 float autocvar_sv_minigames_snake_delay_min = 0.1;
+#ifdef SVQC
 int autocvar_sv_minigames_snake_lives = 3;
+#endif
 
 .int snake_score;
 
index 2685e2f..ab64498 100644 (file)
@@ -12,6 +12,7 @@ const int MON_FLAG_CRUSH = BIT(11); // monster can be stomped in special modes
 const int MON_FLAG_RIDE = BIT(12); // monster can be ridden in special modes
 const int MONSTER_SIZE_QUAKE = BIT(13);
 const int MONSTER_TYPE_PASSIVE = BIT(14); // doesn't target or chase enemies
+const int MONSTER_TYPE_UNDEAD = BIT(15); // monster is by most definitions a zombie (doesn't fully die unless gibbed)
 
 // entity properties of monsterinfo:
 .bool(int, entity actor, entity targ) monster_attackfunc;
index b52056e..d3c94cd 100644 (file)
@@ -7,7 +7,7 @@ MODEL(MON_ZOMBIE, M_Model("zombie.dpm"));
 #endif
 
 CLASS(Zombie, Monster)
-    ATTRIB(Zombie, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RIDE);
+    ATTRIB(Zombie, spawnflags, int, MONSTER_TYPE_UNDEAD | MON_FLAG_MELEE | MON_FLAG_RIDE);
     ATTRIB(Zombie, mins, vector, '-18 -18 -25');
     ATTRIB(Zombie, maxs, vector, '18 18 47');
 #ifdef GAMEQC
index 6d9daa2..497dee8 100644 (file)
@@ -69,7 +69,11 @@ entity spawnmonster (entity e, string monster, int monster_id, entity spawnedby,
        }
 
        // Monster_Spawn checks if monster is valid
-       Monster_Spawn(e, false, monster_id);
+       if(!Monster_Spawn(e, false, monster_id))
+       {
+               delete(e);
+               return NULL; // remove even if told not to, as we didn't spawn any kind of monster
+       }
 
        return e;
 }
index 5587da5..4503718 100644 (file)
@@ -231,6 +231,7 @@ void buff_Think(entity this)
                this.skin = buff.m_skin;
 
                setmodel(this, MDL_BUFF);
+               setsize(this, BUFF_MIN, BUFF_MAX);
 
                if(this.buff_waypoint)
                {
@@ -424,9 +425,9 @@ void buff_Medic_Heal(entity this)
        });
 }
 
-float buff_Inferno_CalculateTime(float x, float offset_x, float offset_y, float intersect_x, float intersect_y, float base)
+float buff_Inferno_CalculateTime(float damg, float offset_x, float offset_y, float intersect_x, float intersect_y, float base)
 {
-       return offset_y + (intersect_y - offset_y) * logn(((x - offset_x) * ((base - 1) / intersect_x)) + 1, base);
+       return offset_y + (intersect_y - offset_y) * logn(((damg - offset_x) * ((base - 1) / intersect_x)) + 1, base);
 }
 
 // mutator hooks
@@ -826,7 +827,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
        if(player.buffs & BUFF_MAGNET.m_itemid)
        {
                vector pickup_size;
-               IL_EACH(g_items, it.classname != "item_flag_team" && it.classname != "item_kh_key",
+               IL_EACH(g_items, it.itemdef,
                {
                        if(it.buffs)
                                pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_buff;
index b9fc1e4..5b14c39 100644 (file)
@@ -70,8 +70,8 @@ float autocvar_g_buffs_luck_damagemultiplier = 3;
 .int oldbuffs; // for updating effects
 .entity buff_model; // controls effects (TODO: make csqc)
 
-const vector BUFF_MIN = ('-16 -16 -20');
-const vector BUFF_MAX = ('16 16 20');
+const vector BUFF_MIN = ('-16 -16 0');
+const vector BUFF_MAX = ('16 16 60');
 
 // client side options
 .float cvar_cl_buffs_autoreplace;
index e55b9fc..7f2b740 100644 (file)
@@ -3,12 +3,21 @@
 #define DAMAGETEXT_PRECISION_MULTIPLIER 128
 #define DAMAGETEXT_SHORT_LIMIT 256 // the smallest value that we can't send as short - 2^15 (signed short) / DAMAGETEXT_PRECISION_MULTIPLIER
 
+const int DTFLAG_SAMETEAM = BIT(0);
+const int DTFLAG_BIG_HEALTH = BIT(1);
+const int DTFLAG_BIG_ARMOR = BIT(2);
+const int DTFLAG_BIG_POTENTIAL = BIT(3);
+const int DTFLAG_NO_ARMOR = BIT(4);
+const int DTFLAG_NO_POTENTIAL = BIT(5);
+
 REGISTER_MUTATOR(damagetext, true);
 
-#if defined(CSQC) || defined(MENUQC)
+// || defined(MENUQC)
+#if defined(CSQC)
 // no translatable cvar description please
 AUTOCVAR_SAVE(cl_damagetext,                        bool,   true,       "Draw damage dealt where you hit the enemy");
-AUTOCVAR_SAVE(cl_damagetext_format,                 string, "-{total}", "How to format the damage text. {health}, {armor}, {total}");
+AUTOCVAR_SAVE(cl_damagetext_format,                 string, "-{total}", "How to format the damage text. {health}, {armor}, {total}, {potential}: full damage not capped to target's health, {potential_health}: health damage not capped to target's health");
+AUTOCVAR_SAVE(cl_damagetext_format_verbose,         bool,   false,      "{health} shows {potential_health} too when they differ; {total} shows {potential} too when they differ");
 STATIC_INIT(DamageText_LegacyFormat) {
     if (strstrofs(autocvar_cl_damagetext_format, "{", 0) < 0) autocvar_cl_damagetext_format = "-{total}";
 }
@@ -37,6 +46,7 @@ CLASS(DamageText, Object)
     ATTRIB(DamageText, m_friendlyfire, bool, false);
     ATTRIB(DamageText, m_damage, int, 0);
     ATTRIB(DamageText, m_armordamage, int, 0);
+    ATTRIB(DamageText, m_potential_damage, int, 0);
     ATTRIB(DamageText, m_deathtype, int, 0);
     ATTRIB(DamageText, time_prev, float, time);
 
@@ -60,28 +70,45 @@ CLASS(DamageText, Object)
                 Weapon w = DEATH_WEAPONOF(this.m_deathtype);
                 if (w != WEP_Null) rgb = w.wpcolor;
             }
+            int health = rint(this.m_damage / DAMAGETEXT_PRECISION_MULTIPLIER);
+            int total = rint((this.m_damage + this.m_armordamage) / DAMAGETEXT_PRECISION_MULTIPLIER);
+            int potential = rint(this.m_potential_damage / DAMAGETEXT_PRECISION_MULTIPLIER);
+            int potential_health = rint((this.m_potential_damage - this.m_armordamage) / DAMAGETEXT_PRECISION_MULTIPLIER);
+
             string s = autocvar_cl_damagetext_format;
-            s = strreplace("{health}", sprintf("%d", rint(this.m_damage / DAMAGETEXT_PRECISION_MULTIPLIER)), s);
             s = strreplace("{armor}",  sprintf("%d", rint(this.m_armordamage / DAMAGETEXT_PRECISION_MULTIPLIER)), s);
-            s = strreplace("{total}",  sprintf("%d", rint((this.m_damage + this.m_armordamage) / DAMAGETEXT_PRECISION_MULTIPLIER)), s);
+            s = strreplace("{potential}",  sprintf("%d", potential), s);
+            s = strreplace("{potential_health}",  sprintf("%d", potential_health), s);
+
+            s = strreplace("{health}", (
+                               (health == potential_health || !autocvar_cl_damagetext_format_verbose)
+                               ? sprintf("%d",      health)
+                               : sprintf("%d (%d)", health, potential_health)
+               ), s);
+            s = strreplace("{total}", (
+                               (total == potential || !autocvar_cl_damagetext_format_verbose)
+                               ? sprintf("%d",      total)
+                               : sprintf("%d (%d)", total, potential)
+               ), s);
             drawcolorcodedstring2_builtin(pos, s, this.m_size * '1 1 0', rgb, this.alpha, DRAWFLAG_NORMAL);
         }
     }
     ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d);
 
-    void DamageText_update(DamageText this, vector _origin, int _health, int _armor, int _deathtype) {
+    void DamageText_update(DamageText this, vector _origin, int _health, int _armor, int _potential_damage, int _deathtype) {
         this.m_damage = _health;
         this.m_armordamage = _armor;
+        this.m_potential_damage = _potential_damage;
         this.m_deathtype = _deathtype;
         setorigin(this, _origin);
         this.alpha = autocvar_cl_damagetext_alpha_start;
     }
 
-    CONSTRUCTOR(DamageText, int _group, vector _origin, int _health, int _armor, int _deathtype, bool _friendlyfire) {
+    CONSTRUCTOR(DamageText, int _group, vector _origin, int _health, int _armor, int _potential_damage, int _deathtype, bool _friendlyfire) {
         CONSTRUCT(DamageText);
         this.m_group = _group;
         this.m_friendlyfire = _friendlyfire;
-        DamageText_update(this, _origin, _health, _armor, _deathtype);
+        DamageText_update(this, _origin, _health, _armor, _potential_damage, _deathtype);
                IL_PUSH(g_drawables_2d, this);
     }
 ENDCLASS(DamageText)
@@ -102,6 +129,7 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
     const float health = M_ARGV(2, float);
     const float armor = M_ARGV(3, float);
     const int deathtype = M_ARGV(5, int);
+    const float potential_damage = M_ARGV(6, float);
     const vector location = hit.origin;
     FOREACH_CLIENT(IS_REAL_CLIENT(it), LAMBDA(
         if (
@@ -110,9 +138,13 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
             (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(it) && it.enemy == attacker) ||
             (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(it))
         ) {
-            int flags = SAME_TEAM(hit, attacker); // BIT(0)
-            if (health >= DAMAGETEXT_SHORT_LIMIT) flags |= BIT(1);
-            if (armor >= DAMAGETEXT_SHORT_LIMIT) flags |= BIT(2);
+            int flags = 0;
+            if (SAME_TEAM(hit, attacker)) flags |= DTFLAG_SAMETEAM;
+            if (health >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_HEALTH;
+            if (armor >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_ARMOR;
+            if (potential_damage >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_POTENTIAL;
+            if (!armor) flags |= DTFLAG_NO_ARMOR;
+            if (fabs((armor + health) - potential_damage) < 0.0001) flags |= DTFLAG_NO_POTENTIAL;
 
             msg_entity = it;
             WriteHeader(MSG_ONE, damagetext);
@@ -126,10 +158,18 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
             // we need to send a few decimal places to minimize errors when accumulating damage
             // sending them multiplied saves bandwidth compared to using WriteCoord,
             // however if the multiplied damage would be too much for (signed) short, we send an int24
-            if (health >= DAMAGETEXT_SHORT_LIMIT) WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
+            if (flags & DTFLAG_BIG_HEALTH) WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
             else WriteShort(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
-            if (armor >= DAMAGETEXT_SHORT_LIMIT) WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
-            else WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
+            if (!(flags & DTFLAG_NO_ARMOR))
+            {
+                if (flags & DTFLAG_BIG_ARMOR) WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
+                else WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
+            }
+            if (!(flags & DTFLAG_NO_POTENTIAL))
+            {
+                if (flags & DTFLAG_BIG_POTENTIAL) WriteInt24_t(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
+                else WriteShort(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
+                       }
         }
     ));
 }
@@ -142,13 +182,17 @@ NET_HANDLE(damagetext, bool isNew)
     vector location = vec3(ReadCoord(), ReadCoord(), ReadCoord());
     int deathtype = ReadInt24_t();
     int flags = ReadByte();
-    bool friendlyfire = flags & 1;
+    bool friendlyfire = flags & DTFLAG_SAMETEAM;
 
-    int health, armor;
-    if (flags & BIT(1)) health = ReadInt24_t();
+    int health, armor, potential_damage;
+    if (flags & DTFLAG_BIG_HEALTH) health = ReadInt24_t();
     else health = ReadShort();
-    if (flags & BIT(2)) armor = ReadInt24_t();
+    if (flags & DTFLAG_NO_ARMOR) armor = 0;
+    else if (flags & DTFLAG_BIG_ARMOR) armor = ReadInt24_t();
     else armor = ReadShort();
+    if (flags & DTFLAG_NO_POTENTIAL) potential_damage = health + armor;
+    else if (flags & DTFLAG_BIG_POTENTIAL) potential_damage = ReadInt24_t();
+    else potential_damage = ReadShort();
 
     return = true;
     if (autocvar_cl_damagetext) {
@@ -158,12 +202,12 @@ NET_HANDLE(damagetext, bool isNew)
         if (autocvar_cl_damagetext_accumulate_range) {
             for (entity e = findradius(location, autocvar_cl_damagetext_accumulate_range); e; e = e.chain) {
                 if (e.instanceOfDamageText && e.m_group == group && e.alpha > autocvar_cl_damagetext_accumulate_alpha_rel * autocvar_cl_damagetext_alpha_start) {
-                    DamageText_update(e, location, e.m_damage + health, e.m_armordamage + armor, deathtype);
+                    DamageText_update(e, location, e.m_damage + health, e.m_armordamage + armor, e.m_potential_damage + potential_damage, deathtype);
                     return;
                 }
             }
         }
-        make_impure(NEW(DamageText, group, location, health, armor, deathtype, friendlyfire));
+        make_impure(NEW(DamageText, group, location, health, armor, potential_damage, deathtype, friendlyfire));
     }
 }
 #endif
@@ -207,6 +251,7 @@ CLASS(XonoticDamageTextSettings, XonoticTab)
                 setDependent(e, "cl_damagetext", 1, 1);
         this.TR(this);
         this.TR(this);
+        // friendly fire
             this.TD(this, 1, 3, e = makeXonoticCheckBox(0, "cl_damagetext_friendlyfire", _("Draw damage numbers for friendly fire")));
                 setDependent(e, "cl_damagetext", 1, 1);
         this.TR(this);
index d20814c..fb1502d 100644 (file)
@@ -109,13 +109,13 @@ bool check_close_to_ground(entity this, float threshold)
        return IS_ONGROUND(this) ? true : false;
 }
 
-float PM_dodging_checkpressedkeys(entity this)
+bool PM_dodging_checkpressedkeys(entity this)
 {
        if(!PHYS_DODGING)
                return false;
 
-       float frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN(this));
-       float frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
+       bool frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN(this));
+       bool frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
 
        // first check if the last dodge is far enough back in time so we can dodge again
        if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
@@ -138,7 +138,9 @@ float PM_dodging_checkpressedkeys(entity this)
                if(!(PHYS_DODGING_PRESSED_KEYS(this) & KEY_##BTN) || frozen_no_doubletap) {             \
                                tap_direction_##RESULT;                                                                                                 \
                                if ((time - this.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(this) || frozen_no_doubletap)    \
-                                       dodge_detected = true;                                                                                                  \
+                                       dodge_detected = true;                                                                                          \
+                               if(PHYS_INPUT_BUTTON_DODGE(this))                                                                               \
+                                       dodge_detected = true;                                                                                          \
                                this.last_##BTN##_KEY_time = time;                                                                              \
                }
        X(x < 0, BACKWARD,      x--);
index 6135e72..4c6dc15 100644 (file)
@@ -360,6 +360,12 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, SetStartItems)
        start_items |= IT_UNLIMITED_SUPERWEAPONS;
 }
 
+MUTATOR_HOOKFUNCTION(mutator_instagib, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 void replace_with_insta_cells(entity item)
 {
        entity e = spawn();
index a834749..a542921 100644 (file)
@@ -8,6 +8,12 @@ MUTATOR_HOOKFUNCTION(melee_only, SetStartItems, CBC_ORDER_LAST)
        start_weapons = warmup_start_weapons = WEPSET(SHOTGUN);
 }
 
+MUTATOR_HOOKFUNCTION(melee_only, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
 {
        return true;
@@ -17,10 +23,10 @@ MUTATOR_HOOKFUNCTION(melee_only, FilterItem)
 {
        entity item = M_ARGV(0, entity);
 
-       switch (item.items)
+       switch (item.itemdef)
        {
-               case ITEM_HealthSmall.m_itemid:
-               case ITEM_ArmorSmall.m_itemid:
+               case ITEM_HealthSmall:
+               case ITEM_ArmorSmall:
                        return false;
        }
 
index 0d804a9..c09e221 100644 (file)
@@ -153,12 +153,14 @@ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expan
 REGISTER_MUTATOR(nades, cvar("g_nades"));
 
 .float nade_time_primed;
+.float nade_lifetime;
 
 .entity nade_spawnloc;
 
+
 void nade_timer_think(entity this)
 {
-       this.skin = 8 - (this.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
+       this.skin = 8 - (this.owner.wait - time) / (this.owner.nade_lifetime / 10);
        this.nextthink = time;
        if(!this.owner || wasfreed(this.owner))
                delete(this);
@@ -862,7 +864,7 @@ void nade_damage(entity this, entity inflictor, entity attacker, float damage, i
        if(this.health == this.max_health)
        {
                sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
-               this.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
+               this.nextthink = max(time + this.nade_lifetime, time);
                setthink(this, nade_beep);
        }
 
@@ -1048,6 +1050,7 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        setthink(n, nade_beep);
        n.nextthink = max(n.wait - 3, time);
        n.projectiledeathtype = DEATH_NADE.m_id;
+       n.nade_lifetime = ntime;
 
        setmodel(fn, MDL_NADE_VIEW);
        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
@@ -1174,18 +1177,6 @@ CLASS(NadeOffhand, OffhandWeapon)
     METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
     {
        entity held_nade = player.nade;
-               if (held_nade)
-               {
-                       player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
-                       // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
-                       makevectors(player.angles);
-                       held_nade.velocity = player.velocity;
-                       setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
-                       held_nade.angles_y = player.angles.y;
-
-                       if (time + 0.1 >= held_nade.wait)
-                               toss_nade(player, false, '0 0 0', time + 0.05);
-               }
 
         if (!CanThrowNade(player)) return;
         if (!(time > player.nade_refire)) return;
@@ -1227,6 +1218,20 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
 
        if (player.nade && (player.offhand != OFFHAND_NADE || (player.weapons & WEPSET(HOOK)))) OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
 
+       entity held_nade = player.nade;
+       if (held_nade)
+       {
+               player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / held_nade.nade_lifetime, 1);
+               // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
+               makevectors(player.angles);
+               held_nade.velocity = player.velocity;
+               setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
+               held_nade.angles_y = player.angles.y;
+
+               if (time + 0.1 >= held_nade.wait)
+                       toss_nade(player, false, '0 0 0', time + 0.05);
+       }
+
        if(IS_PLAYER(player))
        {
                if ( autocvar_g_nades_bonus && autocvar_g_nades )
index 95e3082..143b3c6 100644 (file)
@@ -232,24 +232,13 @@ MUTATOR_HOOKFUNCTION(nix, FilterItem)
 {
        entity item = M_ARGV(0, entity);
 
-       switch (item.items)
+       if(item.itemdef.instanceOfHealth || item.itemdef.instanceOfArmor)
        {
-               case ITEM_HealthSmall.m_itemid:
-               case ITEM_HealthMedium.m_itemid:
-               case ITEM_HealthBig.m_itemid:
-               case ITEM_HealthMega.m_itemid:
-               case ITEM_ArmorSmall.m_itemid:
-               case ITEM_ArmorMedium.m_itemid:
-               case ITEM_ArmorBig.m_itemid:
-               case ITEM_ArmorMega.m_itemid:
-                       if (autocvar_g_nix_with_healtharmor)
-                               return false;
-                       break;
-               case ITEM_Strength.m_itemid:
-               case ITEM_Shield.m_itemid:
-                       if (autocvar_g_nix_with_powerups)
-                               return false;
-                       break;
+               return !autocvar_g_nix_with_healtharmor;
+       }
+       else if(item.itemdef.instanceOfPowerup)
+       {
+               return !autocvar_g_nix_with_powerups;
        }
 
        return true; // delete all other items
index f9cd2b9..dc1a2e5 100644 (file)
@@ -339,6 +339,12 @@ MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
        start_weapons = warmup_start_weapons = ok_start_items;
 }
 
+MUTATOR_HOOKFUNCTION(ok, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsString)
 {
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ":OK");
index 123b8ca..5f11777 100644 (file)
@@ -1,10 +1,13 @@
 #include "sv_spawn_near_teammate.qh"
 
+const float FLOAT_MAX = 340282346638528859811704183484516925440.0f;
+
 float autocvar_g_spawn_near_teammate_distance;
 int autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+int autocvar_g_spawn_near_teammate_ignore_spawnpoint_max;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
 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_check_health;
 bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
 
 REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
@@ -12,7 +15,6 @@ REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
 .entity msnt_lookat;
 
 .float msnt_timer;
-.vector msnt_deathloc;
 
 .float cvar_cl_spawn_near_teammate;
 
@@ -80,86 +82,126 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
                        player.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
 
                entity best_mate = NULL;
-               vector best_spot = '0 0 0';
-               float pc = 0, best_dist = 0, dist = 0;
-               FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
-                       if((autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health >= 0 && it.health >= autocvar_g_balance_health_regenstable) || autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health == 0)
-                       if(!IS_DEAD(it))
-                       if(it.msnt_timer < time)
-                       if(SAME_TEAM(player, it))
-                       if(time > it.spawnshieldtime) // spawn shielding
-                       if(!forbidWeaponUse(it))
-                       if(STAT(FROZEN, it) == 0)
-                       if(it != player)
+               vector best_pos = '0 0 0';
+               float best_dist2 = FLOAT_MAX;
+               int tested = 0;
+               FOREACH_CLIENT_RANDOM(IS_PLAYER(it), LAMBDA(
+                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_max && tested >= autocvar_g_spawn_near_teammate_ignore_spawnpoint_max) break;
+
+                       if (PHYS_INPUT_BUTTON_CHAT(it)) continue;
+                       if (!SAME_TEAM(player, it)) continue;
+                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && it.health < autocvar_g_balance_health_regenstable) continue;
+                       if (IS_DEAD(it)) continue;
+                       if (time < it.msnt_timer) continue;
+                       if (time < it.spawnshieldtime) continue;
+                       if (forbidWeaponUse(it)) continue;
+                       if (it == player) continue;
+
+                       tested++; // i consider a teammate to be available when he passes the checks above
+
+                       vector horiz_vel = vec2(it.velocity);
+                       // when walking slowly sideways, we assume the player wants a clear shot ahead - spawn behind him according to where he's looking
+                       // when running fast, spawn behind him according to his direction of movement to prevent colliding with the newly spawned player
+                       if (vdist(horiz_vel, >, autocvar_sv_maxspeed + 50))
+                               fixedmakevectors(vectoangles(horiz_vel));
+                       else
+                               fixedmakevectors(it.angles); // .angles is the angle of the model - usually/always 0 pitch
+
+                       // test different spots close to mate - trace upwards so it works on uneven surfaces
+                       // don't spawn in front of player or directly behind to avoid players shooting each other
+                       // test the potential spots in pairs (first pair is better than second and so on) but don't prefer one side
+                       RandomSelection_Init();
+                       for(int i = 0; i < 6; ++i)
                        {
-                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - '0 0 100', MOVE_NOMONSTERS, it);
-                               if(trace_fraction != 1.0)
-                               if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
+                               switch(i)
                                {
-                                       pc = pointcontents(trace_endpos + '0 0 1');
-                                       if(pc == CONTENT_EMPTY)
+                                       case 0:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 + v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 1:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 - v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 2:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 3:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 4:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 + v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 5:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 - v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                               }
+
+                               vector horizontal_trace_endpos = trace_endpos;
+                               //te_lightning1(NULL, it.origin, horizontal_trace_endpos);
+                               if (trace_fraction != 1.0) goto skip;
+
+                               // 400 is about the height of a typical laser jump (in overkill)
+                               // not traceline because we need space for the whole player, not just his origin
+                               tracebox(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), horizontal_trace_endpos - '0 0 400', MOVE_NORMAL, it);
+                               vector vectical_trace_endpos = trace_endpos;
+                               //te_lightning1(NULL, horizontal_trace_endpos, vectical_trace_endpos);
+                               if (trace_startsolid) goto skip; // inside another player
+                               if (trace_fraction == 1.0) goto skip; // above void or too high
+                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) goto skip;
+                               if (pointcontents(vectical_trace_endpos) != CONTENT_EMPTY) goto skip; // no lava or slime (or water which i assume would be annoying anyway)
+                               if (tracebox_hits_trigger_hurt(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), vectical_trace_endpos)) goto skip;
+
+                               // make sure the spawned player will have floor ahead (or at least a wall - he shouldn't fall as soon as he starts moving)
+                               vector floor_test_start = vectical_trace_endpos + v_up * STAT(PL_MAX, NULL).z + v_forward * STAT(PL_MAX, NULL).x; // top front of player's bbox - highest point we know is not inside solid
+                               traceline(floor_test_start, floor_test_start + v_forward * 100 - v_up * 128, MOVE_NOMONSTERS, it);
+                               //te_beam(NULL, floor_test_start, trace_endpos);
+                               if (trace_fraction == 1.0) goto skip;
+
+                               if (autocvar_g_nades) {
+                                       bool nade_in_range = false;
+                                       IL_EACH(g_projectiles, it.classname == "nade",
                                        {
-                                               if(vdist(it.velocity, >, 5))
-                                                       fixedmakevectors(vectoangles(it.velocity));
-                                               else
-                                                       fixedmakevectors(it.angles);
+                                               if (vdist(it.origin - vectical_trace_endpos, <, autocvar_g_nades_nade_radius)) {
+                                                       nade_in_range = true;
+                                                       goto skip;
+                                               }
+                                       });
+                                       if (nade_in_range) goto skip;
+                               }
+
+                               // here, we know we found a good spot
+                               RandomSelection_Add(it, 0, string_null, vectical_trace_endpos, 1, 1);
+                               //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + v_forward * 10);
 
-                                               for(pc = 0; pc < 4; ++pc) // test 4 diffrent spots close to mate
+LABEL(skip)
+                               if (i % 2 == 1 && RandomSelection_chosen_ent)
+                               {
+                                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
+                                       {
+                                               float dist2 = vlen2(RandomSelection_chosen_ent.origin - player.death_origin);
+                                               if (dist2 < best_dist2)
                                                {
-                                                       switch(pc)
-                                                       {
-                                                               case 0:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 1:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 , MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 2:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 3:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               //case 4:
-                                                                       //tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128, MOVE_NOMONSTERS, it);
-                                                                       //break;
-                                                       }
-
-                                                       if(trace_fraction == 1.0)
-                                                       {
-                                                               traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NOMONSTERS, it);
-                                                               if(trace_fraction != 1.0)
-                                                               {
-                                                                       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
-                                                                       {
-                                                                               dist = vlen(trace_endpos - player.msnt_deathloc);
-                                                                               if(dist < best_dist || best_dist == 0)
-                                                                               {
-                                                                                       best_dist = dist;
-                                                                                       best_spot = trace_endpos;
-                                                                                       best_mate = it;
-                                                                               }
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               setorigin(player, trace_endpos);
-                                                                               player.angles = it.angles;
-                                                                               player.angles_z = 0; // never spawn tilted even if the spot says to
-                                                                               it.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
-                                                                               return;
-                                                                       }
-                                                               }
-                                                       }
+                                                       best_dist2 = dist2;
+                                                       best_pos = RandomSelection_chosen_vec;
+                                                       best_mate = RandomSelection_chosen_ent;
                                                }
                                        }
+                                       else
+                                       {
+                                               setorigin(player, RandomSelection_chosen_vec);
+                                               player.angles = RandomSelection_chosen_ent.angles;
+                                               player.angles_z = 0; // never spawn tilted even if the spot says to
+                                               RandomSelection_chosen_ent.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+                                               return;
+                                       }
+                                       break; // don't test the other spots near this teammate, go to the next one
                                }
                        }
                ));
 
                if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
-               if(best_dist)
+               if(best_mate)
                {
-                       setorigin(player, best_spot);
+                       setorigin(player, best_pos);
                        player.angles = best_mate.angles;
                        player.angles_z = 0; // never spawn tilted even if the spot says to
                        best_mate.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
@@ -178,11 +220,4 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
        }
 }
 
-MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerDies)
-{
-       entity frag_target = M_ARGV(0, entity);
-
-       frag_target.msnt_deathloc = frag_target.origin;
-}
-
 REPLICATE(cvar_cl_spawn_near_teammate, bool, "cl_spawn_near_teammate");
index e7a3356..a26441e 100644 (file)
@@ -475,13 +475,13 @@ void Draw_WaypointSprite(entity this)
 
     InterpolateOrigin_Do(this);
 
-    float t = entcs_GetTeam(player_localnum) + 1;
     string spriteimage = "";
 
     // choose the sprite
     switch (this.rule)
     {
         case SPRITERULE_SPECTATOR:
+            float t = entcs_GetTeam(player_localnum) + 1;
             if (!(
                 (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1)
             || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage || STAT(ITEMSTIME) == 2))
@@ -492,7 +492,7 @@ void Draw_WaypointSprite(entity this)
         case SPRITERULE_DEFAULT:
             if (this.team)
             {
-                if (this.team == t)
+                if (this.team == myteam + 1)
                     spriteimage = this.netname;
                 else
                     spriteimage = "";
@@ -501,9 +501,9 @@ void Draw_WaypointSprite(entity this)
                 spriteimage = this.netname;
             break;
         case SPRITERULE_TEAMPLAY:
-            if (t == NUM_SPECTATOR + 1)
+            if (myteam == NUM_SPECTATOR)
                 spriteimage = this.netname3;
-            else if (this.team == t)
+            else if (this.team == myteam + 1)
                 spriteimage = this.netname2;
             else
                 spriteimage = this.netname;
@@ -613,7 +613,7 @@ void Draw_WaypointSprite(entity this)
 
     float crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
 
-    t = waypointsprite_scale;
+    float t = waypointsprite_scale;
     a *= waypointsprite_alpha;
 
     {
index d2682a1..5e5fbf1 100644 (file)
@@ -200,8 +200,8 @@ GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt"
        }
 }
 
-float autocvar_notification_debug = false;
 #ifdef NOTIFICATIONS_DEBUG
+bool autocvar_notification_debug = false;
 void Debug_Notification(string input)
 {
        switch (autocvar_notification_debug)
@@ -297,8 +297,10 @@ float autocvar_notification_show_sprees_info = 3; // 0 = off, 1 = target only, 2
 float autocvar_notification_show_sprees_info_newline = true;
 float autocvar_notification_show_sprees_info_specialonly = true;
 float autocvar_notification_errors_are_fatal = true;
+#ifdef SVQC
 float autocvar_notification_lifetime_runtime = 0.5;
 float autocvar_notification_lifetime_mapload = 10;
+#endif
 
 #ifdef SVQC
 .float FRAG_VERBOSE;
index 729928b..f0df80c 100644 (file)
@@ -510,9 +510,9 @@ void makevectors_matrix(vector myangles)  // AngleVectorsFLU
 {
        v_forward = v_right = v_up = '0 0 0';
 
-       float y = myangles.y * (M_PI * 2 / 360);
-       float sy = sin(y);
-       float cy = cos(y);
+       float yy = myangles.y * (M_PI * 2 / 360);
+       float sy = sin(yy);
+       float cy = cos(yy);
        float p = myangles.x * (M_PI * 2 / 360);
        float sp = sin(p);
        float cp = cos(p);
index b5635e0..2645415 100644 (file)
@@ -481,15 +481,15 @@ float racecar_angle(float forward, float down)
                return ret * angle_mult;
 }
 
+#ifdef SVQC
 string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
 .float specialcommand_pos;
 void SpecialCommand(entity this)
 {
-#ifdef SVQC
        if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
                LOG_INFO("A hollow voice says \"Plugh\".\n");
-#endif
 }
+#endif
 
 bool PM_check_specialcommand(entity this, int buttons)
 {
index 5c0b104..39cc573 100644 (file)
@@ -121,6 +121,7 @@ STATIC_INIT(PHYS_INPUT_BUTTON_HOOK)
 #define PHYS_INPUT_BUTTON_PRYDON(s)         PHYS_INPUT_BUTTON_BUTTON_PRYDON(s)
 #define PHYS_INPUT_BUTTON_ZOOMSCRIPT(s)     PHYS_INPUT_BUTTON_BUTTON9(s)
 #define PHYS_INPUT_BUTTON_JETPACK(s)        PHYS_INPUT_BUTTON_BUTTON10(s)
+#define PHYS_INPUT_BUTTON_DODGE(s)                     PHYS_INPUT_BUTTON_BUTTON11(s)
 
 #ifdef CSQC
 STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
@@ -128,6 +129,12 @@ STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
        localcmd("alias +jetpack +button10\n");
     localcmd("alias -jetpack -button10\n");
 }
+
+STATIC_INIT(PHYS_INPUT_BUTTON_DODGE)
+{
+    localcmd("alias +dodge +button11\n");
+    localcmd("alias -dodge -button11\n");
+}
 #endif
 
 // if more buttons are needed, start using impulse bits as buttons
index 4dab611..b879b63 100644 (file)
@@ -5,9 +5,10 @@
     #include "constants.qh"
     #include "util.qh"
     #include <common/weapons/_all.qh>
-    #include "../server/weapons/accuracy.qh"
+    #include "../server/anticheat.qh"
     #include "../server/defs.qh"
     #include "../server/scores.qh"
+    #include "../server/weapons/accuracy.qh"
 #endif
 
 #ifdef SVQC
@@ -141,6 +142,7 @@ void PlayerStats_GameReport_FinalizePlayer(entity p)
                PS_GR_P_ADDVAL(p, PLAYERSTATS_JOINS, 1);
 
        PlayerStats_GameReport_Accuracy(p);
+       anticheat_report_to_playerstats(p);
 
        if(IS_REAL_CLIENT(p))
        {
@@ -249,6 +251,8 @@ void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE);
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD);
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM);
+
+               anticheat_register_to_playerstats();
        }
        else { PlayerStats_GameReport_DelayMapVote = false; }
 }
index 73496ba..1fafb13 100644 (file)
@@ -40,6 +40,7 @@ const string PLAYERSTATS_SCOREBOARD_POS = "scoreboardpos";
 
 const string PLAYERSTATS_TOTAL = "total-";
 const string PLAYERSTATS_SCOREBOARD = "scoreboard-";
+const string PLAYERSTATS_ANTICHEAT = "anticheat-";
 
 const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3 = "achievement-kill-spree-3";
 const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5 = "achievement-kill-spree-5";
index 891461c..1a2fb1e 100644 (file)
@@ -63,7 +63,7 @@ void ClientState_attach(entity this)
 
 void bot_clientdisconnect(entity this);
 void W_HitPlotClose(entity this);
-void anticheat_report(entity this);
+void anticheat_report_to_eventlog(entity this);
 void playerdemo_shutdown(entity this);
 void entcs_detach(entity this);
 void accuracy_free(entity this);
@@ -80,7 +80,7 @@ void ClientState_detach(entity this)
     bot_clientdisconnect(this);
 
     W_HitPlotClose(this);
-    anticheat_report(this);
+    anticheat_report_to_eventlog(this);
     playerdemo_shutdown(this);
     entcs_detach(this);
     accuracy_free(this);
index e37e528..19aa6ba 100644 (file)
@@ -82,6 +82,11 @@ void ItemDraw(entity this)
                 if(this.ItemStatus & ITS_ANIMATE2)
                     this.avelocity = '0 -90 0';
             }
+
+            // delay is for blocking item's position for a while;
+            // it's a workaround for dropped weapons that receive the position
+            // another time right after they spawn overriding animation position
+            this.onground_time = time + 0.5;
         }
     }
     else if (autocvar_cl_animate_items)
@@ -89,13 +94,15 @@ void ItemDraw(entity this)
         if(this.ItemStatus & ITS_ANIMATE1)
         {
             this.angles += this.avelocity * frametime;
-            setorigin(this, '0 0 10' + this.oldorigin + '0 0 8' * sin(time * 2));
+            float fade_in = bound(0, time - this.onground_time, 1);
+            setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
         }
 
         if(this.ItemStatus & ITS_ANIMATE2)
         {
             this.angles += this.avelocity * frametime;
-            setorigin(this, '0 0 8' + this.oldorigin + '0 0 4' * sin(time * 3));
+            float fade_in = bound(0, time - this.onground_time, 1);
+            setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
         }
     }
 
@@ -183,7 +190,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
             if(this.ItemStatus & ITS_ALLOWFB)
                 this.effects |= EF_FULLBRIGHT;
 
-        if(this.ItemStatus & ITS_POWERUP)
+        if(this.ItemStatus & ITS_GLOW)
         {
             if(this.ItemStatus & ITS_AVAILABLE)
                 this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
@@ -423,6 +430,7 @@ void Item_Show (entity e, float mode)
 {
        e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST);
        e.ItemStatus &= ~ITS_STAYWEP;
+       entity def = e.itemdef;
        if (mode > 0)
        {
                // make the item look normal, and be touchable
@@ -440,7 +448,6 @@ void Item_Show (entity e, float mode)
                e.ItemStatus &= ~ITS_AVAILABLE;
        }
        else {
-       entity def = e.itemdef;
        bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.weapons & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons
                || e.team // weapon stay isn't supported for teamed weapons
                ;
@@ -463,8 +470,8 @@ void Item_Show (entity e, float mode)
                e.ItemStatus &= ~ITS_AVAILABLE;
        }}
 
-       if (e.items & ITEM_Strength.m_itemid || e.items & ITEM_Shield.m_itemid)
-               e.ItemStatus |= ITS_POWERUP;
+       if (def.m_glow)
+               e.ItemStatus |= ITS_GLOW;
 
        if (autocvar_g_nodepthtestitems)
                e.effects |= EF_NODEPTHTEST;
@@ -497,13 +504,7 @@ void Item_ItemsTime_SetTimesForAllPlayers();
 void Item_Respawn (entity this)
 {
        Item_Show(this, 1);
-       // this is ugly...
-       if(this.items == ITEM_Strength.m_itemid)
-               sound (this, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTEN_NORM);   // play respawn sound
-       else if(this.items == ITEM_Shield.m_itemid)
-               sound (this, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTEN_NORM);     // play respawn sound
-       else
-               sound (this, CH_TRIGGER, SND_ITEMRESPAWN, VOL_BASE, ATTEN_NORM);        // play respawn sound
+       sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM);     // play respawn sound
        setorigin(this, this.origin);
 
     if (Item_ItemsTime_Allow(this.itemdef) || this.weapons & WEPSET_SUPERWEAPONS)
@@ -837,7 +838,7 @@ LABEL(pickup)
                        RandomSelection_Init();
                        IL_EACH(g_items, it.team == this.team,
                        {
-                               if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
+                               if(it.itemdef) // is a registered item
                                {
                                        Item_Show(it, -1);
                                        RandomSelection_AddEnt(it, it.cnt, 0);
@@ -881,7 +882,7 @@ void Item_FindTeam(entity this)
                RandomSelection_Init();
                IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
+                       if(it.itemdef) // is a registered item
                                RandomSelection_AddEnt(it, it.cnt, 0);
                });
 
@@ -891,7 +892,7 @@ void Item_FindTeam(entity this)
 
                IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
+                       if(it.itemdef) // is a registered item
                        {
                                if(it != e)
                                {
@@ -1797,6 +1798,7 @@ float GiveItems(entity e, float beginarg, float endarg)
        });
        POSTGIVE_VALUE(e, strength_finished, 1, SND_POWERUP, SND_POWEROFF);
        POSTGIVE_VALUE(e, invincible_finished, 1, SND_Shield, SND_POWEROFF);
+       //POSTGIVE_VALUE(e, superweapons_finished, 1, SND_Null, SND_Null);
        POSTGIVE_VALUE(e, ammo_nails, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_VALUE(e, ammo_cells, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_VALUE(e, ammo_plasma, 0, SND_ITEMPICKUP, SND_Null);
index 06e1455..418ce39 100644 (file)
@@ -12,7 +12,7 @@ const int ISF_STATUS                  = BIT(3);
     const int ITS_AVAILABLE        = BIT(3);
     const int ITS_ALLOWFB                  = BIT(4);
     const int ITS_ALLOWSI                  = BIT(5);
-    const int ITS_POWERUP                  = BIT(6);
+    const int ITS_GLOW                     = BIT(6);
 const int ISF_COLORMAP                         = BIT(4);
 const int ISF_DROP                             = BIT(5);
 const int ISF_ANGLES                   = BIT(6);
@@ -20,6 +20,7 @@ const int ISF_SIZE                            = BIT(7);
 
 .int ItemStatus;
 
+.float onground_time;
 .float fade_start;
 .float fade_end;
 
index dd9eaac..2e4356b 100644 (file)
@@ -1,5 +1,6 @@
 #include "train.qh"
 .float train_wait_turning;
+.entity future_target;
 void train_next(entity this);
 #ifdef SVQC
 void train_use(entity this, entity actor, entity trigger);
@@ -14,7 +15,7 @@ void train_wait(entity this)
        {
                entity targ, cp;
                vector ang;
-               targ = find(NULL, targetname, this.target);
+               targ = this.future_target;
                if((this.spawnflags & 1) && targ.curvetarget)
                        cp = find(NULL, targetname, targ.curvetarget);
                else
@@ -41,7 +42,7 @@ void train_wait(entity this)
 #endif
 
 #ifdef SVQC
-       entity tg = find(NULL, targetname, this.target);
+       entity tg = this.future_target;
        if(tg.spawnflags & 4)
        {
                this.use = train_use;
@@ -62,13 +63,34 @@ void train_wait(entity this)
        }
 }
 
+entity train_next_find(entity this)
+{
+       if(this.target_random)
+       {
+               RandomSelection_Init();
+               for(entity t = NULL; (t = find(t, targetname, this.target));)
+               {
+                       RandomSelection_AddEnt(t, 1, 0);
+               }
+               return RandomSelection_chosen_ent;
+       }
+       else
+       {
+               return find(NULL, targetname, this.target);
+       }
+}
+
 void train_next(entity this)
 {
-       entity targ, cp = NULL;
+       entity targ = NULL, cp = NULL;
        vector cp_org = '0 0 0';
 
-       targ = find(NULL, targetname, this.target);
+       targ = this.future_target;
+
        this.target = targ.target;
+       this.target_random = targ.target_random;
+       this.future_target = train_next_find(targ);
+
        if (this.spawnflags & 1)
        {
                if(targ.curvetarget)
@@ -186,9 +208,11 @@ void train_use(entity this, entity actor, entity trigger)
 
 void func_train_find(entity this)
 {
-       entity targ;
-       targ = find(NULL, targetname, this.target);
+       entity targ = train_next_find(this);
        this.target = targ.target;
+       this.target_random = targ.target_random;
+       // save the future target for later
+       this.future_target = train_next_find(targ);
        if (this.target == "")
                objerror(this, "func_train_find: no next target");
        SUB_SETORIGIN(this, targ.origin - this.view_ofs);
index c21e327..48c6a87 100644 (file)
@@ -67,13 +67,12 @@ void turret_draw2d(entity this)
                return;
 
        float dist = vlen(this.origin - view_origin);
-       float t = (entcs_GetTeam(player_localnum) + 1);
 
        vector o;
        string txt;
 
        if(autocvar_cl_vehicles_hud_tactical)
-       if(dist < 10240 && t != this.team)
+       if(dist < 10240 && (myteam + 1 != this.team))
        {
                // TODO: Vehicle tactical hud
                o = project_3d_to_2d(this.origin + '0 0 32');
@@ -121,7 +120,7 @@ void turret_draw2d(entity this)
        else
                txt = spritelookuptext(this, spriteimage);
 
-       if(time - floor(time) > 0.5 && t == this.team)
+       if(time - floor(time) > 0.5 && (myteam + 1 == this.team))
        {
                if(this.helpme && time < this.helpme)
                {
@@ -163,7 +162,7 @@ void turret_draw2d(entity this)
 
        float crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
 
-       t = waypointsprite_scale;
+       float t = waypointsprite_scale;
        a *= waypointsprite_alpha;
 
        {
index 2b1e00c..68cac08 100644 (file)
@@ -28,12 +28,12 @@ float T_Config_Queue_Compare(float root, float child, entity pass)
 
 void Dump_Turret_Settings()
 {
-       float x, totalsettings = 0;
+       int totalsettings = 0;
        FOREACH(Turrets, it != TUR_Null, {
                // step 1: clear the queue
                TUR_CONFIG_COUNT = 0;
-               for(x = 0; x <= MAX_TUR_CONFIG; ++x)
-                       { tur_config_queue[x] = string_null; }
+               for(int j = 0; j <= MAX_TUR_CONFIG; ++j)
+                       { tur_config_queue[j] = string_null; }
 
                // step 2: build new queue
                it.tr_config(it);
@@ -43,8 +43,8 @@ void Dump_Turret_Settings()
 
                // step 4: write queue
                TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, it.turret_name))
-               for(x = 0; x <= TUR_CONFIG_COUNT; ++x)
-                       { TUR_CONFIG_WRITETOFILE(tur_config_queue[x]) }
+               for(int j = 0; j <= TUR_CONFIG_COUNT; ++j)
+                       { TUR_CONFIG_WRITETOFILE(tur_config_queue[j]) }
                TUR_CONFIG_WRITETOFILE("// }}}\n")
 
                // step 5: debug info
@@ -54,8 +54,8 @@ void Dump_Turret_Settings()
 
        // clear queue now that we're finished
        TUR_CONFIG_COUNT = 0;
-       for(x = 0; x <= MAX_TUR_CONFIG; ++x)
-               { tur_config_queue[x] = string_null; }
+       for(int j = 0; j <= MAX_TUR_CONFIG; ++j)
+               { tur_config_queue[j] = string_null; }
 
        // extra information
        LOG_INFO(sprintf("Totals: %d turrets, %d settings\n", (Turrets_COUNT - 1), totalsettings));
index 87636d2..d838710 100644 (file)
@@ -228,13 +228,13 @@ string ScoreString(int pFlags, float pValue)
 
 float lengthLogTable[128];
 
-float invertLengthLog(float x)
+float invertLengthLog(float dist)
 {
        int l, r, m;
 
-       if(x >= lengthLogTable[127])
+       if(dist >= lengthLogTable[127])
                return 127;
-       if(x <= lengthLogTable[0])
+       if(dist <= lengthLogTable[0])
                return 0;
 
        l = 0;
@@ -243,15 +243,15 @@ float invertLengthLog(float x)
        while(r - l > 1)
        {
                m = floor((l + r) / 2);
-               if(lengthLogTable[m] < x)
+               if(lengthLogTable[m] < dist)
                        l = m;
                else
                        r = m;
        }
 
        // now: r is >=, l is <
-       float lerr = (x - lengthLogTable[l]);
-       float rerr = (lengthLogTable[r] - x);
+       float lerr = (dist - lengthLogTable[l]);
+       float rerr = (lengthLogTable[r] - dist);
        if(lerr < rerr)
                return l;
        return r;
@@ -263,26 +263,26 @@ vector decompressShortVector(int data)
        if(data == 0)
                return '0 0 0';
        float p = (data & 0xF000) / 0x1000;
-       float y = (data & 0x0F80) / 0x80;
+       float q = (data & 0x0F80) / 0x80;
        int len = (data & 0x007F);
 
-       //print("\ndecompress: p ", ftos(p)); print("y ", ftos(y)); print("len ", ftos(len), "\n");
+       //print("\ndecompress: p ", ftos(p)); print("q ", ftos(q)); print("len ", ftos(len), "\n");
 
        if(p == 0)
        {
                out.x = 0;
                out.y = 0;
-               if(y == 31)
+               if(q == 31)
                        out.z = -1;
                else
                        out.z = +1;
        }
        else
        {
-               y   = .19634954084936207740 * y;
+               q   = .19634954084936207740 * q;
                p = .19634954084936207740 * p - 1.57079632679489661922;
-               out.x = cos(y) *  cos(p);
-               out.y = sin(y) *  cos(p);
+               out.x = cos(q) *  cos(p);
+               out.y = sin(q) *  cos(p);
                out.z =          -sin(p);
        }
 
@@ -1073,26 +1073,25 @@ vector get_shotvelocity(vector myvel, vector mydir, float spd, float newton_styl
 
 float compressShotOrigin(vector v)
 {
-       float x, y, z;
-       x = rint(v.x * 2);
-       y = rint(v.y * 4) + 128;
-       z = rint(v.z * 4) + 128;
-       if(x > 255 || x < 0)
+       float rx = rint(v.x * 2);
+       float ry = rint(v.y * 4) + 128;
+       float rz = rint(v.z * 4) + 128;
+       if(rx > 255 || rx < 0)
        {
                LOG_INFO("shot origin ", vtos(v), " x out of bounds\n");
-               x = bound(0, x, 255);
+               rx = bound(0, rx, 255);
        }
-       if(y > 255 || y < 0)
+       if(ry > 255 || ry < 0)
        {
                LOG_INFO("shot origin ", vtos(v), " y out of bounds\n");
-               y = bound(0, y, 255);
+               ry = bound(0, ry, 255);
        }
-       if(z > 255 || z < 0)
+       if(rz > 255 || rz < 0)
        {
                LOG_INFO("shot origin ", vtos(v), " z out of bounds\n");
-               z = bound(0, z, 255);
+               rz = bound(0, rz, 255);
        }
-       return x * 0x10000 + y * 0x100 + z;
+       return rx * 0x10000 + ry * 0x100 + rz;
 }
 vector decompressShotOrigin(int f)
 {
index 57f9a22..05e4a4e 100644 (file)
@@ -103,7 +103,7 @@ float almost_equals(float a, float b);
 float almost_in_bounds(float a, float b, float c);
 
 float power2of(float e);
-float log2of(float x);
+float log2of(float e);
 
 vector rgb_to_hsl(vector rgb);
 vector hsl_to_rgb(vector hsl);
@@ -238,7 +238,7 @@ void queue_to_execute_next_frame(string s);
 // f(1) = 1
 // f'(0) = startspeedfactor
 // f'(1) = endspeedfactor
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x);
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float spd);
 
 // checks whether f'(x) = 0 anywhere from 0 to 1
 // because if this is the case, the function is not usable for platforms
index d4ed950..e9c5bf4 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <common/weapons/_all.qh>
 
+#ifdef SVQC
 float autocvar_g_vehicle_bumblebee_cannon_cost = 2;
 float autocvar_g_vehicle_bumblebee_cannon_damage = 60;
 float autocvar_g_vehicle_bumblebee_cannon_radius = 225;
@@ -9,6 +10,7 @@ float autocvar_g_vehicle_bumblebee_cannon_refire = 0.2;
 float autocvar_g_vehicle_bumblebee_cannon_speed = 20000;
 float autocvar_g_vehicle_bumblebee_cannon_spread = 0.02;
 float autocvar_g_vehicle_bumblebee_cannon_force = -35;
+#endif
 
 #ifdef SVQC
 void bumblebee_fire_cannon(entity this, entity _gun, string _tagname, entity _owner);
index 41a3174..0cdfc8c 100644 (file)
@@ -35,7 +35,7 @@ float autocvar_g_vehicle_racer_friction = 0.45;
 
 float autocvar_g_vehicle_racer_water_time = 5;
 
-float autocvar_g_vehicle_racer_collision_multiplier = 0.05;
+//float autocvar_g_vehicle_racer_collision_multiplier = 0.05;
 
 // 0 = hover, != 0 = maglev
 int autocvar_g_vehicle_racer_hovertype = 0;
index 51c20ef..f8b18a8 100644 (file)
@@ -15,6 +15,7 @@ REGISTER_WEAPON(RACER, NEW(RacerAttack));
 void racer_fire_rocket(entity player, vector org, vector dir, entity trg);
 #endif
 
+#ifdef SVQC
 float autocvar_g_vehicle_racer_cannon_cost = 2;
 float autocvar_g_vehicle_racer_cannon_damage = 15;
 float autocvar_g_vehicle_racer_cannon_radius = 100;
@@ -33,3 +34,4 @@ float autocvar_g_vehicle_racer_rocket_refire = 3;
 
 float autocvar_g_vehicle_racer_rocket_climbspeed = 1600;
 float autocvar_g_vehicle_racer_rocket_locked_maxangle = 1.8;
+#endif
index 4260d42..a7908d5 100644 (file)
@@ -26,7 +26,7 @@ CLASS(RaptorFlare, PortoLaunch)
 ENDCLASS(RaptorFlare)
 REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
 
-
+#ifdef SVQC
 float autocvar_g_vehicle_raptor_cannon_cost = 1;
 float autocvar_g_vehicle_raptor_cannon_damage = 10;
 float autocvar_g_vehicle_raptor_cannon_radius = 60;
@@ -51,3 +51,4 @@ float autocvar_g_vehicle_raptor_flare_refire = 5;
 float autocvar_g_vehicle_raptor_flare_lifetime = 10;
 float autocvar_g_vehicle_raptor_flare_chase = 0.9;
 float autocvar_g_vehicle_raptor_flare_range = 2000;
+#endif
index 347d212..d99335a 100644 (file)
@@ -603,8 +603,8 @@ METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh, entity instance))
 
 #endif // SVQC
 #ifdef CSQC
-float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
-float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+//float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
+//float autocvar_cl_vehicle_spiderbot_cross_size = 1;
 
 METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh))
 {
index a152304..199d9cf 100644 (file)
@@ -6,6 +6,7 @@
 void spiderbot_rocket_do(entity this);
 #endif
 
+#ifdef SVQC
 // 400 (x2) DPS
 float autocvar_g_vehicle_spiderbot_minigun_damage = 24;
 float autocvar_g_vehicle_spiderbot_minigun_refire = 0.06;
@@ -30,3 +31,4 @@ float autocvar_g_vehicle_spiderbot_rocket_health = 100;
 float autocvar_g_vehicle_spiderbot_rocket_noise = 0.2;
 float autocvar_g_vehicle_spiderbot_rocket_turnrate = 0.25;
 float autocvar_g_vehicle_spiderbot_rocket_lifetime = 20;
+#endif
index 9570e8c..a805ce5 100644 (file)
@@ -143,10 +143,12 @@ X(weaponreplace, string)
 X(weaponstartoverride, float)
 X(weaponstart, float)
 X(weaponthrowable, float)
+#ifdef SVQC
 X(reload_ammo, float)
 .float reloading_ammo = reload_ammo;
 X(reload_time, float)
 .float reloading_time = reload_time;
+#endif
 #undef X
 
 
index d16d733..b287b14 100644 (file)
@@ -117,6 +117,8 @@ CLASS(Weapon, Object)
         // no weapon specific image for this weapon
         return false;
     }
+    /** (CLIENT) weapon specific view model */
+    METHOD(Weapon, wr_viewmodel, string(Weapon this, entity wep)) { return string_null; }
     /** (CLIENT) weapon specific glow */
     METHOD(Weapon, wr_glow, vector(Weapon this, entity actor)) { return '0 0 0'; }
     /** (SERVER) the weapon is dropped */
index 1f01ef0..e3e1f52 100644 (file)
@@ -487,6 +487,15 @@ METHOD(Tuba, wr_killmessage, Notification(Tuba this))
                return WEAPON_TUBA_MURDER;
 }
 
+#elif defined(CSQC)
+
+METHOD(Tuba, wr_viewmodel, string(Tuba this, entity wep))
+{
+       return (wep.tuba_instrument == 0) ? "tuba" :
+              (wep.tuba_instrument == 1) ? "akordeon" :
+                                           "kleinbottle";
+}
+
 #endif
 
 #ifdef CSQC
index a617c73..2d48e57 100644 (file)
@@ -28,8 +28,8 @@
  */
 #define SYSTEM(sys, frameLimit, minfps) \
        void sys_##sys##_update(entity this, float dt); \
-       float autocvar_xon_sys_##sys##_dt = ((frameLimit) ? (1 / (frameLimit)) : 0); \
-       float autocvar_xon_sys_##sys##_minfps = (1 / (1 / (minfps)))
+       noref float autocvar_xon_sys_##sys##_dt = ((frameLimit) ? (1 / (frameLimit)) : 0); \
+       noref float autocvar_xon_sys_##sys##_minfps = (1 / (1 / (minfps)))
 
 #define SYSTEM_UPDATE(sys) \
        MACRO_BEGIN \
index b25c93b..0c18e58 100644 (file)
@@ -160,9 +160,6 @@ void sys_phys_update(entity this, float dt)
 /** for players */
 void sys_phys_simulate(entity this, float dt)
 {
-       const vector g = -this.com_phys_gravity;
-       const bool jump = this.com_in_jump;
-
        if (!this.com_phys_ground && !this.com_phys_air) {
                // noclipping
                // flying
@@ -172,6 +169,7 @@ void sys_phys_simulate(entity this, float dt)
                UNSET_ONGROUND(this);
 
                if (this.com_phys_friction_air) {
+                       const vector g = -this.com_phys_gravity;
                        this.velocity_z += g.z / 2;
                        this.velocity = this.velocity * (1 - dt * this.com_phys_friction);
                        this.velocity_z += g.z / 2;
@@ -181,7 +179,7 @@ void sys_phys_simulate(entity this, float dt)
        if (this.com_phys_water) {
                // water jump only in certain situations
                // this mimics quakeworld code
-               if (jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180 && !this.viewloc) {
+               if (this.com_in_jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180 && !this.viewloc) {
                        vector yawangles = '0 1 0' * this.v_angle.y;
                        makevectors(yawangles);
                        vector forward = v_forward;
@@ -320,7 +318,7 @@ void sys_phys_simulate(entity this, float dt)
                                }
 
                                // holding jump button swims upward slowly
-                               if (jump && !this.viewloc) {
+                               if (this.com_in_jump && !this.viewloc) {
                                        // was:
                                        // lava: 50
                                        // slime: 80
index 904ebba..4973a18 100644 (file)
@@ -37,7 +37,7 @@ void sys_phys_ai(entity this)
 void sys_phys_pregame_hold(entity this)
 {
        if (!IS_PLAYER(this)) { return; }
-       const bool allowed_to_move = (time >= game_starttime);
+       const bool allowed_to_move = (time >= game_starttime && !gameover);
        if (!allowed_to_move) {
                this.velocity = '0 0 0';
                set_movetype(this, MOVETYPE_NONE);
index 6408d6e..65dc080 100644 (file)
@@ -183,6 +183,12 @@ void make_safe_for_remove(entity this);
        void SetChangeParms() { ENGINE_EVENT(); if (_SetChangeParms) _SetChangeParms(this); }
        #define SetChangeParms _SetChangeParms
 
+#ifdef DP_EXT_PRECONNECT
+       void _ClientPreConnect(entity this);
+       void ClientPreConnect() { ENGINE_EVENT(); if (_ClientPreConnect) _ClientPreConnect(this); }
+       #define ClientPreConnect _ClientPreConnect
+#endif
+
        void _ClientConnect(entity this);
        void ClientConnect() { ENGINE_EVENT(); if (_ClientConnect) _ClientConnect(this); }
        #define ClientConnect _ClientConnect
index feb7a82..92d45bf 100644 (file)
@@ -82,12 +82,12 @@ vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
               + (b - a) * 2;
 }
 
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float spd)
 {
        return (((startspeedfactor + endspeedfactor - 2
-                ) * x - 2 * startspeedfactor - endspeedfactor + 3
-               ) * x + startspeedfactor
-              ) * x;
+                ) * spd - 2 * startspeedfactor - endspeedfactor + 3
+               ) * spd + startspeedfactor
+              ) * spd;
 }
 
 bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
@@ -195,54 +195,54 @@ float power2of(float e)
        return pow(2, e);
 }
 
-float log2of(float x)
+float log2of(float e)
 {
        // NOTE: generated code
-       if (x > 2048)
-               if (x > 131072)
-                       if (x > 1048576)
-                               if (x > 4194304) return 23;
+       if (e > 2048)
+               if (e > 131072)
+                       if (e > 1048576)
+                               if (e > 4194304) return 23;
                                else
-                                       if (x > 2097152) return 22;
+                                       if (e > 2097152) return 22;
                                        else return 21;
                        else
-                               if (x > 524288) return 20;
+                               if (e > 524288) return 20;
                                else
-                                       if (x > 262144) return 19;
+                                       if (e > 262144) return 19;
                                        else return 18;
                else
-                       if (x > 16384)
-                               if (x > 65536) return 17;
+                       if (e > 16384)
+                               if (e > 65536) return 17;
                                else
-                                       if (x > 32768) return 16;
+                                       if (e > 32768) return 16;
                                        else return 15;
                        else
-                               if (x > 8192) return 14;
+                               if (e > 8192) return 14;
                                else
-                                       if (x > 4096) return 13;
+                                       if (e > 4096) return 13;
                                        else return 12;
        else
-               if (x > 32)
-                       if (x > 256)
-                               if (x > 1024) return 11;
+               if (e > 32)
+                       if (e > 256)
+                               if (e > 1024) return 11;
                                else
-                                       if (x > 512) return 10;
+                                       if (e > 512) return 10;
                                        else return 9;
                        else
-                               if (x > 128) return 8;
+                               if (e > 128) return 8;
                                else
-                                       if (x > 64) return 7;
+                                       if (e > 64) return 7;
                                        else return 6;
                else
-                       if (x > 4)
-                               if (x > 16) return 5;
+                       if (e > 4)
+                               if (e > 16) return 5;
                                else
-                                       if (x > 8) return 4;
+                                       if (e > 8) return 4;
                                        else return 3;
                        else
-                               if (x > 2) return 2;
+                               if (e > 2) return 2;
                                else
-                                       if (x > 1) return 1;
+                                       if (e > 1) return 1;
                                        else return 0;
 }
 
index 43bd123..f4c246f 100644 (file)
@@ -48,7 +48,7 @@
 
 #define SELFWRAP(T, R, oldargs, args, forward) \
     .R oldargs T; \
-    .R oldargs __##T = T; \
+    noref .R oldargs __##T = T; \
     .R args self##T; \
     R T##_self oldargs { ENGINE_EVENT(); return this.self##T forward; }
 
index 4e3bc06..e8aeaec 100644 (file)
@@ -29,7 +29,7 @@ noref bool require_spawnfunc_prefix;
 
        noref bool __spawnfunc_expecting;
        noref entity __spawnfunc_expect;
-       bool __spawnfunc_unreachable_workaround = true;
+       noref bool __spawnfunc_unreachable_workaround = true;
 
        #define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
        #define spawnfunc_2(id, whitelist) \
index ac3b65f..e190518 100644 (file)
 #elif defined(SVQC)
 #endif
 
-int fpclassify(float x)
+int fpclassify(float e)
 {
-       if(isnan(x))
+       if(isnan(e))
                return FP_NAN;
-       if(isinf(x))
+       if(isinf(e))
                return FP_INFINITE;
-       if(x == 0)
+       if(e == 0)
                return FP_ZERO;
        return FP_NORMAL;
 }
-bool isfinite(float x)
+bool isfinite(float e)
 {
-       return !(isnan(x) || isinf(x));
+       return !(isnan(e) || isinf(e));
 }
-bool isinf(float x)
+bool isinf(float e)
 {
-       return (x != 0) && (x + x == x);
+       return (e != 0) && (e + e == e);
 }
-bool isnan(float x)
+bool isnan(float e)
 {
-       float y;
-       y = x;
-       return (x != y);
+       float f = e;
+       return (e != f);
 }
-bool isnormal(float x)
+bool isnormal(float e)
 {
-       return isfinite(x);
+       return isfinite(e);
 }
-bool signbit(float x)
+bool signbit(float e)
 {
-       return (x < 0);
+       return (e < 0);
 }
 
-float acosh(float x)
+float acosh(float e)
 {
-       return log(x + sqrt(x*x - 1));
+       return log(e + sqrt(e*e - 1));
 }
-float asinh(float x)
+float asinh(float e)
 {
-       return log(x + sqrt(x*x + 1));
+       return log(e + sqrt(e*e + 1));
 }
-float atanh(float x)
+float atanh(float e)
 {
-       return 0.5 * log((1+x) / (1-x));
+       return 0.5 * log((1+e) / (1-e));
 }
-float cosh(float x)
+float cosh(float e)
 {
-       return 0.5 * (exp(x) + exp(-x));
+       return 0.5 * (exp(e) + exp(-e));
 }
-float sinh(float x)
+float sinh(float e)
 {
-       return 0.5 * (exp(x) - exp(-x));
+       return 0.5 * (exp(e) - exp(-e));
 }
-float tanh(float x)
+float tanh(float e)
 {
-       return sinh(x) / cosh(x);
+       return sinh(e) / cosh(e);
 }
 
-float exp(float x)
+float exp(float e)
 {
-       return pow(M_E, x);
+       return pow(M_E, e);
 }
-float exp2(float x)
+float exp2(float e)
 {
-       return pow(2, x);
+       return pow(2, e);
 }
-float expm1(float x)
+float expm1(float e)
 {
-       return exp(x) - 1;
+       return exp(e) - 1;
 }
 
-vector frexp(float x)
+vector frexp(float e)
 {
        vector v;
        v.z = 0;
-       v.y = ilogb(x) + 1;
-       v.x = x / exp2(v.y);
+       v.y = ilogb(e) + 1;
+       v.x = e / exp2(v.y);
        return v;
 }
-int ilogb(float x)
+int ilogb(float e)
 {
-       return floor(log2(fabs(x)));
+       return floor(log2(fabs(e)));
 }
-float ldexp(float x, int e)
+float ldexp(float e, int e)
 {
-       return x * pow(2, e);
+       return e * pow(2, e);
 }
-float logn(float x, float base)
+float logn(float e, float base)
 {
-       return log(x) / log(base);
+       return log(e) / log(base);
 }
-float log10(float x)
+float log10(float e)
 {
-       return log(x) * M_LOG10E;
+       return log(e) * M_LOG10E;
 }
-float log1p(float x)
+float log1p(float e)
 {
-       return log(x + 1);
+       return log(e + 1);
 }
-float log2(float x)
+float log2(float e)
 {
-       return log(x) * M_LOG2E;
+       return log(e) * M_LOG2E;
 }
-float logb(float x)
+float logb(float e)
 {
-       return floor(log2(fabs(x)));
+       return floor(log2(fabs(e)));
 }
 vector modf(float f)
 {
        return '1 0 0' * (f - trunc(f)) + '0 1 0' * trunc(f);
 }
 
-float scalbn(float x, int n)
+float scalbn(float e, int n)
 {
-       return x * pow(2, n);
+       return e * pow(2, n);
 }
 
-float cbrt(float x)
+float cbrt(float e)
 {
-       return copysign(pow(fabs(x), 1.0/3.0), x);
+       return copysign(pow(fabs(e), 1.0/3.0), e);
 }
-float hypot(float x, float y)
+float hypot(float e, float f)
 {
-       return sqrt(x*x + y*y);
+       return sqrt(e*e + f*f);
 }
 
-float erf(float x)
+float erf(float e)
 {
        // approximation taken from wikipedia
-       float y;
-       y = x*x;
-       return copysign(sqrt(1 - exp(-y * (1.273239544735163 + 0.14001228868667 * y) / (1 + 0.14001228868667 * y))), x);
+       float f;
+       f = e*e;
+       return copysign(sqrt(1 - exp(-f * (1.273239544735163 + 0.14001228868667 * f) / (1 + 0.14001228868667 * f))), e);
 }
-float erfc(float x)
+float erfc(float e)
 {
-       return 1.0 - erf(x);
+       return 1.0 - erf(e);
 }
-vector lgamma(float x)
+vector lgamma(float e)
 {
        // TODO improve accuracy
-       if(!isfinite(x))
-               return fabs(x) * '1 0 0' + copysign(1, x) * '0 1 0';
-       if(x < 1 && x == floor(x))
+       if(!isfinite(e))
+               return fabs(e) * '1 0 0' + copysign(1, e) * '0 1 0';
+       if(e < 1 && e == floor(e))
                return nan("gamma") * '1 1 1';
-       if(x < 0.1)
+       if(e < 0.1)
        {
                vector v;
-               v = lgamma(1.0 - x);
+               v = lgamma(1.0 - e);
                // reflection formula:
                // gamma(1-z) * gamma(z) = pi / sin(pi*z)
                // lgamma(1-z) + lgamma(z) = log(pi) - log(sin(pi*z))
                // sign of gamma(1-z) = sign of gamma(z) * sign of sin(pi*z)
-               v.z = sin(M_PI * x);
+               v.z = sin(M_PI * e);
                v.x = log(M_PI) - log(fabs(v.z)) - v.x;
                if(v.z < 0)
                        v.y = -v.y;
                v.z = 0;
                return v;
        }
-       if(x < 1.1)
-               return lgamma(x + 1) - log(x) * '1 0 0';
-       x -= 1;
-       return (0.5 * log(2 * M_PI * x) + x * (log(x) - 1)) * '1 0 0' + '0 1 0';
+       if(e < 1.1)
+               return lgamma(e + 1) - log(e) * '1 0 0';
+       e -= 1;
+       return (0.5 * log(2 * M_PI * e) + e * (log(e) - 1)) * '1 0 0' + '0 1 0';
 }
-float tgamma(float x)
+float tgamma(float e)
 {
-       vector v;
-       v = lgamma(x);
+       vector v = lgamma(e);
        return exp(v.x) * v.y;
 }
 
@@ -184,109 +182,109 @@ float tgamma(float x)
  *  1 % -2 == -1
  * -1 % -2 == -1
  */
-float pymod(float x, float y)
+float pymod(float e, float f)
 {
-       return x - y * floor(x / y);
+       return e - f * floor(e / f);
 }
 
-float nearbyint(float x)
+float nearbyint(float e)
 {
-       return rint(x);
+       return rint(e);
 }
-float trunc(float x)
+float trunc(float e)
 {
-       return (x>=0) ? floor(x) : ceil(x);
+       return (e>=0) ? floor(e) : ceil(e);
 }
 
-float fmod(float x, float y)
+float fmod(float e, float f)
 {
-       return x - y * trunc(x / y);
+       return e - f * trunc(e / f);
 }
-float remainder(float x, float y)
+float remainder(float e, float f)
 {
-       return x - y * rint(x / y);
+       return e - f * rint(e / f);
 }
-vector remquo(float x, float y)
+vector remquo(float e, float f)
 {
        vector v;
        v.z = 0;
-       v.y = rint(x / y);
-       v.x = x - y * v.y;
+       v.y = rint(e / f);
+       v.x = e - f * v.y;
        return v;
 }
 
-float copysign(float x, float y)
+float copysign(float e, float f)
 {
-       return fabs(x) * ((y>0) ? 1 : -1);
+       return fabs(e) * ((f>0) ? 1 : -1);
 }
 float nan(string tag)
 {
        return sqrt(-1);
 }
-float nextafter(float x, float y)
+float nextafter(float e, float f)
 {
        // TODO very crude
-       if(x == y)
+       if(e == f)
                return nan("nextafter");
-       if(x > y)
-               return -nextafter(-x, -y);
-       // now we know that x < y
-       // so we need the next number > x
+       if(e > f)
+               return -nextafter(-e, -f);
+       // now we know that e < f
+       // so we need the next number > e
        float d, a, b;
-       d = max(fabs(x), 0.00000000000000000000001);
-       a = x + d;
+       d = max(fabs(e), 0.00000000000000000000001);
+       a = e + d;
        do
        {
                d *= 0.5;
                b = a;
-               a = x + d;
+               a = e + d;
        }
-       while(a != x);
+       while(a != e);
        return b;
 }
-float nexttoward(float x, float y)
+float nexttoward(float e, float f)
 {
-       return nextafter(x, y);
+       return nextafter(e, f);
 }
 
-float fdim(float x, float y)
+float fdim(float e, float f)
 {
-       return max(x-y, 0);
+       return max(e-f, 0);
 }
-float fmax(float x, float y)
+float fmax(float e, float f)
 {
-       return max(x, y);
+       return max(e, f);
 }
-float fmin(float x, float y)
+float fmin(float e, float f)
 {
-       return min(x, y);
+       return min(e, f);
 }
-float fma(float x, float y, float z)
+float fma(float e, float f, float g)
 {
-       return x * y + z;
+       return e * f + g;
 }
 
-int isgreater(float x, float y)
+int isgreater(float e, float f)
 {
-       return x > y;
+       return e > f;
 }
-int isgreaterequal(float x, float y)
+int isgreaterequal(float e, float f)
 {
-       return x >= y;
+       return e >= f;
 }
-int isless(float x, float y)
+int isless(float e, float f)
 {
-       return x < y;
+       return e < f;
 }
-int islessequal(float x, float y)
+int islessequal(float e, float f)
 {
-       return x <= y;
+       return e <= f;
 }
-int islessgreater(float x, float y)
+int islessgreater(float e, float f)
 {
-       return x < y || x > y;
+       return e < f || e > f;
 }
-int isunordered(float x, float y)
+int isunordered(float e, float f)
 {
-       return !(x < y || x == y || x > y);
+       return !(e < f || e == f || e > f);
 }
index 2b35c92..f5d8f63 100644 (file)
@@ -10,55 +10,55 @@ const int FP_INFINITE = 1;
 const int FP_ZERO = 2;
 const int FP_SUBNORMAL = 3;
 const int FP_NORMAL = 4;
-int fpclassify(float x);
-bool isfinite(float x);
-bool isinf(float x);
-bool isnan(float x);
-bool isnormal(float x);
-bool signbit(float x);
-
-//float acos(float x);
-//float asin(float x);
-//float atan(float x);
-//float atan2(float y, float x);
-//float cos(float x);
-//float sin(float x);
-//float tan(float x);
-
-float acosh(float x);
-float asinh(float x);
-float atanh(float x);
-float cosh(float x);
-float sinh(float x);
-float tanh(float x);
-
-float exp(float x);
-float exp2(float x);
-float expm1(float x);
-
-vector frexp(float x); // returns mantissa as _x, exponent as _y
-int ilogb(float x);
-float ldexp(float x, int e);
-//float log(float x);
-float logn(float x, float base);
-float log10(float x);
-float log1p(float x);
-float log2(float x);
-float logb(float x);
+int fpclassify(float e);
+bool isfinite(float e);
+bool isinf(float e);
+bool isnan(float e);
+bool isnormal(float e);
+bool signbit(float e);
+
+//float acos(float e);
+//float asin(float e);
+//float atan(float e);
+//float atan2(float f, float e);
+//float cos(float e);
+//float sin(float e);
+//float tan(float e);
+
+float acosh(float e);
+float asinh(float e);
+float atanh(float e);
+float cosh(float e);
+float sinh(float e);
+float tanh(float e);
+
+float exp(float e);
+float exp2(float e);
+float expm1(float e);
+
+vector frexp(float e); // returns mantissa as _x, exponent as _y
+int ilogb(float e);
+float ldexp(float e, int e);
+//float log(float e);
+float logn(float e, float base);
+float log10(float e);
+float log1p(float e);
+float log2(float e);
+float logb(float e);
 vector modf(float f); // fraction as _x, integer as _y
 
-float scalbn(float x, int n);
+float scalbn(float e, int n);
 
-float cbrt(float x);
-//float fabs(float x);
-float hypot(float x, float y);
-//float pow(float x, float y);
-//float sqrt(float x, float y);
+float cbrt(float e);
+//float fabs(float e);
+float hypot(float e, float f);
+//float pow(float e, float f);
+//float sqrt(float e, float f);
 
-float erf(float x);
-float erfc(float x);
-vector lgamma(float x); // value in _x, sign in _y
-float tgamma(float x);
+float erf(float e);
+float erfc(float e);
+vector lgamma(float e); // value in _x, sign in _y
+float tgamma(float e);
 
 /**
  * Pythonic mod:
@@ -69,35 +69,35 @@ float tgamma(float x);
  *  1 % -2 == -1
  * -1 % -2 == -1
  */
-float pymod(float x, float y);
+float pymod(float e, float f);
 
-//float ceil(float x);
-//float floor(float x);
-float nearbyint(float x);
-//float rint(float x);
-//float round(float x);
-float trunc(float x);
+//float ceil(float e);
+//float floor(float e);
+float nearbyint(float e);
+//float rint(float e);
+//float round(float e);
+float trunc(float e);
 
-float fmod(float x, float y);
-float remainder(float x, float y);
-vector remquo(float x, float y);
+float fmod(float e, float f);
+float remainder(float e, float f);
+vector remquo(float e, float f);
 
-float copysign(float x, float y);
+float copysign(float e, float f);
 float nan(string tag);
-float nextafter(float x, float y);
-float nexttoward(float x, float y);
-
-float fdim(float x, float y);
-float fmax(float x, float y);
-float fmin(float x, float y);
-float fma(float x, float y, float z);
-
-int isgreater(float x, float y);
-int isgreaterequal(float x, float y);
-int isless(float x, float y);
-int islessequal(float x, float y);
-int islessgreater(float x, float y);
-int isunordered(float x, float y);
+float nextafter(float e, float f);
+float nexttoward(float e, float f);
+
+float fdim(float e, float f);
+float fmax(float e, float f);
+float fmin(float e, float f);
+float fma(float e, float f, float g);
+
+int isgreater(float e, float f);
+int isgreaterequal(float e, float f);
+int isless(float e, float f);
+int islessequal(float e, float f);
+int islessgreater(float e, float f);
+int isunordered(float e, float f);
 
 const float M_E        = 2.7182818284590452354;   /* e */
 const float M_LOG2E    = 1.4426950408889634074;   /* log_2 e */
index 06ac91f..59405ec 100644 (file)
                }
                return 1;
        }
-       void Image_setZoom(entity me, float z, float atMousePosition)
+       void Image_setZoom(entity me, float newzoom, float atMousePosition)
        {
                float prev_zoomFactor;
                prev_zoomFactor = me.zoomFactor;
-               if (z < 0)  // multiply by the current zoomFactor (but can also snap to real dimensions or to box)
+               if (newzoom < 0)  // multiply by the current zoomFactor (but can also snap to real dimensions or to box)
                {
-                       me.zoomFactor *= -z;
+                       me.zoomFactor *= -newzoom;
                        float realSize_in_the_middle, boxSize_in_the_middle;
                        realSize_in_the_middle = ((prev_zoomFactor - 1) * (me.zoomFactor - 1) < 0);
                        boxSize_in_the_middle = (me.zoomBox > 0 && (prev_zoomFactor - me.zoomBox) * (me.zoomFactor - me.zoomBox) < 0);
                                me.zoomFactor = me.zoomBox; // snap to box
                        }
                }
-               else if (z == 0)                    // reset (no zoom)
+               else if (newzoom == 0)                    // reset (no zoom)
                {
                        if (me.zoomBox > 0) me.zoomFactor = me.zoomBox;
                        else me.zoomFactor = 1;
                }
                else  // directly set
                {
-                       me.zoomFactor = z;
+                       me.zoomFactor = newzoom;
                }
                me.zoomFactor = bound(1 / 16, me.zoomFactor, 16);
                if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax) me.zoomFactor = me.zoomMax;
index d9d63ab..aa10c20 100644 (file)
                oldshift = draw_shift;
                oldscale = draw_scale;
 
-               float y;
                i = me.getItemAtPos(me, me.scrollPos);
-               y = me.getItemStart(me, i) - me.scrollPos;
-               for ( ; i < me.nItems && y < 1; ++i)
+               float j = me.getItemStart(me, i) - me.scrollPos;
+               for ( ; i < me.nItems && j < 1; ++i)
                {
-                       draw_shift = boxToGlobal(eY * y, oldshift, oldscale);
+                       draw_shift = boxToGlobal(eY * j, oldshift, oldscale);
                        vector relSize = eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, i);
                        absSize = boxToGlobalSize(relSize, me.size);
                        draw_scale = boxToGlobalSize(relSize, oldscale);
                        me.drawListBoxItem(me, i, absSize, (me.selectedItem == i), (me.focusedItem == i));
-                       y += relSize.y;
+                       j += relSize.y;
                }
                draw_ClearClip();
 
index b863518..949b01c 100644 (file)
@@ -2,28 +2,28 @@
 
 entity makeXonoticCheckBox_T(float isInverted, string theCvar, string theText, string theTooltip)
 {
-       float y, n;
+       float m, n;
        if(isInverted > 1)
        {
                n = isInverted - 1;
-               y = -n;
+               m = -n;
        }
        else if(isInverted < -1)
        {
                n = isInverted + 1;
-               y = -n;
+               m = -n;
        }
        else if(isInverted == 1)
        {
                n = 1;
-               y = 0;
+               m = 0;
        }
        else
        {
                n = 0;
-               y = 1;
+               m = 1;
        }
-       return makeXonoticCheckBoxEx_T(y, n, theCvar, theText, theTooltip);
+       return makeXonoticCheckBoxEx_T(m, n, theCvar, theText, theTooltip);
 }
 entity makeXonoticCheckBox(float isInverted, string theCvar, string theText)
 {
index d30ab3d..816120b 100644 (file)
@@ -402,7 +402,6 @@ void XonoticCreditsList_resizeNotify(entity me, vector relOrigin, vector relSize
 }
 void XonoticCreditsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
-       // layout: Ping, Credits name, Map name, NP, TP, MP
        string s;
        float theAlpha;
        vector theColor;
index 85e0e9e..4819142 100644 (file)
@@ -58,6 +58,27 @@ void GameType_ConfigureSliders(entity me, string pLabel, float pMin, float pMax,
        t.configureXonoticTextSliderValues(t);
 }
 
+void GameType_ConfigureSliders_for_CurrentGametype(entity me)
+{
+       switch(MapInfo_CurrentGametype())
+       {
+               case MAPINFO_TYPE_CA:              GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_ca_teams_override",          _("The amount of frags needed before the match will end")); break;
+               case MAPINFO_TYPE_FREEZETAG:       GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_freezetag_teams_override",   _("The amount of frags needed before the match will end")); break;
+               case MAPINFO_TYPE_CTF:             GameType_ConfigureSliders(me, _("Capture limit:"),   1,   20,  1, "capturelimit_override",     string_null,                    _("The amount of captures needed before the match will end")); break;
+               case MAPINFO_TYPE_DOMINATION:      GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, "g_domination_point_limit",  "g_domination_teams_override",  _("The amount of points needed before the match will end")); break;
+               case MAPINFO_TYPE_KEYHUNT:         GameType_ConfigureSliders(me, _("Point limit:"),   200, 1500, 50, "g_keyhunt_point_limit",     "g_keyhunt_teams_override",     _("The amount of points needed before the match will end")); break;
+               case MAPINFO_TYPE_LMS:             GameType_ConfigureSliders(me, _("Lives:"),           3,   50,  1, "g_lms_lives_override",      string_null,                    string_null); break;
+               case MAPINFO_TYPE_RACE:            GameType_ConfigureSliders(me, _("Laps:"),            1,   25,  1, "g_race_laps_limit",         string_null,                    string_null); break;
+               case MAPINFO_TYPE_NEXBALL:         GameType_ConfigureSliders(me, _("Goals:"),           1,   50,  1, "g_nexball_goallimit",       string_null,                    _("The amount of goals needed before the match will end")); break;
+               case MAPINFO_TYPE_ASSAULT:         GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
+               case MAPINFO_TYPE_ONSLAUGHT:       GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
+               case MAPINFO_TYPE_CTS:             GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
+               case MAPINFO_TYPE_INVASION:        GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
+               case MAPINFO_TYPE_TEAM_DEATHMATCH: GameType_ConfigureSliders(me, _("Point limit:"),     5,  100,  5, "g_tdm_point_limit",         "g_tdm_teams_override",         _("The amount of points needed before the match will end")); break;
+               default:                           GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        string_null,                    _("The amount of frags needed before the match will end")); break;
+       }
+}
+
 entity makeXonoticServerCreateTab()
 {
        entity me;
@@ -210,28 +231,12 @@ void XonoticServerCreateTab_fill(entity me)
                        e.onClickEntity = me.mapListBox;
                        me.mapListBox.startButton = e;
 
-       me.gameTypeChangeNotify(me);
+       GameType_ConfigureSliders_for_CurrentGametype(me);
 }
 
 void XonoticServerCreateTab_gameTypeChangeNotify(entity me)
 {
-       switch(MapInfo_CurrentGametype())
-       {
-               case MAPINFO_TYPE_CA:              GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_ca_teams_override",          _("The amount of frags needed before the match will end")); break;
-               case MAPINFO_TYPE_FREEZETAG:       GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_freezetag_teams_override",   _("The amount of frags needed before the match will end")); break;
-               case MAPINFO_TYPE_CTF:             GameType_ConfigureSliders(me, _("Capture limit:"),   1,   20,  1, "capturelimit_override",     string_null,                    _("The amount of captures needed before the match will end")); break;
-               case MAPINFO_TYPE_DOMINATION:      GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, "g_domination_point_limit",  "g_domination_teams_override",  _("The amount of points needed before the match will end")); break;
-               case MAPINFO_TYPE_KEYHUNT:         GameType_ConfigureSliders(me, _("Point limit:"),   200, 1500, 50, "g_keyhunt_point_limit",     "g_keyhunt_teams_override",     _("The amount of points needed before the match will end")); break;
-               case MAPINFO_TYPE_LMS:             GameType_ConfigureSliders(me, _("Lives:"),           3,   50,  1, "g_lms_lives_override",      string_null,                    string_null); break;
-               case MAPINFO_TYPE_RACE:            GameType_ConfigureSliders(me, _("Laps:"),            1,   25,  1, "g_race_laps_limit",         string_null,                    string_null); break;
-               case MAPINFO_TYPE_NEXBALL:         GameType_ConfigureSliders(me, _("Goals:"),           1,   50,  1, "g_nexball_goallimit",       string_null,                    _("The amount of goals needed before the match will end")); break;
-               case MAPINFO_TYPE_ASSAULT:         GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_ONSLAUGHT:       GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_CTS:             GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_INVASION:        GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_TEAM_DEATHMATCH: GameType_ConfigureSliders(me, _("Point limit:"),     5,  100,  5, "g_tdm_point_limit",         "g_tdm_teams_override",         _("The amount of points needed before the match will end")); break;
-               default:                           GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        string_null,                    _("The amount of frags needed before the match will end")); break;
-       }
+       GameType_ConfigureSliders_for_CurrentGametype(me);
 
        me.mapListBox.refilter(me.mapListBox);
 }
index 07fe09c..65edcde 100644 (file)
@@ -53,8 +53,6 @@ string WeaponArenaString()
        return weaponarenastring;
 }
 
-AUTOCVAR(g_grappling_hook, bool, _("let players spawn with the grappling hook which allows them to pull themselves up"));
-
 string XonoticMutatorsDialog_toString(entity me)
 {
        string s;
@@ -79,7 +77,7 @@ string XonoticMutatorsDialog_toString(entity me)
                s = strcat(s, ", ", _("Low gravity"));
        if(cvar("g_cloaked"))
                s = strcat(s, ", ", _("Cloaked"));
-       if(autocvar_g_grappling_hook)
+       if(cvar("g_grappling_hook"))
                s = strcat(s, ", ", _("Hook"));
        if(cvar("g_midair"))
                s = strcat(s, ", ", _("Midair"));
index 7b5f23b..187d080 100644 (file)
@@ -3,7 +3,7 @@
 #include "rootdialog.qh"
 CLASS(XonoticUid2NameDialog, XonoticRootDialog)
        METHOD(XonoticUid2NameDialog, fill, void(entity));
-       ATTRIB(XonoticUid2NameDialog, title, string);
+       ATTRIB(XonoticUid2NameDialog, title, string, "");
        ATTRIB(XonoticUid2NameDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
        ATTRIB(XonoticUid2NameDialog, intendedWidth, float, 0.5);
        ATTRIB(XonoticUid2NameDialog, rows, float, 4);
index 82ff4ba..42e168b 100644 (file)
@@ -56,12 +56,11 @@ void XonoticScreenshotImage_draw(entity me)
                if (time < me.zoomTime + 2) // 1 seconds at full alpha, 1 second fading out
                {
                        string zoomString;
-                       float z;
-                       z = me.zoomFactor * 100;
-                       if (z - floor(z) == 0)
-                               zoomString = sprintf("%d%%", z);
+                       float myzoom = me.zoomFactor * 100;
+                       if (myzoom - floor(myzoom) == 0)
+                               zoomString = sprintf("%d%%", myzoom);
                        else
-                               zoomString = sprintf("%.2f%%", z);
+                               zoomString = sprintf("%.2f%%", myzoom);
                        theAlpha = (2 - (time - me.zoomTime));
                        draw_Text('0.05 0.95 0', zoomString, me.realFontSize, '1 1 1', theAlpha, false);
                }
index cd3d702..bbb9dca 100644 (file)
@@ -471,9 +471,8 @@ void XonoticServerList_draw(entity me)
                // entire list, otherwise there is no way to know which item is first in its category.
 
                // binary search method suggested by div
-               float x;
                float begin = 0;
-               for(x = 1; x <= category_ent_count; ++x) {
+               for(int j = 1; j <= category_ent_count; ++j) {
                        float first = begin;
                        float last = (itemcount - 1);
                        if (first > last) {
@@ -482,42 +481,42 @@ void XonoticServerList_draw(entity me)
                        }
                        float catf = gethostcachenumber(SLIST_FIELD_CATEGORY, first);
                        float catl = gethostcachenumber(SLIST_FIELD_CATEGORY, last);
-                       if (catf > x) {
-                               // The first one is already > x.
-                               // Therefore, category x does not exist.
+                       if (catf > j) {
+                               // The first one is already > j.
+                               // Therefore, category j does not exist.
                                // Higher numbered categories do exist though.
-                       } else if (catl < x) {
-                               // The last one is < x.
+                       } else if (catl < j) {
+                               // The last one is < j.
                                // Thus this category - and any following -
                                // don't exist.
                                break;
-                       } else if (catf == x) {
+                       } else if (catf == j) {
                                // Starts at first. This breaks the loop
                                // invariant in the binary search and thus has
                                // to be handled separately.
-                               if(gethostcachenumber(SLIST_FIELD_CATEGORY, first) != x)
+                               if(gethostcachenumber(SLIST_FIELD_CATEGORY, first) != j)
                                        error("Category mismatch I");
                                if(first > 0)
-                                       if(gethostcachenumber(SLIST_FIELD_CATEGORY, first - 1) == x)
+                                       if(gethostcachenumber(SLIST_FIELD_CATEGORY, first - 1) == j)
                                                error("Category mismatch II");
-                               category_name[category_draw_count] = x;
+                               category_name[category_draw_count] = j;
                                category_item[category_draw_count] = first;
                                ++category_draw_count;
                                begin = first + 1;
                        } else {
-                               // At this point, catf <= x < catl, thus
+                               // At this point, catf <= j < catl, thus
                                // catf < catl, thus first < last.
                                // INVARIANTS:
                                // last - first >= 1
                                // catf == gethostcachenumber(SLIST_FIELD_CATEGORY(first)
                                // catl == gethostcachenumber(SLIST_FIELD_CATEGORY(last)
-                               // catf < x
-                               // catl >= x
+                               // catf < j
+                               // catl >= j
                                while (last - first > 1) {
                                        float middle = floor((first + last) / 2);
                                        // By loop condition, middle != first && middle != last.
                                        float cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle);
-                                       if (cat >= x) {
+                                       if (cat >= j) {
                                                last = middle;
                                                catl = cat;
                                        } else {
@@ -525,13 +524,13 @@ void XonoticServerList_draw(entity me)
                                                catf = cat;
                                        }
                                }
-                               if (catl == x) {
-                                       if(gethostcachenumber(SLIST_FIELD_CATEGORY, last) != x)
+                               if (catl == j) {
+                                       if(gethostcachenumber(SLIST_FIELD_CATEGORY, last) != j)
                                                error("Category mismatch III");
                                        if(last > 0)
-                                               if(gethostcachenumber(SLIST_FIELD_CATEGORY, last - 1) == x)
+                                               if(gethostcachenumber(SLIST_FIELD_CATEGORY, last - 1) == j)
                                                        error("Category mismatch IV");
-                                       category_name[category_draw_count] = x;
+                                       category_name[category_draw_count] = j;
                                        category_item[category_draw_count] = last;
                                        ++category_draw_count;
                                        begin = last + 1; // already scanned through these, skip 'em
index 50c766e..e45abfd 100644 (file)
@@ -154,8 +154,8 @@ int category_draw_count;
        SLIST_CATEGORY(CAT_SERVERS,      "CAT_NORMAL",  "CAT_SERVERS",  CTX(_("SLCAT^Servers"))) \
        SLIST_CATEGORY(CAT_XPM,          "CAT_NORMAL",  "CAT_SERVERS",  CTX(_("SLCAT^Competitive Mode"))) \
        SLIST_CATEGORY(CAT_MODIFIED,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Modified Servers"))) \
-       SLIST_CATEGORY(CAT_OVERKILL,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Overkill Mode"))) \
-       SLIST_CATEGORY(CAT_INSTAGIB,     "",            "CAT_SERVERS",  CTX(_("SLCAT^InstaGib Mode"))) \
+       SLIST_CATEGORY(CAT_OVERKILL,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Overkill"))) \
+       SLIST_CATEGORY(CAT_INSTAGIB,     "",            "CAT_SERVERS",  CTX(_("SLCAT^InstaGib"))) \
        SLIST_CATEGORY(CAT_DEFRAG,       "",            "CAT_SERVERS",  CTX(_("SLCAT^Defrag Mode")))
 
 #define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
index 2b78141..dcc2c85 100644 (file)
@@ -7,9 +7,9 @@ float toDecibelOfSquare(float f, float mi)
        {
                // linear scale part
                float t = 1 / A + mi;
-               float y = exp(1 + A * mi);
-               if(f <= y)
-                       return mi + (t - mi) * (f / y);
+               float u = exp(1 + A * mi);
+               if(f <= u)
+                       return mi + (t - mi) * (f / u);
        }
        return log(f) / A;
 }
@@ -21,9 +21,9 @@ float fromDecibelOfSquare(float f, float mi)
        {
                // linear scale part
                float t = 1 / A + mi;
-               float y = exp(1 + A * mi);
+               float u = exp(1 + A * mi);
                if(f <= t)
-                       return y * ((f - mi) / (t - mi));
+                       return u * ((f - mi) / (t - mi));
        }
        return exp(A * f);
 }
index ed3083a..1fabe4d 100644 (file)
@@ -43,6 +43,37 @@ const string STR_OBSERVER = "observer";
 
 #define FOREACH_CLIENT(cond, body) FOREACH_CLIENTSLOT(IS_CLIENT(it) && (cond), body)
 
+// using the "inside out" version of knuth-fisher-yates shuffle
+// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
+entity _FCR_clients[255];
+bool _FCR_entered = false;
+#define FOREACH_CLIENT_RANDOM(cond, body) \
+       MACRO_BEGIN { \
+               if (_FCR_entered) LOG_FATAL("FOREACH_CLIENT_RANDOM must not be nested"); \
+               _FCR_entered = true; \
+               int _cnt = 0; \
+               FOREACH_CLIENT(cond, LAMBDA( \
+                       int _j = floor(random() * (_cnt + 1)); \
+                       if (_j == _cnt) \
+                       { \
+                               _FCR_clients[_cnt] = it; \
+                       } \
+                       else \
+                       { \
+                               _FCR_clients[_cnt] = _FCR_clients[_j]; \
+                               _FCR_clients[_j] = it; \
+                       } \
+                       _cnt++; \
+               )); \
+               for (int _i = 0; _i < _cnt; ++_i) \
+               { \
+                       const noref int i = _i; \
+                       ITER_CONST noref entity it = _FCR_clients[i]; \
+                       if (cond) { LAMBDA(body) } \
+               } \
+               _FCR_entered = false; \
+       } MACRO_END
+
 // NOTE: FOR_EACH_MONSTER deprecated! Use the following instead: IL_EACH(g_monsters, true, { code; });
 
 #include <common/effects/all.qh>
index 4861fe2..4e794cb 100644 (file)
@@ -6,6 +6,7 @@
 #include "miscfunctions.qh"
 
 #include "command/common.qh"
+#include <common/playerstats.qh>
 #include <common/state.qh>
 
 .float anticheat_jointime;
@@ -158,67 +159,66 @@ void anticheat_prethink(entity this)
        CS(this).anticheat_div0_evade_offset = 0;
 }
 
-string anticheat_display(float f, float tmin, float mi, float ma)
+string anticheat_display(float f, float t, float tmin, float mi, float ma)
 {
        string s;
        s = ftos(f);
-       if(f <= mi)
-               return strcat(s, ":N");
-       if(f >= ma)
-               return strcat(s, ":Y");
+       if (t >= tmin) {
+               if(f <= mi)
+                       return strcat(s, ":N");
+               if(f >= ma)
+                       return strcat(s, ":Y");
+       }
        return strcat(s, ":-");
 }
 
-void anticheat_report(entity this)
-{
+#define ANTICHEATS(ANTICHEAT) \
+       ANTICHEAT("speedhack", MEAN_EVALUATE(CS(this), anticheat_speedhack), 240, 0, 9999); /* Actually this one seems broken. */ \
+       ANTICHEAT("speedhack_m1", MEAN_EVALUATE(CS(this), anticheat_speedhack_m1), 240, 1.01, 1.25); \
+       ANTICHEAT("speedhack_m2", MEAN_EVALUATE(CS(this), anticheat_speedhack_m2), 240, 1.01, 1.25); \
+       ANTICHEAT("speedhack_m3", MEAN_EVALUATE(CS(this), anticheat_speedhack_m3), 240, 1.01, 1.25); \
+       ANTICHEAT("speedhack_m4", MEAN_EVALUATE(CS(this), anticheat_speedhack_m4), 240, 1.01, 1.25); \
+       ANTICHEAT("speedhack_m5", MEAN_EVALUATE(CS(this), anticheat_speedhack_m5), 240, 1.01, 1.25); \
+       ANTICHEAT("div0_strafebot_old", MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_old), 120, 0.15, 0.4); \
+       ANTICHEAT("div0_strafebot_new", MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_new), 120, 0.25, 0.8); \
+       ANTICHEAT("div0_evade", MEAN_EVALUATE(CS(this), anticheat_div0_evade), 120, 0.2, 0.5); \
+       ANTICHEAT("idle_snapaim", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal) - MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_signal", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_noise", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_m2", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m2), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_m3", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m3), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_m4", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m4), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_m7", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m7), 120, 0, 9999); \
+       ANTICHEAT("idle_snapaim_m10", MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m10), 120, 0, 9999)
+
+void anticheat_report_to_eventlog(entity this) {
        if(!autocvar_sv_eventlog)
                return;
-       // TODO(divVerent): Use xonstat to acquire good thresholds.
        GameLogEcho(strcat(":anticheat:_time:", ftos(this.playerid), ":", ftos(servertime - CS(this).anticheat_jointime)));
-       GameLogEcho(strcat(":anticheat:speedhack:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
-       GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack_m1), 240, 1.01, 1.25)));
-       GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack_m2), 240, 1.01, 1.25)));
-       GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack_m3), 240, 1.01, 1.25)));
-       GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack_m4), 240, 1.01, 1.25)));
-       GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_speedhack_m5), 240, 1.01, 1.25)));
-       GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
-       GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
-       GameLogEcho(strcat(":anticheat:div0_evade:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_div0_evade), 120, 0.2, 0.5)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal) - MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m2), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m3), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m4), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m7), 120, 0, 9999)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(this.playerid), ":", anticheat_display(MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m10), 120, 0, 9999)));
+#define ANTICHEAT_REPORT_ONE(name, f, tmin, mi, ma) \
+       GameLogEcho(strcat(":anticheat:", name, ":", anticheat_display(f, servertime - CS(this).anticheat_jointime, tmin, mi, ma)))
+       ANTICHEATS(ANTICHEAT_REPORT_ONE);
+#undef ANTICHEAT_REPORT_ONE
 }
 
-float anticheat_getvalue(entity this, string id)
-{
-       switch(id) {
-               case "_time": return servertime - CS(this).anticheat_jointime;
-               case "speedhack": return MEAN_EVALUATE(CS(this), anticheat_speedhack);
-               case "speedhack_m1": return MEAN_EVALUATE(CS(this), anticheat_speedhack_m1);
-               case "speedhack_m2": return MEAN_EVALUATE(CS(this), anticheat_speedhack_m2);
-               case "speedhack_m3": return MEAN_EVALUATE(CS(this), anticheat_speedhack_m3);
-               case "speedhack_m4": return MEAN_EVALUATE(CS(this), anticheat_speedhack_m4);
-               case "speedhack_m5": return MEAN_EVALUATE(CS(this), anticheat_speedhack_m5);
-               case "div0_strafebot_old": return MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_old);
-               case "div0_strafebot_new": return MEAN_EVALUATE(CS(this), anticheat_div0_strafebot_new);
-               case "div0_evade": return MEAN_EVALUATE(CS(this), anticheat_div0_evade);
-               case "idle_snapaim": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal) - MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise);
-               case "idle_snapaim_signal": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_signal);
-               case "idle_snapaim_noise": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_noise);
-               case "idle_snapaim_m2": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m2);
-               case "idle_snapaim_m3": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m3);
-               case "idle_snapaim_m4": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m4);
-               case "idle_snapaim_m7": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m7);
-               case "idle_snapaim_m10": return MEAN_EVALUATE(CS(this), anticheat_idle_snapaim_m10);
-       }
-       return -1;
+void anticheat_report_to_playerstats(entity this) {
+       PS_GR_P_ADDVAL(this, strcat(PLAYERSTATS_ANTICHEAT, "_time"), servertime - CS(this).anticheat_jointime);
+#define ANTICHEAT_REPORT_ONE(name, f, tmin, mi, ma) \
+       PS_GR_P_ADDVAL(this, strcat(PLAYERSTATS_ANTICHEAT, name), f)
+       ANTICHEATS(ANTICHEAT_REPORT_ONE);
+#undef ANTICHEAT_REPORT_ONE
 }
 
+void anticheat_register_to_playerstats() {
+       PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_ANTICHEAT, "_time"));
+#define ANTICHEAT_REGISTER_ONE(name, unused_f, unused_tmin, unused_mi, unused_ma) \
+       PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_ANTICHEAT, name))
+       ANTICHEATS(ANTICHEAT_REGISTER_ONE);
+#undef ANTICHEAT_REGISTER_ONE
+}
+
+#undef ANTICHEATS
+
 void anticheat_startframe()
 {
        anticheat_div0_evade_evasion_delta += frametime * (0.5 + random());
index 2b0522b..dd870dd 100644 (file)
@@ -1,14 +1,14 @@
 #pragma once
 
 void anticheat_init(entity this);
-void anticheat_report(entity this);
+void anticheat_report_to_eventlog(entity this);
+void anticheat_report_to_playerstats(entity this);
+void anticheat_register_to_playerstats();
 
 void anticheat_physics(entity this);
 void anticheat_spectatecopy(entity this, entity spectatee);
 void anticheat_prethink(entity this);
 
-float anticheat_getvalue(entity this, string name);
-
 void anticheat_startframe();
 void anticheat_endframe();
 
index 2a7478d..9d612ea 100644 (file)
@@ -72,6 +72,7 @@ void bot_think(entity this)
 
        if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start))
        {
+               this.movement = '0 0 0';
                this.bot_nextthink = time + 0.5;
                return;
        }
@@ -118,6 +119,7 @@ void bot_think(entity this)
        // if dead, just wait until we can respawn
        if (IS_DEAD(this))
        {
+               this.movement = '0 0 0';
                if (this.deadflag == DEAD_DEAD)
                {
                        PHYS_INPUT_BUTTON_JUMP(this) = true; // press jump to respawn
index 56c36c0..e599bb8 100644 (file)
@@ -29,6 +29,10 @@ void havocbot_ai(entity this)
        if(bot_execute_commands(this))
                return;
 
+       if(this.goalcurrent)
+       if(wasfreed(this.goalcurrent))
+               navigation_poproute(this);
+
        if (bot_strategytoken == this)
        if (!bot_strategytoken_taken)
        {
@@ -44,7 +48,7 @@ void havocbot_ai(entity this)
 
                // TODO: tracewalk() should take care of this job (better path finding under water)
                // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
-               if(IS_DEAD(this))
+               if(!(IS_DEAD(this)))
                if(!this.goalcurrent)
                if(this.waterlevel == WATERLEVEL_SWIMMING || (this.aistatus & AI_STATUS_OUT_WATER))
                {
@@ -860,9 +864,6 @@ entity havocbot_gettarget(entity this, bool secondary)
 
 void havocbot_chooseenemy(entity this)
 {
-       entity head, best, head2;
-       float rating, bestrating, hf;
-       vector eye, v;
        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
        {
                this.enemy = NULL;
@@ -901,13 +902,12 @@ void havocbot_chooseenemy(entity this)
        if (time < this.havocbot_chooseenemy_finished)
                return;
        this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
-       eye = this.origin + this.view_ofs;
-       best = NULL;
-       bestrating = 100000000;
-       head = head2 = findchainfloat(bot_attack, true);
+       vector eye = this.origin + this.view_ofs;
+       entity best = NULL;
+       float bestrating = 100000000;
 
        // Backup hit flags
-       hf = this.dphitcontentsmask;
+       int hf = this.dphitcontentsmask;
 
        // Search for enemies, if no enemy can be seen directly try to look through transparent objects
 
@@ -920,42 +920,38 @@ void havocbot_chooseenemy(entity this)
        {
                scan_secondary_targets = false;
 LABEL(scan_targets)
-               for( ; head; head = head.chain)
+               IL_EACH(g_bot_targets, it.bot_attack,
                {
                        if(!scan_secondary_targets)
                        {
-                               if(head.classname == "misc_breakablemodel")
+                               if(it.classname == "misc_breakablemodel")
                                {
                                        have_secondary_targets = true;
                                        continue;
                                }
                        }
-                       else
-                       {
-                               if(head.classname != "misc_breakablemodel")
-                                       continue;
-                       }
+                       else if(it.classname != "misc_breakablemodel")
+                               continue;
 
-                       v = (head.absmin + head.absmax) * 0.5;
-                       rating = vlen(v - eye);
-                       if (rating<autocvar_bot_ai_enemydetectionradius)
+                       vector v = (it.absmin + it.absmax) * 0.5;
+                       float rating = vlen2(v - eye);
+                       if (vdist(v - eye, <, autocvar_bot_ai_enemydetectionradius))
                        if (bestrating > rating)
-                       if (bot_shouldattack(this, head))
+                       if (bot_shouldattack(this, it))
                        {
                                traceline(eye, v, true, this);
-                               if (trace_ent == head || trace_fraction >= 1)
+                               if (trace_ent == it || trace_fraction >= 1)
                                {
-                                       best = head;
+                                       best = it;
                                        bestrating = rating;
                                }
                        }
-               }
+               });
 
                if(!best && have_secondary_targets && !scan_secondary_targets)
                {
                        scan_secondary_targets = true;
                        // restart the loop
-                       head = head2;
                        bestrating = 100000000;
                        goto scan_targets;
                }
@@ -970,7 +966,6 @@ LABEL(scan_targets)
                // Set flags to see through transparent objects
                this.dphitcontentsmask |= DPCONTENTS_OPAQUE;
 
-               head = head2;
                scan_transparent = true;
        }
 
index 7c71720..5092a65 100644 (file)
@@ -1032,7 +1032,7 @@ void navigation_unstuck(entity this)
 
        if (!bot_waypoint_queue_owner)
        {
-               LOG_DEBUG(this.netname, " sutck, taking over the waypoints queue");
+               LOG_DEBUG(this.netname, " stuck, taking over the waypoints queue");
                bot_waypoint_queue_owner = this;
                bot_waypoint_queue_bestgoal = NULL;
                bot_waypoint_queue_bestgoalrating = 0;
@@ -1044,7 +1044,7 @@ void navigation_unstuck(entity this)
        if (bot_waypoint_queue_goal)
        {
                // evaluate the next goal on the queue
-               float d = vlen(this.origin - bot_waypoint_queue_goal.origin);
+               float d = vlen2(this.origin - bot_waypoint_queue_goal.origin);
                LOG_DEBUG(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d));
                if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), bot_waypoint_queue_goal.origin, bot_navigation_movemode))
                {
index 9f29a22..f960990 100644 (file)
@@ -1160,16 +1160,17 @@ float bot_execute_commands_once(entity this)
        // Find command
        bot_setcurrentcommand(this);
 
-       // if we have no bot command, better return
-       // old logic kept pressing previously pressed keys, but that has problems
-       // (namely, it means you cannot make a bot "normal" ever again)
-       // to keep a bot walking for a while, use the "wait" bot command
-       if(bot_cmd == NULL)
-               return false;
-
        // Ignore all commands except continue when the bot is paused
-       if(this.bot_exec_status & BOT_EXEC_STATUS_PAUSED)
-       if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE)
+       if(!(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED))
+       {
+               // if we have no bot command, better return
+               // old logic kept pressing previously pressed keys, but that has problems
+               // (namely, it means you cannot make a bot "normal" ever again)
+               // to keep a bot walking for a while, use the "wait" bot command
+               if(bot_cmd == world)
+                       return 0;
+       }
+       else if(bot_cmd.bot_cmd_type != BOT_CMD_CONTINUE)
        {
                if(bot_cmd.bot_cmd_type!=BOT_CMD_NULL)
                {
index da66ece..04c35a1 100644 (file)
@@ -339,6 +339,7 @@ void PutObserverInServer(entity this)
        this.hook_time = 0;
        this.deadflag = DEAD_NO;
        this.crouch = false;
+       this.revive_progress = 0;
        this.revival_time = 0;
 
        this.items = 0;
@@ -616,6 +617,7 @@ void PutClientInServer(entity this)
                this.strength_finished = 0;
                this.invincible_finished = 0;
                this.fire_endtime = -1;
+               this.revive_progress = 0;
                this.revival_time = 0;
                this.air_finished = time + 12;
 
@@ -1050,8 +1052,8 @@ ClientPreConnect
 Called once (not at each match start) when a client begins a connection to the server
 =============
 */
-void ClientPreConnect ()
-{ENGINE_EVENT();
+void ClientPreConnect(entity this)
+{
        if(autocvar_sv_eventlog)
        {
                GameLogEcho(sprintf(":connect:%d:%d:%s",
@@ -1190,12 +1192,6 @@ void ClientConnect(entity this)
 
        if (IS_REAL_CLIENT(this))
        {
-               if (!autocvar_g_campaign)
-               {
-                       this.motd_actived_time = -1;
-                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
-               }
-
                if (g_weaponarena_weapons == WEPSET(TUBA))
                        stuffcmd(this, "cl_cmd settemp chase_active 1\n");
        }
@@ -1222,6 +1218,15 @@ void ClientConnect(entity this)
        });
 
        MUTATOR_CALLHOOK(ClientConnect, this);
+
+       if (IS_REAL_CLIENT(this))
+       {
+               if (!autocvar_g_campaign && !IS_PLAYER(this))
+               {
+                       this.motd_actived_time = -1;
+                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
+               }
+       }
 }
 /*
 =============
@@ -1605,11 +1610,11 @@ void player_regen(entity this)
 }
 
 bool zoomstate_set;
-void SetZoomState(entity this, float z)
+void SetZoomState(entity this, float newzoom)
 {
-       if(z != this.zoomstate)
+       if(newzoom != this.zoomstate)
        {
-               this.zoomstate = z;
+               this.zoomstate = newzoom;
                ClientData_Touch(this);
        }
        zoomstate_set = true;
index 5f2c86e..3f8e4c4 100644 (file)
@@ -2,7 +2,6 @@
 
 .float cmd_floodtime;
 .float cmd_floodcount;
-.float lms_spectate_warning;
 
 string MapVote_Suggest(entity this, string m);
 
index a5e4a75..ad86afb 100644 (file)
@@ -49,18 +49,18 @@ float FullTraceFraction(vector a, vector mi, vector ma, vector b)
 
        return white / (black + white);
 }
-float RadarMapAtPoint_Trace(float x, float y, float w, float h, float zmin, float zsize, float q)
+float RadarMapAtPoint_Trace(float e, float f, float w, float h, float zmin, float zsize, float q)
 {
        vector a, b, mi, ma;
 
        mi = '0 0 0';
        ma = '1 0 0' * w + '0 1 0' * h;
-       a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin;
-       b = '1 0 0' * x + '0 1 0' * y + '0 0 1' * (zsize + zmin);
+       a = '1 0 0' * e + '0 1 0' * f + '0 0 1' * zmin;
+       b = '1 0 0' * e + '0 1 0' * f + '0 0 1' * (zsize + zmin);
 
        return FullTraceFraction(a, mi, ma, b);
 }
-float RadarMapAtPoint_LineBlock(float x, float y, float w, float h, float zmin, float zsize, float q)
+float RadarMapAtPoint_LineBlock(float e, float f, float w, float h, float zmin, float zsize, float q)
 {
        vector o, mi, ma;
        float i, r;
@@ -72,12 +72,12 @@ float RadarMapAtPoint_LineBlock(float x, float y, float w, float h, float zmin,
        mi = '0 0 0';
        dz = (zsize / q) * '0 0 1';
        ma = '1 0 0' * w + '0 1 0' * h + dz;
-       o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin;
+       o = '1 0 0' * e + '0 1 0' * f + '0 0 1' * zmin;
 
-       if (x < world.absmin.x - w) return 0;
-       if (y < world.absmin.y - h) return 0;
-       if (x > world.absmax.x) return 0;
-       if (y > world.absmax.y) return 0;
+       if (e < world.absmin.x - w) return 0;
+       if (f < world.absmin.y - h) return 0;
+       if (e > world.absmax.x) return 0;
+       if (f > world.absmax.y) return 0;
 
        r = 0;
        for (i = 0; i < q; ++i)
@@ -95,7 +95,7 @@ float RadarMapAtPoint_LineBlock(float x, float y, float w, float h, float zmin,
        }
        return r / q;
 }
-float RadarMapAtPoint_Block(float x, float y, float w, float h, float zmin, float zsize, float q)
+float RadarMapAtPoint_Block(float e, float f, float w, float h, float zmin, float zsize, float q)
 {
        vector o, mi, ma;
        float i, r;
@@ -107,12 +107,12 @@ float RadarMapAtPoint_Block(float x, float y, float w, float h, float zmin, floa
        mi = '0 0 0';
        dz = (zsize / q) * '0 0 1';
        ma = '1 0 0' * w + '0 1 0' * h + dz;
-       o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin;
+       o = '1 0 0' * e + '0 1 0' * f + '0 0 1' * zmin;
 
-       if (x < world.absmin.x - w) return 0;
-       if (y < world.absmin.y - h) return 0;
-       if (x > world.absmax.x) return 0;
-       if (y > world.absmax.y) return 0;
+       if (e < world.absmin.x - w) return 0;
+       if (f < world.absmin.y - h) return 0;
+       if (e > world.absmax.x) return 0;
+       if (f > world.absmax.y) return 0;
 
        r = 0;
        for (i = 0; i < q; ++i)
@@ -122,7 +122,7 @@ float RadarMapAtPoint_Block(float x, float y, float w, float h, float zmin, floa
        }
        return r / q;
 }
-float RadarMapAtPoint_Sample(float x, float y, float w, float h, float zmin, float zsize, float q)
+float RadarMapAtPoint_Sample(float e, float f, float w, float h, float zmin, float zsize, float q)
 {
        vector a, b, mi, ma;
 
@@ -133,7 +133,7 @@ float RadarMapAtPoint_Sample(float x, float y, float w, float h, float zmin, flo
 
        mi = '0 0 0';
        ma = '1 0 0' * w + '0 1 0' * h;
-       a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin;
+       a = '1 0 0' * e + '0 1 0' * f + '0 0 1' * zmin;
        b = '1 0 0' * w + '0 1 0' * h + '0 0 1' * zsize;
 
        float c, i;
@@ -151,31 +151,31 @@ float RadarMapAtPoint_Sample(float x, float y, float w, float h, float zmin, flo
 
        return c / q;
 }
-void sharpen_set(int x, float v)
+void sharpen_set(int b, float v)
 {
-       sharpen_buffer[x + 2 * RADAR_WIDTH_MAX] = v;
+       sharpen_buffer[b + 2 * RADAR_WIDTH_MAX] = v;
 }
-float sharpen_getpixel(int x, int y)
+float sharpen_getpixel(int b, int c)
 {
-       if (x < 0) return 0;
-       if (x >= RADAR_WIDTH_MAX) return 0;
-       if (y < 0) return 0;
-       if (y > 2) return 0;
-       return sharpen_buffer[x + y * RADAR_WIDTH_MAX];
+       if (b < 0) return 0;
+       if (b >= RADAR_WIDTH_MAX) return 0;
+       if (c < 0) return 0;
+       if (c > 2) return 0;
+       return sharpen_buffer[b + c * RADAR_WIDTH_MAX];
 }
-float sharpen_get(float x, float a)
+float sharpen_get(float b, float a)
 {
-       float sum = sharpen_getpixel(x, 1);
+       float sum = sharpen_getpixel(b, 1);
        if (a == 0) return sum;
        sum *= (8 + 1 / a);
-       sum -= sharpen_getpixel(x - 1, 0);
-       sum -= sharpen_getpixel(x - 1, 1);
-       sum -= sharpen_getpixel(x - 1, 2);
-       sum -= sharpen_getpixel(x + 1, 0);
-       sum -= sharpen_getpixel(x + 1, 1);
-       sum -= sharpen_getpixel(x + 1, 2);
-       sum -= sharpen_getpixel(x, 0);
-       sum -= sharpen_getpixel(x, 2);
+       sum -= sharpen_getpixel(b - 1, 0);
+       sum -= sharpen_getpixel(b - 1, 1);
+       sum -= sharpen_getpixel(b - 1, 2);
+       sum -= sharpen_getpixel(b + 1, 0);
+       sum -= sharpen_getpixel(b + 1, 1);
+       sum -= sharpen_getpixel(b + 1, 2);
+       sum -= sharpen_getpixel(b, 0);
+       sum -= sharpen_getpixel(b, 2);
        return bound(0, sum * a, 1);
 }
 void sharpen_shift(int w)
index cbc6568..1e5fedb 100644 (file)
@@ -226,7 +226,7 @@ void GameCommand_anticheat(float request, float argc)
 
                        if (accepted > 0)
                        {
-                               anticheat_report(client);
+                               anticheat_report_to_eventlog(client);
                                return;
                        }
                        else
@@ -1328,7 +1328,7 @@ void GameCommand_shuffleteams(float request)
                {
                        if (teamplay)
                        {
-                               float x, t_teams, t_players, team_color;
+                               float t_teams, t_players, team_color;
 
                                // count the total amount of players and total amount of teams
                                t_players = 0;
@@ -1366,15 +1366,15 @@ void GameCommand_shuffleteams(float request)
                                for (int i = 1; i <= t_teams; ++i)
                                {
                                        // find out how many players to assign to this team
-                                       x = (t_players / t_teams);
-                                       x = ((i == 1) ? ceil(x) : floor(x));
+                                       int pnum = (t_players / t_teams);
+                                       pnum = ((i == 1) ? ceil(pnum) : floor(pnum));
 
                                        team_color = Team_NumberToTeam(i);
 
                                        // sort through the random list of players made earlier
                                        for (int z = 1; z <= maxclients; ++z)
                                        {
-                                               if (!(shuffleteams_teams[i] >= x))
+                                               if (!(shuffleteams_teams[i] >= pnum))
                                                {
                                                        if (!(shuffleteams_players[z])) continue;  // not a player, move on to next random slot
 
index d1cdb7e..85c5d18 100644 (file)
@@ -334,7 +334,13 @@ void VoteThink()
 // Resets the state of all clients, items, weapons, waypoints, ... of the map.
 void reset_map(bool dorespawn)
 {
-       if (time <= game_starttime && round_handler_IsActive()) round_handler_Reset(game_starttime);
+       if (time <= game_starttime)
+       {
+               if (gameover)
+                       return;
+               if (round_handler_IsActive())
+                       round_handler_Reset(game_starttime);
+       }
 
        MUTATOR_CALLHOOK(reset_map_global);
 
@@ -399,6 +405,9 @@ void ReadyRestart_think(entity this)
 // Forces a restart of the game without actually reloading the map // this is a mess...
 void ReadyRestart_force()
 {
+       if (time <= game_starttime && gameover)
+               return;
+
        bprint("^1Server is restarting...\n");
 
        VoteReset();
index e90dbeb..7f4899f 100644 (file)
@@ -238,6 +238,9 @@ string formatmessage(entity this, string msg)
        cursor = trace_endpos;
        cursor_ent = trace_ent;
 
+       MUTATOR_CALLHOOK(PreFormatMessage, this, msg);
+       msg = M_ARGV(1, string);
+
        while (1) {
                if (n < 1)
                        break; // too many replacements
index 9d7d8af..cab67d0 100644 (file)
@@ -134,6 +134,14 @@ MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
     /**/
 MUTATOR_HOOKABLE(FormatMessage, EV_FormatMessage);
 
+/** called before any formatting is applied, handy for tweaking the message before scripts get ahold of it */
+#define EV_PreFormatMessage(i, o) \
+    /** player        */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** message       */ i(string, MUTATOR_ARGV_1_string) \
+    /**/                 o(string, MUTATOR_ARGV_1_string) \
+    /**/
+MUTATOR_HOOKABLE(PreFormatMessage, EV_PreFormatMessage);
+
 /** returns true if throwing the current weapon shall not be allowed */
 #define EV_ForbidThrowCurrentWeapon(i, o) \
     /** player        */ i(entity, MUTATOR_ARGV_0_entity) \
@@ -359,6 +367,7 @@ MUTATOR_HOOKABLE(PlayerDamage_Calculate, EV_PlayerDamage_Calculate);
     /** armor     */ i(float,    MUTATOR_ARGV_3_float) \
     /** location  */ i(vector, MUTATOR_ARGV_4_vector) \
     /** deathtype */ i(int,    MUTATOR_ARGV_5_int) \
+    /** potential_damage     */ i(float,    MUTATOR_ARGV_6_float) \
     /**/
 MUTATOR_HOOKABLE(PlayerDamaged, EV_PlayerDamaged);
 
@@ -882,3 +891,18 @@ MUTATOR_HOOKABLE(ForbidWeaponUse, EV_ForbidWeaponUse);
     /** keepvelocity? */        i(bool, MUTATOR_ARGV_2_bool) \
     /**/
 MUTATOR_HOOKABLE(CopyBody, EV_CopyBody);
+
+/** called when sending a chat message, ret argument can be changed to prevent the message */
+#define EV_ChatMessage(i, o) \
+    /** sender */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** ret */ i(int, MUTATOR_ARGV_1_int) \
+    /**/ o(int, MUTATOR_ARGV_1_int) \
+    /**/
+MUTATOR_HOOKABLE(ChatMessage, EV_ChatMessage);
+
+/** return true to prevent sending a chat (private, team or regular) message from reaching a certain player */
+#define EV_ChatMessageTo(i, o) \
+    /** destination player */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** sender */ i(entity, MUTATOR_ARGV_1_entity) \
+    /**/
+MUTATOR_HOOKABLE(ChatMessageTo, EV_ChatMessageTo);
index 8009feb..5aba748 100644 (file)
@@ -6,7 +6,7 @@ int autocvar_g_ca_point_limit;
 int autocvar_g_ca_point_leadlimit;
 float autocvar_g_ca_round_timelimit;
 bool autocvar_g_ca_team_spawns;
-int autocvar_g_ca_teams;
+//int autocvar_g_ca_teams;
 int autocvar_g_ca_teams_override;
 float autocvar_g_ca_warmup;
 
@@ -33,7 +33,8 @@ REGISTER_MUTATOR(ca, false)
                allowed_to_spawn = true;
 
                ca_teams = autocvar_g_ca_teams_override;
-               if (ca_teams < 2) ca_teams = autocvar_g_ca_teams;
+               if (ca_teams < 2)
+                       ca_teams = cvar("g_ca_teams"); // read the cvar directly as it gets written earlier in the same frame
                ca_teams = bound(2, ca_teams, 4);
 
                int teams = 0;
index eb94e4f..7f98ed2 100644 (file)
@@ -631,7 +631,10 @@ void dom_DelayedInit(entity this) // Do this check with a delay so we can wait f
        if(find(NULL, classname, "dom_team") == NULL || autocvar_g_domination_teams_override >= 2)
        {
                LOG_TRACE("No \"dom_team\" entities found on this map, creating them anyway.");
-               domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
+               domination_teams = autocvar_g_domination_teams_override;
+               if (domination_teams < 2)
+                       domination_teams = autocvar_g_domination_default_teams;
+               domination_teams = bound(2, domination_teams, 4);
                dom_spawnteams(domination_teams);
        }
 
index 32c91d8..cec7d95 100644 (file)
@@ -3,7 +3,7 @@
 float autocvar_g_freezetag_frozen_maxtime;
 float autocvar_g_freezetag_revive_clearspeed;
 float autocvar_g_freezetag_round_timelimit;
-int autocvar_g_freezetag_teams;
+//int autocvar_g_freezetag_teams;
 int autocvar_g_freezetag_teams_override;
 float autocvar_g_freezetag_warmup;
 
@@ -573,7 +573,7 @@ void freezetag_Initialize()
 {
        freezetag_teams = autocvar_g_freezetag_teams_override;
        if(freezetag_teams < 2)
-               freezetag_teams = autocvar_g_freezetag_teams;
+               freezetag_teams = cvar("g_freezetag_teams"); // read the cvar directly as it gets written earlier in the same frame
        freezetag_teams = bound(2, freezetag_teams, 4);
 
        int teams = 0;
index efed23a..1496fee 100644 (file)
@@ -23,28 +23,18 @@ spawnfunc(invasion_spawnpoint)
 
        this.classname = "invasion_spawnpoint";
        IL_PUSH(g_invasion_spawns, this);
-
-       if(autocvar_g_invasion_zombies_only) // precache only if it hasn't been already
-       if(this.spawnmob)
-       {
-               FOREACH(Monsters, it.netname == this.spawnmob,
-               {
-                       it.mr_precache(it);
-               });
-       }
 }
 
 Monster invasion_PickMonster(int supermonster_count)
 {
-       if(autocvar_g_invasion_zombies_only)
-               return MON_ZOMBIE;
-
        RandomSelection_Init();
 
        FOREACH(Monsters, it != MON_Null,
        {
                if((it.spawnflags & MONSTER_TYPE_PASSIVE) || (it.spawnflags & MONSTER_TYPE_FLY) || (it.spawnflags & MONSTER_TYPE_SWIM) || (it.spawnflags & MONSTER_SIZE_QUAKE) || ((it.spawnflags & MON_FLAG_SUPERMONSTER) && supermonster_count >= 1))
                        continue;
+               if(autocvar_g_invasion_zombies_only && !(it.spawnflags & MONSTER_TYPE_UNDEAD))
+                       continue;
         RandomSelection_AddEnt(it, 1, 1);
        });
 
@@ -77,11 +67,18 @@ void invasion_SpawnChosenMonster(Monster mon)
                setsize(e, mon.mins, mon.maxs);
 
                if(MoveToRandomMapLocation(e, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
-                       monster = spawnmonster(e, "", mon.m_id, NULL, NULL, e.origin, false, false, 2);
-               else return;
+                       monster = spawnmonster(e, "", mon.monsterid, NULL, NULL, e.origin, false, false, 2);
+               else
+               {
+                       delete(e);
+                       return;
+               }
        }
        else // if spawnmob field falls through (unset), fallback to mon (relying on spawnmonster for that behaviour)
-               monster = spawnmonster(spawn(), spawn_point.spawnmob, mon.m_id, spawn_point, spawn_point, spawn_point.origin, false, false, 2);
+               monster = spawnmonster(spawn(), spawn_point.spawnmob, mon.monsterid, spawn_point, spawn_point, spawn_point.origin, false, false, 2);
+
+       if(!monster)
+               return;
 
        if(spawn_point) monster.target2 = spawn_point.target2;
        monster.spawnshieldtime = time;
@@ -465,22 +462,5 @@ void invasion_DelayedInit(entity this) // Do this check with a delay so we can w
 
 void invasion_Initialize()
 {
-       if(autocvar_g_invasion_zombies_only) {
-               Monster mon = MON_ZOMBIE;
-               mon.mr_precache(mon);
-       } else
-       {
-               float i;
-               entity mon;
-               for(i = MON_FIRST; i <= MON_LAST; ++i)
-               {
-                       mon = get_monsterinfo(i);
-                       if((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM))
-                               continue; // flying/swimming monsters not yet supported
-
-                       mon.mr_precache(mon);
-               }
-       }
-
        InitializeEntity(NULL, invasion_DelayedInit, INITPRIO_GAMETYPE);
 }
index 9443115..2954fd1 100644 (file)
@@ -17,7 +17,7 @@ int autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
 int autocvar_g_balance_keyhunt_score_push;
 float autocvar_g_balance_keyhunt_throwvelocity;
 
-int autocvar_g_keyhunt_teams;
+//int autocvar_g_keyhunt_teams;
 int autocvar_g_keyhunt_teams_override;
 
 // #define KH_PLAYER_USE_ATTACHMENT
@@ -47,17 +47,17 @@ bool kh_no_radar_circles;
 //     bits  5- 9: team of key 2, or 0 for no such key, or 30 for dropped, or 31 for self
 //     bits 10-14: team of key 3, or 0 for no such key, or 30 for dropped, or 31 for self
 //     bits 15-19: team of key 4, or 0 for no such key, or 30 for dropped, or 31 for self
-.float kh_state = _STAT(KH_KEYS);
+.int kh_state = _STAT(KH_KEYS);
 .float siren_time;  //  time delay the siren
 //.float stuff_time;  //  time delay to stuffcmd a cvar
 
-float kh_keystatus[17];
+int kh_keystatus[17];
 //kh_keystatus[0] = status of dropped keys, kh_keystatus[1 - 16] = player #
 //replace 17 with cvar("maxplayers") or similar !!!!!!!!!
 //for(i = 0; i < maxplayers; ++i)
 //     kh_keystatus[i] = "0";
 
-float kh_Team_ByID(float t)
+int kh_Team_ByID(int t)
 {
        if(t == 0) return NUM_TEAM_1;
        if(t == 1) return NUM_TEAM_2;
@@ -69,16 +69,17 @@ float kh_Team_ByID(float t)
 //entity kh_worldkeylist;
 .entity kh_worldkeynext;
 entity kh_controller;
-//float kh_tracking_enabled;
-float kh_teams;
-float kh_interferemsg_time, kh_interferemsg_team;
+//bool kh_tracking_enabled;
+int kh_teams;
+int kh_interferemsg_team;
+float kh_interferemsg_time;
 .entity kh_next, kh_prev; // linked list
 .float kh_droptime;
-.float kh_dropperteam;
+.int kh_dropperteam;
 .entity kh_previous_owner;
-.float kh_previous_owner_playerid;
+.int kh_previous_owner_playerid;
 
-float kh_key_dropped, kh_key_carried;
+int kh_key_dropped, kh_key_carried;
 
 int kh_Key_AllOwnedByWhichTeam();
 
@@ -119,10 +120,8 @@ bool kh_Key_waypointsprite_visible_for_player(entity this, entity player, entity
 void kh_update_state()
 {
        entity key;
-       float s;
-       float f;
-
-       s = 0;
+       int f;
+       int s = 0;
        FOR_EACH_KH_KEY(key)
        {
                if(key.owner)
@@ -159,7 +158,10 @@ void kh_Controller_Think(entity this)  // called a lot
        if(intermission_running)
                return;
        if(this.cnt > 0)
-       { if(getthink(this) != kh_WaitForPlayers) { this.cnt -= 1; } }
+       {
+               if(getthink(this) != kh_WaitForPlayers)
+                       this.cnt -= 1;
+       }
        else if(this.cnt == 0)
        {
                this.cnt -= 1;
@@ -214,8 +216,7 @@ vector kh_AttachedOrigin(entity e)  // runs when a team captures the flag, it ca
 void kh_Key_Attach(entity key)  // runs when a player picks up a key and several times when a key is assigned to a player at the start of a round
 {
 #ifdef KH_PLAYER_USE_ATTACHMENT
-       entity first;
-       first = key.owner.kh_next;
+       entity first = key.owner.kh_next;
        if(key == first)
        {
                setattachment(key, key.owner, KH_PLAYER_ATTACHMENT_BONE);
@@ -258,8 +259,7 @@ void kh_Key_Attach(entity key)  // runs when a player picks up a key and several
 void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs several times times when all the keys are captured
 {
 #ifdef KH_PLAYER_USE_ATTACHMENT
-       entity first;
-       first = key.owner.kh_next;
+       entity first = key.owner.kh_next;
        if(key == first)
        {
                if(key.kh_next)
@@ -299,12 +299,10 @@ void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs
 
 void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is picked up or assigned. Runs prior to kh_key_attach
 {
-       entity k;
-       float ownerteam0, ownerteam;
        if(key.owner == player)
                return;
 
-       ownerteam0 = kh_Key_AllOwnedByWhichTeam();
+       int ownerteam0 = kh_Key_AllOwnedByWhichTeam();
 
        if(key.owner)
        {
@@ -376,15 +374,16 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
 
        key.pusher = NULL;
 
-       ownerteam = kh_Key_AllOwnedByWhichTeam();
+       int ownerteam = kh_Key_AllOwnedByWhichTeam();
        if(ownerteam != ownerteam0)
        {
+               entity k;
                if(ownerteam != -1)
                {
                        kh_interferemsg_time = time + 0.2;
                        kh_interferemsg_team = player.team;
 
-                       // audit all key carrier sprites, update them to RUN HERE
+                       // audit all key carrier sprites, update them to "Run here"
                        FOR_EACH_KH_KEY(k)
                        {
                                if (!k.owner) continue;
@@ -399,7 +398,7 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                {
                        kh_interferemsg_time = 0;
 
-                       // audit all key carrier sprites, update them to RUN HERE
+                       // audit all key carrier sprites, update them to "Key Carrier"
                        FOR_EACH_KH_KEY(k)
                        {
                                if (!k.owner) continue;
@@ -441,7 +440,8 @@ void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped ke
                PlayerScore_Add(player, SP_KH_PICKUPS, 1);
        }
        key.kh_dropperteam = 0;
-       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_PICKUP), player.netname);
+       int realteam = kh_Team_ByID(key.count);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_PICKUP), player.netname);
 
        kh_Key_AssignTo(key, player); // this also updates .kh_state
 }
@@ -474,8 +474,7 @@ void kh_Key_Touch(entity this, entity toucher)  // runs many, many times when a
 
 void kh_Key_Remove(entity key)  // runs after when all the keys have been collected or when a key has been dropped for more than X seconds
 {
-       entity o;
-       o = key.owner;
+       entity o = key.owner;
        kh_Key_AssignTo(key, NULL);
        if(o) // it was attached
                WaypointSprite_Kill(key.waypointsprite_attachedforcarrier);
@@ -521,27 +520,23 @@ void kh_FinishRound()  // runs when a team captures the keys
 
 void nades_GiveBonus(entity player, float score);
 
-void kh_WinnerTeam(float teem)  // runs when a team wins // Samual: Teem?.... TEEM?!?! what the fuck is wrong with you people
+void kh_WinnerTeam(int winner_team)  // runs when a team wins
 {
        // all key carriers get some points
-       vector firstorigin, lastorigin, midpoint;
-       float first;
        entity key;
-       float score;
-       score = (NumTeams(kh_teams) - 1) * autocvar_g_balance_keyhunt_score_capture;
+       float score = (NumTeams(kh_teams) - 1) * autocvar_g_balance_keyhunt_score_capture;
        DistributeEvenly_Init(score, NumTeams(kh_teams));
        // twice the score for 3 team games, three times the score for 4 team games!
        // note: for a win by destroying the key, this should NOT be applied
        FOR_EACH_KH_KEY(key)
        {
-               float f;
-               f = DistributeEvenly_Get(1);
+               float f = DistributeEvenly_Get(1);
                kh_Scores_Event(key.owner, key, "capture", f, 0);
                PlayerTeamScore_Add(key.owner, SP_KH_CAPS, ST_KH_CAPS, 1);
                nades_GiveBonus(key.owner, autocvar_g_nades_bonus_score_high);
        }
 
-       first = true;
+       bool first = true;
        string keyowner = "";
        FOR_EACH_KH_KEY(key)
                if(key.owner.kh_next == key)
@@ -552,17 +547,13 @@ void kh_WinnerTeam(float teem)  // runs when a team wins // Samual: Teem?.... TE
                        first = false;
                }
 
-       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(teem, INFO_KEYHUNT_CAPTURE), keyowner);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_KEYHUNT_CAPTURE), keyowner);
 
        first = true;
-       midpoint = '0 0 0';
-       firstorigin = '0 0 0';
-       lastorigin = '0 0 0';
+       vector firstorigin = '0 0 0', lastorigin = '0 0 0', midpoint = '0 0 0';
        FOR_EACH_KH_KEY(key)
        {
-               vector thisorigin;
-
-               thisorigin = kh_AttachedOrigin(key);
+               vector thisorigin = kh_AttachedOrigin(key);
                //dprint("Key origin: ", vtos(thisorigin), "\n");
                midpoint += thisorigin;
 
@@ -578,27 +569,21 @@ void kh_WinnerTeam(float teem)  // runs when a team wins // Samual: Teem?.... TE
                te_lightning2(NULL, lastorigin, firstorigin);
        }
        midpoint = midpoint * (1 / NumTeams(kh_teams));
-       te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5');  // make the color >=0.5 in each component
+       te_customflash(midpoint, 1000, 1, Team_ColorRGB(winner_team) * 0.5 + '0.5 0.5 0.5');  // make the color >=0.5 in each component
 
        play2all(SND(KH_CAPTURE));
        kh_FinishRound();
 }
 
-void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a flag carrier off the map
+void kh_LoserTeam(int loser_team, entity lostkey)  // runs when a player pushes a flag carrier off the map
 {
-       entity key, attacker;
-       float players;
-       float keys;
        float f;
-
-       attacker = NULL;
+       entity attacker = NULL;
        if(lostkey.pusher)
-               if(lostkey.pusher.team != teem)
+               if(lostkey.pusher.team != loser_team)
                        if(IS_PLAYER(lostkey.pusher))
                                attacker = lostkey.pusher;
 
-       players = keys = 0;
-
        if(attacker)
        {
                if(lostkey.kh_previous_owner)
@@ -610,13 +595,15 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
        }
        else
        {
-               float of, fragsleft, i, j, thisteam;
-               of = autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
+               int players = 0;
+               float of = autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
 
-               FOREACH_CLIENT(IS_PLAYER(it) && it.team != teem, LAMBDA(++players));
+               FOREACH_CLIENT(IS_PLAYER(it) && it.team != loser_team, LAMBDA(++players));
 
+               entity key;
+               int keys = 0;
                FOR_EACH_KH_KEY(key)
-                       if(key.owner && key.team != teem)
+                       if(key.owner && key.team != loser_team)
                                ++keys;
 
                if(lostkey.kh_previous_owner)
@@ -629,20 +616,20 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
                DistributeEvenly_Init(autocvar_g_balance_keyhunt_score_destroyed, keys * of + players);
 
                FOR_EACH_KH_KEY(key)
-                       if(key.owner && key.team != teem)
+                       if(key.owner && key.team != loser_team)
                        {
                                f = DistributeEvenly_Get(of);
                                kh_Scores_Event(key.owner, NULL, "destroyed_holdingkey", f, 0);
                        }
 
-               fragsleft = DistributeEvenly_Get(players);
+               int fragsleft = DistributeEvenly_Get(players);
 
                // Now distribute these among all other teams...
-               j = NumTeams(kh_teams) - 1;
-               for(i = 0; i < NumTeams(kh_teams); ++i)
+               int j = NumTeams(kh_teams) - 1;
+               for(int i = 0; i < NumTeams(kh_teams); ++i)
                {
-                       thisteam = kh_Team_ByID(i);
-                       if(thisteam == teem) // bad boy, no cookie - this WILL happen
+                       int thisteam = kh_Team_ByID(i);
+                       if(thisteam == loser_team) // bad boy, no cookie - this WILL happen
                                continue;
 
                        players = 0;
@@ -661,7 +648,8 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
                }
        }
 
-       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(lostkey.team, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
+       int realteam = kh_Team_ByID(lostkey.count);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
 
        play2all(SND(KH_DESTROY));
        te_tarexplosion(lostkey.origin);
@@ -697,8 +685,7 @@ void kh_Key_Think(entity this)  // runs all the time
                }
 
                entity key;
-               vector p;
-               p = this.owner.origin;
+               vector p = this.owner.origin;
                FOR_EACH_KH_KEY(key)
                        if(vdist(key.owner.origin - p, >, autocvar_g_balance_keyhunt_maxdist))
                                goto not_winning;
@@ -806,15 +793,15 @@ int kh_Key_AllOwnedByWhichTeam()  // constantly called. check to see if all the
 void kh_Key_DropOne(entity key)
 {
        // prevent collecting this one for some time
-       entity player;
-       player = key.owner;
+       entity player = key.owner;
 
        key.kh_droptime = time;
        key.enemy = player;
 
        kh_Scores_Event(player, key, "dropkey", 0, 0);
        PlayerScore_Add(player, SP_KH_LOSSES, 1);
-       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_DROP), player.netname);
+       int realteam = kh_Team_ByID(key.count);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_DROP), player.netname);
 
        kh_Key_AssignTo(key, NULL);
        makevectors(player.v_angle);
@@ -828,19 +815,20 @@ void kh_Key_DropOne(entity key)
 
 void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
 {
-       entity key;
-       entity mypusher;
        if(player.kh_next)
        {
-               mypusher = NULL;
+               entity mypusher = NULL;
                if(player.pusher)
                        if(time < player.pushltime)
                                mypusher = player.pusher;
+
+               entity key;
                while((key = player.kh_next))
                {
                        kh_Scores_Event(player, key, "losekey", 0, 0);
                        PlayerScore_Add(player, SP_KH_LOSSES, 1);
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_LOST), player.netname);
+                       int realteam = kh_Team_ByID(key.count);
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(realteam, INFO_KEYHUNT_LOST), player.netname);
                        kh_Key_AssignTo(key, NULL);
                        makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
                        key.velocity = W_CalculateProjectileVelocity(player, player.velocity, autocvar_g_balance_keyhunt_dropvelocity * v_forward, false);
@@ -918,8 +906,6 @@ void kh_EnableTrackingDevice()  // runs after each round
 
 void kh_StartRound()  // runs at the start of each round
 {
-       int i, players, teem;
-
        if(time < game_starttime)
        {
                kh_Controller_SetThink(game_starttime - time + 0.1, kh_WaitForPlayers);
@@ -935,10 +921,10 @@ void kh_StartRound()  // runs at the start of each round
        Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_KEYHUNT);
        Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_KEYHUNT_OTHER);
 
-       for(i = 0; i < NumTeams(kh_teams); ++i)
+       for(int i = 0; i < NumTeams(kh_teams); ++i)
        {
-               teem = kh_Team_ByID(i);
-               players = 0;
+               int teem = kh_Team_ByID(i);
+               int players = 0;
                entity my_player = NULL;
                FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
                        if(!IS_DEAD(it) && !PHYS_INPUT_BUTTON_CHAT(it) && it.team == teem)
@@ -965,10 +951,8 @@ float kh_HandleFrags(entity attacker, entity targ, float f)  // adds to the play
        {
                if(attacker.team == targ.team)
                {
-                       entity k;
-                       float nk;
-                       nk = 0;
-                       for(k = targ.kh_next; k != NULL; k = k.kh_next)
+                       int nk = 0;
+                       for(entity k = targ.kh_next; k != NULL; k = k.kh_next)
                                ++nk;
                        kh_Scores_Event(attacker, targ.kh_next, "carrierfrag", -nk * autocvar_g_balance_keyhunt_score_collect, 0);
                }
@@ -988,7 +972,7 @@ void kh_Initialize()  // sets up th KH environment
        // setup variables
        kh_teams = autocvar_g_keyhunt_teams_override;
        if(kh_teams < 2)
-               kh_teams = autocvar_g_keyhunt_teams;
+               kh_teams = cvar("g_keyhunt_teams"); // read the cvar directly as it gets written earlier in the same frame
        kh_teams = bound(2, kh_teams, 4);
 
        int teams = 0;
@@ -1212,12 +1196,10 @@ void havocbot_role_kh_freelancer(entity this)
 
        if (this.bot_strategytime&n