set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
set sv_track_canjump 0 "track if the player released the jump key between 2 jumps to decide if they are able to jump or not"
+set sv_jumpvelocity_crouch 0 "jump height while crouching, set to 0 to use regular jump height"
set sv_precacheplayermodels 1
set sv_precacheweapons 0
set sv_dodging_air_dodging 0
set sv_dodging_wall_dodging 0 "allow dodging off walls"
-set sv_dodging_delay 0.5 "determines how long a player has to wait to be able to dodge again after dodging"
+set sv_dodging_delay 0.6 "determines how long a player has to wait to be able to dodge again after dodging"
set sv_dodging_up_speed 200 "the jump velocity of the dodge"
-set sv_dodging_horiz_speed 400 "the horizontal velocity of the dodge"
-set sv_dodging_horiz_speed_frozen 200 "the horizontal velocity of the dodge while frozen"
+set sv_dodging_horiz_speed_min 200 "the lower bound of current velocity for force scaling"
+set sv_dodging_horiz_speed_max 1000 "the upper bound of current velocity for force scaling"
+set sv_dodging_horiz_force_slowest 400 "the horizontal velocity of the dodge when current velocity is <= sv_dodging_horiz_speed_min, values between min and max are linearly scaled"
+set sv_dodging_horiz_force_fastest 400 "the horizontal velocity of the dodge when current velocity is >= sv_dodging_horiz_speed_max, values between min and max are linearly scaled"
+set sv_dodging_horiz_force_frozen 200 "the horizontal velocity of the dodge while frozen"
set sv_dodging_ramp_time 0.1 "a ramp so that the horizontal part of the dodge is added smoothly (seconds)"
set sv_dodging_height_threshold 10 "the maximum height above ground where to allow dodging"
set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging"
set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent"
set sv_dodging_frozen 0 "allow dodging while frozen"
set sv_dodging_frozen_doubletap 0
-set sv_dodging_maxspeed 450 "maximum speed a player can be moving at before they dodge again"
+set sv_dodging_maxspeed 350 "maximum speed a player can be moving at to use the standard dodging from an (almost) standstill"
+set sv_dodging_air_maxspeed 450 "maximum speed a player can be moving at before they dodge again when air dodging is enabled"
// ===========
set g_dynamic_handicap_min 0 "The minimum value of the handicap."
set g_dynamic_handicap_max 0 "The maximum value of the handicap."
+// =====================
+// stale-move negation
+// =====================
+set g_smneg 0 "Stale-move negation: penalize repeated use of the same weapon"
+set g_smneg_bonus 1 "Stale-move negation: allow weapons to become stronger than their baseline"
+set g_smneg_bonus_asymptote 4 "Stale-move negation: damage = infinity at this bonus level"
+set g_smneg_cooldown_factor 0.25 "Stale-move negation: penalty cooldown factor"
+
// ==============
// random items
// ==============
set g_random_items 0 "Whether to enable random items."
-set g_random_items_replace_item_health_small "random" "Classnames to replace small health with."
-set g_random_items_replace_item_health_medium "random" "Classnames to replace medium health with."
-set g_random_items_replace_item_health_big "random" "Classnames to replace big health with."
-set g_random_items_replace_item_health_mega "random" "Classnames to replace mega health with."
-set g_random_items_replace_item_armor_small "random" "Classnames to replace small armor with."
-set g_random_items_replace_item_armor_medium "random" "Classnames to replace medium armor with."
-set g_random_items_replace_item_armor_big "random" "Classnames to replace big armor with."
-set g_random_items_replace_item_armor_mega "random" "Classnames to replace mega armor with."
-set g_random_items_replace_item_shells "random" "Classnames to replace shells with."
-set g_random_items_replace_item_bullets "random" "Classnames to replace bullets with."
-set g_random_items_replace_item_rockets "random" "Classnames to replace rockets with."
-set g_random_items_replace_item_cells "random" "Classnames to replace cells with."
-set g_random_items_replace_item_plasma "random" "Classnames to replace plasma with."
-set g_random_items_replace_item_fuel "random" "Classnames to replace fuel with."
-set g_random_items_replace_weapon_blaster "random" "Classnames to replace blaster with."
-set g_random_items_replace_weapon_shotgun "random" "Classnames to replace shotgun with."
-set g_random_items_replace_weapon_machinegun "random" "Classnames to replace machinegun with."
-set g_random_items_replace_weapon_mortar "random" "Classnames to replace mortar with."
-set g_random_items_replace_weapon_electro "random" "Classnames to replace electro with."
-set g_random_items_replace_weapon_crylink "random" "Classnames to replace crylink with."
-set g_random_items_replace_weapon_vortex "random" "Classnames to replace vortex with."
-set g_random_items_replace_weapon_hagar "random" "Classnames to replace hagar with."
-set g_random_items_replace_weapon_devastator "random" "Classnames to replace devastator with."
-set g_random_items_replace_weapon_shockwave "random" "Classnames to replace shockwave with."
-set g_random_items_replace_weapon_arc "random" "Classnames to replace arc with."
-set g_random_items_replace_weapon_hook "random" "Classnames to replace hook with."
-set g_random_items_replace_weapon_tuba "random" "Classnames to replace tuba with."
-set g_random_items_replace_weapon_porto "random" "Classnames to replace port-o-launch with."
-set g_random_items_replace_weapon_fireball "random" "Classnames to replace fireball with."
-set g_random_items_replace_weapon_minelayer "random" "Classnames to replace mine layer with."
-set g_random_items_replace_weapon_hlac "random" "Classnames to replace HLAC with."
-set g_random_items_replace_weapon_rifle "random" "Classnames to replace rifle with."
-set g_random_items_replace_weapon_seeker "random" "Classnames to replace TAG seeker with."
-set g_random_items_replace_weapon_vaporizer "random" "Classnames to replace vaporizer with."
-set g_random_items_replace_weapon_hmg "random" "Classnames to replace HMG with."
-set g_random_items_replace_weapon_rpc "random" "Classnames to replace RPC with."
-set g_random_items_replace_item_strength "random" "Classnames to replace strength with."
-set g_random_items_replace_item_shield "random" "Classnames to replace shield with."
-set g_random_items_replace_item_fuel_regen "random" "Classnames to replace fuel regeneration with."
-set g_random_items_replace_item_jetpack "random" "Classnames to replace jetpack with."
-set g_random_items_replace_item_vaporizer_cells "random" "Classnames to replace vaporizer cells with."
-set g_random_items_replace_item_invisibility "random" "Classnames to replace invisibility with."
-set g_random_items_replace_item_extralife "random" "Classnames to replace extra life with."
-set g_random_items_replace_item_speed "random" "Classnames to replace speed with."
-set g_random_items_health_probability 1 "Probability of random health items spawning in the map."
-set g_random_items_armor_probability 1 "Probability of random armor items spawning in the map."
-set g_random_items_resource_probability 1 "Probability of random resource items spawning in the map."
-set g_random_items_weapon_probability 1 "Probability of random weapons spawning in the map."
-set g_random_items_powerup_probability 0.15 "Probability of random powerups spawning in the map."
-set g_random_items_item_health_small_probability 10 "Probability of random small health spawning in the map."
-set g_random_items_item_health_medium_probability 4 "Probability of random medium health spawning in the map."
-set g_random_items_item_health_big_probability 2 "Probability of random big health spawning in the map."
-set g_random_items_item_health_mega_probability 1 "Probability of random mega health spawning in the map."
-set g_random_items_item_armor_small_probability 10 "Probability of random small armor spawning in the map."
-set g_random_items_item_armor_medium_probability 4 "Probability of random medium armor spawning in the map."
-set g_random_items_item_armor_big_probability 2 "Probability of random big armor spawning in the map."
-set g_random_items_item_armor_mega_probability 1 "Probability of random mega armor spawning in the map."
-set g_random_items_item_shells_probability 1 "Probability of random shells spawning in the map."
-set g_random_items_item_bullets_probability 1 "Probability of random bullets spawning in the map."
-set g_random_items_item_rockets_probability 1 "Probability of random rockets spawning in the map."
-set g_random_items_item_cells_probability 1 "Probability of random cells spawning in the map."
-set g_random_items_item_plasma_probability 0 "Probability of random plasma spawning in the map."
-set g_random_items_item_fuel_probability 0 "Probability of random fuel spawning in the map."
-set g_random_items_weapon_blaster_probability 0 "Probability of random blaster spawning in the map."
-set g_random_items_weapon_shotgun_probability 0 "Probability of random shotgun spawning in the map."
-set g_random_items_weapon_machinegun_probability 1 "Probability of random machinegun spawning in the map."
-set g_random_items_weapon_mortar_probability 1 "Probability of random mortar spawning in the map."
-set g_random_items_weapon_electro_probability 1 "Probability of random electro spawning in the map."
-set g_random_items_weapon_crylink_probability 1 "Probability of random crylink spawning in the map."
-set g_random_items_weapon_vortex_probability 1 "Probability of random vortex spawning in the map."
-set g_random_items_weapon_hagar_probability 1 "Probability of random hagar spawning in the map."
-set g_random_items_weapon_devastator_probability 1 "Probability of random devastator spawning in the map."
-set g_random_items_weapon_shockwave_probability 0 "Probability of random shockwave spawning in the map."
-set g_random_items_weapon_arc_probability 0 "Probability of random arc spawning in the map."
-set g_random_items_weapon_hook_probability 0 "Probability of random hook spawning in the map."
-set g_random_items_weapon_tuba_probability 0 "Probability of random tuba spawning in the map."
-set g_random_items_weapon_porto_probability 0 "Probability of random port-o-launch spawning in the map."
-set g_random_items_weapon_fireball_probability 0 "Probability of random fireball spawning in the map."
-set g_random_items_weapon_minelayer_probability 0 "Probability of random mine layer spawning in the map."
-set g_random_items_weapon_hlac_probability 0 "Probability of random HLAC spawning in the map."
-set g_random_items_weapon_rifle_probability 0 "Probability of random rifle spawning in the map."
-set g_random_items_weapon_seeker_probability 0 "Probability of random TAG seeker spawning in the map."
-set g_random_items_weapon_vaporizer_probability 0 "Probability of random vaporizer spawning in the map."
-set g_random_items_item_strength_probability 1 "Probability of random strength spawning in the map."
-set g_random_items_item_shield_probability 1 "Probability of random shield spawning in the map."
-set g_random_items_item_fuel_regen_probability 0 "Probability of random fuel regeneration spawning in the map."
-set g_random_items_item_jetpack_probability 0 "Probability of random jetpack spawning in the map."
-set g_random_items_item_vaporizer_cells_probability 20 "Probability of random vaporizer cells spawning in the map."
-set g_random_items_item_invisibility_probability 1 "Probability of random invisibility spawning in the map."
-set g_random_items_item_extralife_probability 1 "Probability of random extra life spawning in the map."
-set g_random_items_item_speed_probability 1 "Probability of random speed spawning in the map."
-set g_random_items_overkill_item_health_mega_probability 1 "Probability of random mega health spawning in the map during overkill."
-set g_random_items_overkill_item_armor_small_probability 10 "Probability of random small armor spawning in the map during overkill."
-set g_random_items_overkill_item_armor_medium_probability 4 "Probability of random medium armor spawning in the map during overkill."
-set g_random_items_overkill_item_armor_big_probability 2 "Probability of random big armor spawning in the map during overkill."
-set g_random_items_overkill_item_armor_mega_probability 1 "Probability of random mega armor spawning in the map during overkill."
-set g_random_items_overkill_weapon_hmg_probability 0.5 "Probability of random HMG spawning in the map during overkill."
-set g_random_items_overkill_weapon_rpc_probability 0.5 "Probability of random RPC spawning in the map during overkill."
set g_random_loot 0 "Whether to enable random loot."
-set g_random_loot_min 0 "Minimum amount of loot items."
-set g_random_loot_max 4 "Maximum amount of loot items."
-set g_random_loot_time 10 "Amount of time the loot will stay in seconds."
-set g_random_loot_spread 200 "How far can loot be thrown."
-set g_random_loot_health_probability 1 "Probability of random health items spawning as loot."
-set g_random_loot_armor_probability 1 "Probability of random armor items spawning as loot."
-set g_random_loot_resource_probability 1 "Probability of random ammo items spawning as loot."
-set g_random_loot_weapon_probability 1 "Probability of random weapons spawning as loot."
-set g_random_loot_powerup_probability 0.2 "Probability of random powerups spawning as loot."
-set g_random_loot_item_health_small_probability 4 "Probability of random small health spawning as loot."
-set g_random_loot_item_health_medium_probability 3 "Probability of random medium health spawning as loot."
-set g_random_loot_item_health_big_probability 2 "Probability of random big health spawning as loot."
-set g_random_loot_item_health_mega_probability 1 "Probability of random mega health spawning as loot."
-set g_random_loot_item_armor_small_probability 4 "Probability of random small armor spawning as loot."
-set g_random_loot_item_armor_medium_probability 3 "Probability of random medium armor spawning as loot."
-set g_random_loot_item_armor_big_probability 2 "Probability of random big armor spawning as loot."
-set g_random_loot_item_armor_mega_probability 1 "Probability of random mega armor spawning as loot."
-set g_random_loot_item_shells_probability 1 "Probability of random shells spawning as loot."
-set g_random_loot_item_bullets_probability 1 "Probability of random bullets spawning as loot."
-set g_random_loot_item_rockets_probability 1 "Probability of random rockets spawning as loot."
-set g_random_loot_item_cells_probability 1 "Probability of random cells spawning as loot."
-set g_random_loot_item_plasma_probability 0 "Probability of random plasma spawning as loot."
-set g_random_loot_item_fuel_probability 0 "Probability of random fuel spawning as loot."
-set g_random_loot_weapon_blaster_probability 0 "Probability of random blaster spawning as loot."
-set g_random_loot_weapon_shotgun_probability 0 "Probability of random shotgun spawning as loot."
-set g_random_loot_weapon_machinegun_probability 1 "Probability of random machinegun spawning as loot."
-set g_random_loot_weapon_mortar_probability 1 "Probability of random mortar spawning as loot."
-set g_random_loot_weapon_electro_probability 1 "Probability of random electro spawning as loot."
-set g_random_loot_weapon_crylink_probability 1 "Probability of random crylink spawning as loot."
-set g_random_loot_weapon_vortex_probability 1 "Probability of random vortex spawning as loot."
-set g_random_loot_weapon_hagar_probability 1 "Probability of random hagar spawning as loot."
-set g_random_loot_weapon_devastator_probability 1 "Probability of random devastator spawning as loot."
-set g_random_loot_weapon_shockwave_probability 0 "Probability of random shockwave spawning as loot."
-set g_random_loot_weapon_arc_probability 0 "Probability of random arc spawning as loot."
-set g_random_loot_weapon_hook_probability 0 "Probability of random hook spawning as loot."
-set g_random_loot_weapon_tuba_probability 0 "Probability of random tuba spawning as loot."
-set g_random_loot_weapon_porto_probability 0 "Probability of random port-o-launch spawning as loot."
-set g_random_loot_weapon_fireball_probability 0 "Probability of random fireball spawning as loot."
-set g_random_loot_weapon_minelayer_probability 0 "Probability of random mine layer spawning as loot."
-set g_random_loot_weapon_hlac_probability 0 "Probability of random HLAC spawning as loot."
-set g_random_loot_weapon_rifle_probability 0 "Probability of random rifle spawning as loot."
-set g_random_loot_weapon_seeker_probability 0 "Probability of random TAG seeker spawning as loot."
-set g_random_loot_weapon_vaporizer_probability 0 "Probability of random vaporizer spawning as loot."
-set g_random_loot_item_strength_probability 1 "Probability of random strength spawning as loot."
-set g_random_loot_item_shield_probability 1 "Probability of random shield spawning as loot."
-set g_random_loot_item_fuel_regen_probability 0 "Probability of random fuel regeneration spawning as loot."
-set g_random_loot_item_jetpack_probability 0 "Probability of random jetpack spawning as loot."
-set g_random_loot_item_vaporizer_cells_probability 20 "Probability of random vaporizer cells spawning as loot."
-set g_random_loot_item_invisibility_probability 1 "Probability of random invisibility spawning as loot."
-set g_random_loot_item_extralife_probability 1 "Probability of random extra life spawning as loot."
-set g_random_loot_item_speed_probability 1 "Probability of random speed spawning as loot."
-set g_random_loot_overkill_item_health_mega_probability 1 "Probability of random mega health spawning as loot during overkill."
-set g_random_loot_overkill_item_armor_small_probability 10 "Probability of random small armor spawning as loot during overkill."
-set g_random_loot_overkill_item_armor_medium_probability 4 "Probability of random medium armor spawning as loot during overkill."
-set g_random_loot_overkill_item_armor_big_probability 2 "Probability of random big armor spawning as loot during overkill."
-set g_random_loot_overkill_item_armor_mega_probability 1 "Probability of random mega armor spawning as loot during overkill."
-set g_random_loot_overkill_weapon_hmg_probability 1 "Probability of random HMG spawning as loot during overkill."
-set g_random_loot_overkill_weapon_rpc_probability 1 "Probability of random RPC spawning as loot during overkill."
+exec randomitems-xonotic.cfg
set g_physics_xonotic_airspeedlimit_nonqw 900
set g_physics_xonotic_maxspeed 360
set g_physics_xonotic_jumpvelocity 260
+set g_physics_xonotic_jumpvelocity_crouch 0
set g_physics_xonotic_maxairstrafespeed 100
set g_physics_xonotic_maxairspeed 360
set g_physics_xonotic_airstrafeaccelerate 18
set g_physics_nexuiz_airspeedlimit_nonqw 0
set g_physics_nexuiz_maxspeed 400
set g_physics_nexuiz_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_nexuiz_jumpvelocity_crouch 0 "333 to match xonotic physics"
set g_physics_nexuiz_maxairstrafespeed 0
set g_physics_nexuiz_maxairspeed 220
set g_physics_nexuiz_airstrafeaccelerate 0
set g_physics_quake_airspeedlimit_nonqw 0
set g_physics_quake_maxspeed 320
set g_physics_quake_jumpvelocity 270
+set g_physics_quake_jumpvelocity_crouch 0
set g_physics_quake_maxairstrafespeed 0
set g_physics_quake_maxairspeed 30
set g_physics_quake_airstrafeaccelerate 0
set g_physics_warsow_airspeedlimit_nonqw 0
set g_physics_warsow_maxspeed 320
set g_physics_warsow_jumpvelocity 280
+set g_physics_warsow_jumpvelocity_crouch 0
set g_physics_warsow_maxairstrafespeed 30
set g_physics_warsow_maxairspeed 320
set g_physics_warsow_airstrafeaccelerate 70
set g_physics_defrag_airspeedlimit_nonqw 0
set g_physics_defrag_maxspeed 320
set g_physics_defrag_jumpvelocity 270
+set g_physics_defrag_jumpvelocity_crouch 0
set g_physics_defrag_maxairstrafespeed 30
set g_physics_defrag_maxairspeed 320
set g_physics_defrag_airstrafeaccelerate 70
set g_physics_quake3_airspeedlimit_nonqw 0
set g_physics_quake3_maxspeed 320
set g_physics_quake3_jumpvelocity 270
+set g_physics_quake3_jumpvelocity_crouch 0
set g_physics_quake3_maxairstrafespeed 0
set g_physics_quake3_maxairspeed 320
set g_physics_quake3_airstrafeaccelerate 0
set g_physics_vecxis_airspeedlimit_nonqw 0
set g_physics_vecxis_maxspeed 400
set g_physics_vecxis_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_vecxis_jumpvelocity_crouch 0 "333 to match xonotic physics"
set g_physics_vecxis_maxairstrafespeed 0
set g_physics_vecxis_maxairspeed 220
set g_physics_vecxis_airstrafeaccelerate 0
set g_physics_quake2_airspeedlimit_nonqw 0
set g_physics_quake2_maxspeed 300
set g_physics_quake2_jumpvelocity 270
+set g_physics_quake2_jumpvelocity_crouch 0
set g_physics_quake2_maxairstrafespeed 0
set g_physics_quake2_maxairspeed 300
set g_physics_quake2_airstrafeaccelerate 0
set g_physics_bones_airspeedlimit_nonqw 0
set g_physics_bones_maxspeed 320
set g_physics_bones_jumpvelocity 270
+set g_physics_bones_jumpvelocity_crouch 0
set g_physics_bones_maxairstrafespeed 30
set g_physics_bones_maxairspeed 320
set g_physics_bones_airstrafeaccelerate 70
set g_physics_overkill_airspeedlimit_nonqw 900
set g_physics_overkill_maxspeed 400
set g_physics_overkill_jumpvelocity 260
+set g_physics_overkill_jumpvelocity_crouch 0
set g_physics_overkill_maxairstrafespeed 100
set g_physics_overkill_maxairspeed 360
set g_physics_overkill_airstrafeaccelerate 24
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 4
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0 // breaks strafing?
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.65
// actually, what we want is 266.6666 for 180bpm
// but 260 takes same amount of frames and is nicer to mappers
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0 // breaks strafing?
// actually, what we want is 266.6666 for 180bpm
// but 260 takes same amount of frames and is nicer to mappers
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1 // div0 says no! lol
sv_stepheight 26
sv_jumpvelocity 304
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0 // pain in the ass to tweak without screwing up the strafing
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 310
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.35
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.3
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.35
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.35
// actually, what we want is 266.6666 for 180bpm
// but 260 takes same amount of frames and is nicer to mappers
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
// this is smaller than 112 qu, so a 112 qu high corridor (7 of 8 grid units in
// the 16 grid, and the 8th unit used for wall/floor) just lets a player jump!
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 4
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.8
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.5
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0.3
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 280
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 10
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 280
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 10
sv_waterfriction 1
sv_airaccel_sideways_friction 0
edgefriction 1
sv_stepheight 18
sv_jumpvelocity 280
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 10
sv_waterfriction 1
sv_airaccel_sideways_friction 0
// this is smaller than 112 qu, so a 112 qu high corridor (7 of 8 grid units in
// the 16 grid, and the 8th unit used for wall/floor) just lets a player jump!
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
// actually, what we want is 266.6666 for 180bpm
// but 260 takes same amount of frames and is nicer to mappers
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
// this is smaller than 112 qu, so a 112 qu high corridor (7 of 8 grid units in
// the 16 grid, and the 8th unit used for wall/floor) just lets a player jump!
sv_jumpvelocity 260
+sv_jumpvelocity_crouch 0
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0
sv_stepheight 26
// CPMA: 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 4
sv_waterfriction 1
sv_airaccel_sideways_friction 0
sv_stepheight 26
// CPMA: 18
sv_jumpvelocity 270
+sv_jumpvelocity_crouch 0
sv_wateraccelerate 4
sv_waterfriction 1
sv_airaccel_sideways_friction 0
const int acc_decimals = 2;
if(time > physics_update_time)
{
+ discrete_acceleration = acceleration;
// workaround for ftos_decimals returning a negative 0
if(discrete_acceleration > -1 / (10 ** acc_decimals) && discrete_acceleration < 0)
discrete_acceleration = 0;
- discrete_acceleration = acceleration;
discrete_speed = speed;
physics_update_time += autocvar_hud_panel_physics_update_interval;
if(physics_update_time < time)
#endif
-enum {
- ITEM_FLAG_MUTATORBLOCKED = BIT(0)
+enum
+{
+ ITEM_FLAG_NORMAL = BIT(0), ///< Item is usable during normal gameplay.
+ ITEM_FLAG_INSTAGIB = BIT(1), ///< Item is usable in instagib.
+ ITEM_FLAG_OVERKILL = BIT(2), ///< Item is usable in overkill.
+ ITEM_FLAG_MUTATORBLOCKED = BIT(3)
};
#define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
REGISTER_ITEM(Bullets, Bullets) {
this.m_canonical_spawnfunc = "item_bullets";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Bullets_ITEM;
#endif
this.netname = "bullets";
REGISTER_ITEM(Cells, Ammo) {
this.m_canonical_spawnfunc = "item_cells";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Cells_ITEM;
#endif
this.netname = "cells";
REGISTER_ITEM(Plasma, Ammo) {
this.m_canonical_spawnfunc = "item_plasma";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Plasma_ITEM;
#endif
this.netname = "plasma";
REGISTER_ITEM(Rockets, Ammo) {
this.m_canonical_spawnfunc = "item_rockets";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Rockets_ITEM;
#endif
this.netname = "rockets";
REGISTER_ITEM(Shells, Shells) {
this.m_canonical_spawnfunc = "item_shells";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Shells_ITEM;
#endif
this.netname = "shells";
REGISTER_ITEM(ArmorSmall, Armor) {
this.m_canonical_spawnfunc = "item_armor_small";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL | ITEM_FLAG_OVERKILL;
this.m_model = MDL_ArmorSmall_ITEM;
this.m_sound = SND_ArmorSmall;
#endif
REGISTER_ITEM(ArmorMedium, Armor) {
this.m_canonical_spawnfunc = "item_armor_medium";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL | ITEM_FLAG_OVERKILL;
this.m_model = MDL_ArmorMedium_ITEM;
this.m_sound = SND_ArmorMedium;
#endif
REGISTER_ITEM(ArmorBig, Armor) {
this.m_canonical_spawnfunc = "item_armor_big";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL | ITEM_FLAG_OVERKILL;
this.m_model = MDL_ArmorBig_ITEM;
this.m_sound = SND_ArmorBig;
#endif
REGISTER_ITEM(ArmorMega, Armor) {
this.m_canonical_spawnfunc = "item_armor_mega";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL | ITEM_FLAG_OVERKILL;
this.m_model = MDL_ArmorMega_ITEM;
this.m_sound = SND_ArmorMega;
#endif
REGISTER_ITEM(HealthSmall, Health) {
this.m_canonical_spawnfunc = "item_health_small";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_HealthSmall_ITEM;
this.m_sound = SND_HealthSmall;
#endif
REGISTER_ITEM(HealthMedium, Health) {
this.m_canonical_spawnfunc = "item_health_medium";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_HealthMedium_ITEM;
this.m_sound = SND_HealthMedium;
#endif
REGISTER_ITEM(HealthBig, Health) {
this.m_canonical_spawnfunc = "item_health_big";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_HealthBig_ITEM;
this.m_sound = SND_HealthBig;
#endif
REGISTER_ITEM(HealthMega, Health) {
this.m_canonical_spawnfunc = "item_health_mega";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL | ITEM_FLAG_OVERKILL;
this.m_model = MDL_HealthMega_ITEM;
this.m_sound = SND_HealthMega;
#endif
REGISTER_ITEM(Jetpack, Powerup) {
this.m_canonical_spawnfunc = "item_jetpack";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Jetpack_ITEM;
this.m_itemid = IT_JETPACK;
#endif
REGISTER_ITEM(JetpackFuel, Ammo) {
this.m_canonical_spawnfunc = "item_fuel";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_JetpackFuel_ITEM;
#endif
this.netname = "fuel";
REGISTER_ITEM(JetpackRegen, JetpackRegen) {
this.m_canonical_spawnfunc = "item_fuel_regen";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_JetpackRegen_ITEM;
#endif
this.netname = "fuel_regen";
REGISTER_ITEM(Strength, Powerup) {
this.m_canonical_spawnfunc = "item_strength";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Strength_ITEM;
this.m_sound = SND_Strength;
this.m_glow = true;
REGISTER_ITEM(Shield, Powerup) {
this.m_canonical_spawnfunc = "item_shield";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_NORMAL;
this.m_model = MDL_Shield_ITEM;
this.m_sound = SND_Shield;
this.m_glow = true;
#include <common/mutators/mutator/running_guns/_mod.inc>
#include <common/mutators/mutator/sandbox/_mod.inc>
#include <common/mutators/mutator/spawn_near_teammate/_mod.inc>
+#include <common/mutators/mutator/stale_move_negation/_mod.inc>
#include <common/mutators/mutator/superspec/_mod.inc>
#include <common/mutators/mutator/touchexplode/_mod.inc>
#include <common/mutators/mutator/vampire/_mod.inc>
#include <common/mutators/mutator/running_guns/_mod.qh>
#include <common/mutators/mutator/sandbox/_mod.qh>
#include <common/mutators/mutator/spawn_near_teammate/_mod.qh>
+#include <common/mutators/mutator/stale_move_negation/_mod.qh>
#include <common/mutators/mutator/superspec/_mod.qh>
#include <common/mutators/mutator/touchexplode/_mod.qh>
#include <common/mutators/mutator/vampire/_mod.qh>
#include "sv_dodging.qh"
+// TODO the CSQC blocks in this sv_ file are currently not compiled but will be when dodging prediction gets enabled
+
#define PHYS_DODGING g_dodging
#define PHYS_DODGING_DELAY autocvar_sv_dodging_delay
#define PHYS_DODGING_DISTANCE_THRESHOLD autocvar_sv_dodging_wall_distance_threshold
-#define PHYS_DODGING_FROZEN_NODOUBLETAP autocvar_sv_dodging_frozen_doubletap
+#define PHYS_DODGING_FROZEN_DOUBLETAP autocvar_sv_dodging_frozen_doubletap
#define PHYS_DODGING_HEIGHT_THRESHOLD autocvar_sv_dodging_height_threshold
-#define PHYS_DODGING_HORIZ_SPEED autocvar_sv_dodging_horiz_speed
-#define PHYS_DODGING_HORIZ_SPEED_FROZEN autocvar_sv_dodging_horiz_speed_frozen
+#define PHYS_DODGING_HORIZ_SPEED_MIN autocvar_sv_dodging_horiz_speed_min
+#define PHYS_DODGING_HORIZ_SPEED_MAX autocvar_sv_dodging_horiz_speed_max
+#define PHYS_DODGING_HORIZ_FORCE_SLOWEST autocvar_sv_dodging_horiz_force_slowest
+#define PHYS_DODGING_HORIZ_FORCE_FASTEST autocvar_sv_dodging_horiz_force_fastest
+#define PHYS_DODGING_HORIZ_FORCE_FROZEN autocvar_sv_dodging_horiz_force_frozen
#define PHYS_DODGING_RAMP_TIME autocvar_sv_dodging_ramp_time
#define PHYS_DODGING_UP_SPEED autocvar_sv_dodging_up_speed
#define PHYS_DODGING_WALL autocvar_sv_dodging_wall_dodging
#define PHYS_DODGING_AIR autocvar_sv_dodging_air_dodging
#define PHYS_DODGING_MAXSPEED autocvar_sv_dodging_maxspeed
+#define PHYS_DODGING_AIR_MAXSPEED autocvar_sv_dodging_air_maxspeed
// we ran out of stats slots! TODO: re-enable this when prediction is available for dodging
#if 0
#define PHYS_DODGING STAT(DODGING, this)
#define PHYS_DODGING_DELAY STAT(DODGING_DELAY, this)
#define PHYS_DODGING_DISTANCE_THRESHOLD STAT(DODGING_DISTANCE_THRESHOLD, this)
-#define PHYS_DODGING_FROZEN_NODOUBLETAP STAT(DODGING_FROZEN_NO_DOUBLETAP, this)
+#define PHYS_DODGING_FROZEN_DOUBLETAP STAT(DODGING_FROZEN_DOUBLETAP, this)
#define PHYS_DODGING_HEIGHT_THRESHOLD STAT(DODGING_HEIGHT_THRESHOLD, this)
-#define PHYS_DODGING_HORIZ_SPEED STAT(DODGING_HORIZ_SPEED, this)
-#define PHYS_DODGING_HORIZ_SPEED_FROZEN STAT(DODGING_HORIZ_SPEED_FROZEN, this)
+#define PHYS_DODGING_HORIZ_SPEED_MIN STAT(DODGING_HORIZ_SPEED_MIN, this)
+#define PHYS_DODGING_HORIZ_SPEED_MAX STAT(DODGING_HORIZ_SPEED_MAX, this)
+#define PHYS_DODGING_HORIZ_FORCE_SLOWEST STAT(DODGING_HORIZ_FORCE_SLOWEST, this)
+#define PHYS_DODGING_HORIZ_FORCE_FASTEST STAT(DODGING_HORIZ_FORCE_FASTEST, this)
+#define PHYS_DODGING_HORIZ_FORCE_FROZEN STAT(DODGING_HORIZ_FORCE_FROZEN, this)
#define PHYS_DODGING_RAMP_TIME STAT(DODGING_RAMP_TIME, this)
#define PHYS_DODGING_UP_SPEED STAT(DODGING_UP_SPEED, this)
#define PHYS_DODGING_WALL STAT(DODGING_WALL, this)
#define PHYS_DODGING_AIR STAT(DODGING_AIR, this)
#define PHYS_DODGING_MAXSPEED STAT(DODGING_MAXSPEED, this)
+#define PHYS_DODGING_AIR_MAXSPEED STAT(DODGING_AIR_MAXSPEED, this)
#endif
#ifdef CSQC
bool autocvar_sv_dodging_sound;
-// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
-.float dodging_action;
-
-// the jump part of the dodge cannot be ramped
-.float dodging_single_action;
-
#include <common/animdecide.qh>
#include <common/physics/player.qh>
// the jump part of the dodge cannot be ramped
.float dodging_single_action;
-
// these are used to store the last key press time for each of the keys..
.float last_FORWARD_KEY_time;
.float last_BACKWARD_KEY_time;
// and to ramp up the dodge acceleration in the physics hook.
.float last_dodging_time;
-// This is the velocity gain to be added over the ramp time.
-// It will decrease from frame to frame during dodging_action = 1
-// until it's 0.
-.float dodging_velocity_gain;
+// the total speed that will be added over the ramp time
+.float dodging_force_total;
+// the part of total yet to be added
+.float dodging_force_remaining;
#ifdef CSQC
.int pressedkeys;
#endif
-// returns true if the player is close to a wall
-bool check_close_to_wall(entity this, float threshold)
-{
- if (PHYS_DODGING_WALL == 0) { return false; }
-
#define X(dir) \
tracebox(this.origin, this.mins, this.maxs, this.origin + threshold * dir, true, this); \
if (trace_fraction < 1 && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) \
return true;
+// returns true if the player is close to a wall
+bool is_close_to_wall(entity this, float threshold)
+{
X(v_right);
X(-v_right);
X(v_forward);
X(-v_forward);
-#undef X
return false;
}
-bool check_close_to_ground(entity this, float threshold)
+bool is_close_to_ground(entity this, float threshold)
{
- return IS_ONGROUND(this) ? true : false;
+ if (IS_ONGROUND(this)) return true;
+ X(-v_up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
+
+ return false;
+}
+
+#undef X
+
+float determine_force(entity player) {
+ if (PHYS_FROZEN(player)) return PHYS_DODGING_HORIZ_FORCE_FROZEN;
+
+ float horiz_vel = vlen(vec2(player.velocity));
+ return map_bound_ranges(horiz_vel,
+ PHYS_DODGING_HORIZ_SPEED_MIN, PHYS_DODGING_HORIZ_SPEED_MAX,
+ PHYS_DODGING_HORIZ_FORCE_SLOWEST, PHYS_DODGING_HORIZ_FORCE_FASTEST);
}
bool PM_dodging_checkpressedkeys(entity this)
{
- if(!PHYS_DODGING)
- return false;
-
bool frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN(this));
- bool frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
+ bool frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_DOUBLETAP);
+
+ float tap_direction_x = 0;
+ float tap_direction_y = 0;
+ bool dodge_detected = false;
+ vector mymovement = PHYS_CS(this).movement;
- // first check if the last dodge is far enough back in time so we can dodge again
+ #define X(COND,BTN,RESULT) \
+ if (mymovement_##COND) { \
+ /* is this a state change? */ \
+ 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; \
+ } else if(PHYS_INPUT_BUTTON_DODGE(this)) { \
+ dodge_detected = true; \
+ } \
+ this.last_##BTN##_KEY_time = time; \
+ } \
+ }
+ X(x < 0, BACKWARD, x--);
+ X(x > 0, FORWARD, x++);
+ X(y < 0, LEFT, y--);
+ X(y > 0, RIGHT, y++);
+ #undef X
+
+ if (!dodge_detected) return false;
+
+ // this check has to be after checking keys:
+ // the first key press of the double tap is allowed to be before dodging delay,
+ // only the second has to be after, otherwise +dodge gives an advantage because typical repress time is 0.1 s
+ // or higher which means players using +dodge would be able to do it more often
if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
return false;
makevectors(this.angles);
- bool wall_dodge = false;
+ bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
+ bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD));
+ bool can_air_dodge = (PHYS_DODGING_AIR && (PHYS_DODGING_AIR_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_AIR_MAXSPEED)));
+ if (!can_dodge && !can_wall_dodge && !can_air_dodge) return false;
- if(!PHYS_DODGING_AIR)
- if(!check_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD))
- {
- wall_dodge = check_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD);
- if(!wall_dodge) // we're not on the ground, and wall dodging isn't allowed, end it!
- return true;
- }
+ this.last_dodging_time = time;
- if(!wall_dodge && PHYS_DODGING_MAXSPEED && vdist(this.velocity, >, PHYS_DODGING_MAXSPEED))
- return false;
+ this.dodging_action = 1;
+ this.dodging_single_action = 1;
- float tap_direction_x = 0;
- float tap_direction_y = 0;
- bool dodge_detected = false;
- vector mymovement = PHYS_CS(this).movement;
+ this.dodging_force_total = determine_force(this);
+ this.dodging_force_remaining = this.dodging_force_total;
- #define X(COND,BTN,RESULT) \
- if (mymovement_##COND) \
- /* is this a state change? */ \
- 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; \
- if(PHYS_INPUT_BUTTON_DODGE(this)) \
- dodge_detected = true; \
- this.last_##BTN##_KEY_time = time; \
- }
- X(x < 0, BACKWARD, x--);
- X(x > 0, FORWARD, x++);
- X(y < 0, LEFT, y--);
- X(y > 0, RIGHT, y++);
- #undef X
-
- if (dodge_detected)
- {
- this.last_dodging_time = time;
-
- this.dodging_action = 1;
- this.dodging_single_action = 1;
+ this.dodging_direction.x = tap_direction_x;
+ this.dodging_direction.y = tap_direction_y;
- this.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
+ // normalize the dodging_direction vector.. (unlike UT99) XD
+ float length = sqrt(this.dodging_direction.x ** 2 + this.dodging_direction.y ** 2);
- this.dodging_direction_x = tap_direction_x;
- this.dodging_direction_y = tap_direction_y;
+ this.dodging_direction.x = this.dodging_direction.x / length;
+ this.dodging_direction.y = this.dodging_direction.y / length;
- // normalize the dodging_direction vector.. (unlike UT99) XD
- float length = this.dodging_direction_x * this.dodging_direction_x
- + this.dodging_direction_y * this.dodging_direction_y;
- length = sqrt(length);
-
- this.dodging_direction_x = this.dodging_direction_x * 1.0 / length;
- this.dodging_direction_y = this.dodging_direction_y * 1.0 / length;
- return true;
- }
- return false;
+ return true;
}
void PM_dodging(entity this)
{
- if (!PHYS_DODGING)
- return;
+ // can't use return value from PM_dodging_checkpressedkeys because they're called from different hooks
+ if (!this.dodging_action) return;
// when swimming or dead, no dodging allowed..
if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this))
{
this.dodging_action = 0;
- this.dodging_direction_x = 0;
- this.dodging_direction_y = 0;
+ this.dodging_direction.x = 0;
+ this.dodging_direction.y = 0;
return;
}
else
makevectors(this.angles);
+ // fraction of the force to apply each frame
// if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
// will be called ramp_time/frametime times = 2 times. so, we need to
// add 0.5 * the total speed each frame until the dodge action is done..
float common_factor = PHYS_DODGING_FRAMETIME / PHYS_DODGING_RAMP_TIME;
+ // NOTE: depending on cl_netfps the client may (and probably will) send more input frames during each server frame
+ // but common_factor uses server frame rate so players with higher cl_netfps will ramp slightly faster
- // if ramp time is smaller than frametime we get problems ;D
- common_factor = min(common_factor, 1);
-
- float horiz_speed = PHYS_FROZEN(this) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
- float new_velocity_gain = this.dodging_velocity_gain - (common_factor * horiz_speed);
- new_velocity_gain = max(0, new_velocity_gain);
-
- float velocity_difference = this.dodging_velocity_gain - new_velocity_gain;
-
- // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
- if (this.dodging_action == 1)
- {
- //disable jump key during dodge accel phase
- if(PHYS_CS(this).movement.z > 0) { PHYS_CS(this).movement_z = 0; }
-
- this.velocity += ((this.dodging_direction_y * velocity_difference) * v_right)
- + ((this.dodging_direction_x * velocity_difference) * v_forward);
-
- this.dodging_velocity_gain = this.dodging_velocity_gain - velocity_difference;
- }
+ float velocity_increase = min(common_factor * this.dodging_force_total, this.dodging_force_remaining);
+ this.dodging_force_remaining -= velocity_increase;
+ this.velocity += this.dodging_direction.x * velocity_increase * v_forward
+ + this.dodging_direction.y * velocity_increase * v_right;
// the up part of the dodge is a single shot action
if (this.dodging_single_action == 1)
this.dodging_single_action = 0;
}
- // are we done with the dodging ramp yet?
- if((this.dodging_action == 1) && ((time - this.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
+ if(this.dodging_force_remaining <= 0)
{
// reset state so next dodge can be done correctly
this.dodging_action = 0;
- this.dodging_direction_x = 0;
- this.dodging_direction_y = 0;
+ this.dodging_direction.x = 0;
+ this.dodging_direction.y = 0;
}
}
+#ifdef CSQC
void PM_dodging_GetPressedKeys(entity this)
{
-#ifdef CSQC
- if(!PHYS_DODGING) { return; }
-
PM_dodging_checkpressedkeys(this);
int keys = this.pressedkeys;
keys = BITSET(keys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(this));
keys = BITSET(keys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(this));
this.pressedkeys = keys;
-#endif
}
+#endif
MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
{
- entity player = M_ARGV(0, entity);
+ entity player = M_ARGV(0, entity);
- // print("dodging_PlayerPhysics\n");
+#ifdef CSQC
PM_dodging_GetPressedKeys(player);
+#endif
PM_dodging(player);
}
REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
-MUTATOR_HOOKFUNCTION(dodging, PlayerPreThink)
-{
- entity player = M_ARGV(0, entity);
-
- STAT(DODGING_TIMEOUT, player) = CS(player).cvar_cl_dodging_timeout;
-}
-
MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
{
entity player = M_ARGV(0, entity);
#endif
REGISTER_ITEM(VaporizerCells, Ammo) {
this.m_canonical_spawnfunc = "item_vaporizer_cells";
- this.spawnflags = ITEM_FLAG_MUTATORBLOCKED;
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_INSTAGIB | ITEM_FLAG_MUTATORBLOCKED;
this.m_model = MDL_VaporizerCells_ITEM;
this.m_sound = SND_VaporizerCells;
#endif
REGISTER_ITEM(ExtraLife, Powerup) {
this.m_canonical_spawnfunc = "item_extralife";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_INSTAGIB;
this.m_model = MDL_ExtraLife_ITEM;
this.m_sound = SND_ExtraLife;
#endif
REGISTER_ITEM(Invisibility, Powerup) {
this.m_canonical_spawnfunc = "item_invisibility";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_INSTAGIB;
this.m_model = MDL_Invisibility_ITEM;
this.m_sound = SND_Invisibility;
this.m_glow = true;
REGISTER_ITEM(Speed, Powerup) {
this.m_canonical_spawnfunc = "item_speed";
#ifdef GAMEQC
+ this.spawnflags = ITEM_FLAG_INSTAGIB;
this.m_model = MDL_Speed_ITEM;
this.m_sound = SND_Speed;
this.m_glow = true;
{
precache_all_playermodels("models/ok_player/*.dpm");
+ if (autocvar_g_overkill_filter_healthmega)
+ {
+ ITEM_HealthMega.spawnflags |= ITEM_FLAG_MUTATORBLOCKED;
+ }
+ if (autocvar_g_overkill_filter_armormedium)
+ {
+ ITEM_ArmorMedium.spawnflags |= ITEM_FLAG_MUTATORBLOCKED;
+ }
+ if (autocvar_g_overkill_filter_armorbig)
+ {
+ ITEM_ArmorBig.spawnflags |= ITEM_FLAG_MUTATORBLOCKED;
+ }
+ if (autocvar_g_overkill_filter_armormega)
+ {
+ ITEM_ArmorMega.spawnflags |= ITEM_FLAG_MUTATORBLOCKED;
+ }
+
WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
MUTATOR_ONREMOVE
{
+ ITEM_HealthMega.spawnflags &= ~ITEM_FLAG_MUTATORBLOCKED;
+ ITEM_ArmorMedium.spawnflags &= ~ITEM_FLAG_MUTATORBLOCKED;
+ ITEM_ArmorBig.spawnflags &= ~ITEM_FLAG_MUTATORBLOCKED;
+ ITEM_ArmorMega.spawnflags &= ~ITEM_FLAG_MUTATORBLOCKED;
+
WEP_RPC.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
WEP_HMG.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
}
if(item.ok_item)
return false;
- switch(item.itemdef)
- {
- case ITEM_HealthMega: return autocvar_g_overkill_filter_healthmega;
- case ITEM_ArmorMedium: return autocvar_g_overkill_filter_armormedium;
- case ITEM_ArmorBig: return autocvar_g_overkill_filter_armorbig;
- case ITEM_ArmorMega: return autocvar_g_overkill_filter_armormega;
- }
-
return true;
}
// Map probability cvars
-/// \brief Probability of random health items spawning in the map.
-float autocvar_g_random_items_health_probability;
-/// \brief Probability of random armor items spawning in the map.
-float autocvar_g_random_items_armor_probability;
-/// \brief Probability of random resource items spawning in the map.
-float autocvar_g_random_items_resource_probability;
-/// \brief Probability of random weapons spawning in the map.
-float autocvar_g_random_items_weapon_probability;
-/// \brief Probability of random powerups spawning in the map.
-float autocvar_g_random_items_powerup_probability;
-
/// \brief Probability of random %s spawning in the map.
/// float autocvar_g_random_items_%s_probability;
// Loot probability cvars
-/// \brief Probability of random health items spawning as loot.
-float autocvar_g_random_loot_health_probability;
-/// \brief Probability of random armor items spawning as loot.
-float autocvar_g_random_loot_armor_probability;
-/// \brief Probability of random resource items spawning as loot.
-float autocvar_g_random_loot_resource_probability;
-/// \brief Probability of random weapons spawning as loot.
-float autocvar_g_random_loot_weapon_probability;
-/// \brief Probability of random powerups spawning as loot.
-float autocvar_g_random_loot_powerup_probability;
-
/// \brief Probability of random %s spawning as loot.
-/// float autocvar_g_random_loot_weapon_%s_probability;
+/// float autocvar_g_random_loot_%s_probability;
/// \brief Probability of random %s spawning as loot during overkill.
/// float autocvar_g_random_loot_overkill_%s_probability;
/// recursion.
bool random_items_is_spawning = false;
-//========================= Free functions ====================================
+//====================== Forward declarations =================================
-string RandomItems_GetItemVarName(string class_name)
+/// \brief Returns a random classname of the item with specific property.
+/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \return Random classname of the item.
+string RandomItems_GetRandomItemClassNameWithProperty(string prefix,
+ .bool item_property);
+
+//=========================== Public API ======================================
+
+string RandomItems_GetRandomItemClassName(string prefix)
{
- if (startsWith(class_name, "weapon_"))
+ if (autocvar_g_instagib)
{
- FOREACH(Weapons, it.m_canonical_spawnfunc == class_name, {
- if (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)
- {
- return "";
- }
- return class_name;
- });
- }
- bool is_ok = expr_evaluate(autocvar_g_overkill);
- switch (class_name)
- {
- #define X(classname) case #classname: return #classname
- #define XCOND(classname, var, expr) case #classname: if (expr) return #var; else break
- X(item_health_small);
- X(item_health_medium);
- X(item_health_big);
- XCOND(item_health_mega, item_health_mega, !is_ok || !autocvar_g_overkill_filter_healthmega);
-
- X(item_armor_small);
- XCOND(item_armor_medium, item_armor_medium, !is_ok || !autocvar_g_overkill_filter_armormedium);
- XCOND(item_armor_big, item_armor_big, !is_ok || !autocvar_g_overkill_filter_armorbig);
- XCOND(item_armor_mega, item_armor_mega, !is_ok || !autocvar_g_overkill_filter_armormega);
-
- X(item_shells);
- X(item_bullets);
- X(item_rockets);
- X(item_cells);
- X(item_plasma);
- X(item_fuel);
-
- X(item_strength);
- X(item_shield);
- X(item_fuel_regen);
- X(item_jetpack);
-
- X(item_vaporizer_cells);
- X(item_invisibility);
- X(item_extralife);
- X(item_speed);
-
- #undef X
- #undef XCOND
+ return RandomItems_GetRandomInstagibItemClassName(prefix);
}
- return "";
-}
-
-/// \brief Returns list of classnames to replace a map item with.
-/// \param[in] item Item to inspect.
-/// \return List of classnames to replace a map item with.
-string RandomItems_GetItemReplacementClassNames(entity item)
-{
- string class_name = RandomItems_GetItemVarName(item.classname);
- if (class_name)
+ if (expr_evaluate(autocvar_g_overkill))
{
- return cvar_string(sprintf("g_random_items_replace_%s", class_name));
+ return RandomItems_GetRandomOverkillItemClassName(prefix);
}
- return "";
+ return RandomItems_GetRandomVanillaItemClassName(prefix);
}
-/// \brief Returns a random classname of the instagib map item.
-/// \return Random classname of the instagib map item.
-string RandomItems_GetRandomInstagibMapItemClassName()
+string RandomItems_GetRandomVanillaItemClassName(string prefix)
{
RandomSelection_Init();
- #define X(classname) \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_items_%s_probability", RandomItems_GetItemVarName(classname))), \
- 1 \
- )
- X("item_vaporizer_cells");
- X("item_invisibility");
- X("item_extralife");
- X("item_speed");
- #undef X
- return RandomSelection_chosen_string;
-}
-
-/// \brief Returns a random classname of the overkill map item.
-/// \return Random classname of the overkill map item.
-string RandomItems_GetRandomOverkillMapItemClassName()
-{
- RandomSelection_Init();
- string varname;
- #define X(classname) MACRO_BEGIN \
- if ((varname = RandomItems_GetItemVarName(classname))) \
- { \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_items_overkill_%s_probability", varname)), \
- 1 \
- ); \
- } \
- MACRO_END
- X("item_health_mega");
- X("item_armor_small");
- X("item_armor_medium");
- X("item_armor_big");
- X("item_armor_mega");
- X("weapon_hmg");
- X("weapon_rpc");
- #undef X
- return RandomSelection_chosen_string;
-}
-
-/// \brief Returns a random classname of the map item.
-/// \return Random classname of the map item.
-string RandomItems_GetRandomMapItemClassName()
-{
- if (autocvar_g_instagib)
+ string cvar_name = sprintf("g_%s_health_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
{
- return RandomItems_GetRandomInstagibMapItemClassName();
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
}
- if (expr_evaluate(autocvar_g_overkill))
+ else
{
- return RandomItems_GetRandomOverkillMapItemClassName();
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH, cvar(cvar_name), 1);
+ }
+ cvar_name = sprintf("g_%s_armor_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR, cvar(cvar_name), 1);
+ }
+ cvar_name = sprintf("g_%s_resource_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE, cvar(cvar_name), 1);
+ }
+ cvar_name = sprintf("g_%s_weapon_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
+ }
+ cvar_name = sprintf("g_%s_powerup_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
}
- RandomSelection_Init();
- #define X(type, name) \
- RandomSelection_AddFloat( \
- RANDOM_ITEM_TYPE_##type, \
- autocvar_g_random_items_##name##_probability, \
- 1 \
- )
- X(HEALTH, health);
- X(ARMOR, armor);
- X(RESOURCE, resource);
- X(WEAPON, weapon);
- X(POWERUP, powerup);
- #undef X
int item_type = RandomSelection_chosen_float;
switch (item_type)
{
case RANDOM_ITEM_TYPE_HEALTH:
{
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfHealth,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_items_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
+ return RandomItems_GetRandomItemClassNameWithProperty(prefix,
+ instanceOfHealth);
}
case RANDOM_ITEM_TYPE_ARMOR:
{
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfArmor,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_items_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
+ return RandomItems_GetRandomItemClassNameWithProperty(prefix,
+ instanceOfArmor);
}
case RANDOM_ITEM_TYPE_RESOURCE:
{
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfAmmo,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_items_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
+ return RandomItems_GetRandomItemClassNameWithProperty(prefix,
+ instanceOfAmmo);
}
case RANDOM_ITEM_TYPE_WEAPON:
{
FOREACH(Weapons, it != WEP_Null &&
!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
{
- string cvar_name = sprintf("g_random_items_%s_probability",
+ cvar_name = sprintf("g_%s_%s_probability", prefix,
it.m_canonical_spawnfunc);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.",
+ cvar_name);
+ continue;
+ }
RandomSelection_AddString(it.m_canonical_spawnfunc,
cvar(cvar_name), 1);
});
}
case RANDOM_ITEM_TYPE_POWERUP:
{
- RandomSelection_Init();
- #define X(classname) \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_items_%s_probability", classname)), \
- 1 \
- )
- X("item_strength");
- X("item_shield");
- X("item_fuel_regen");
- X("item_jetpack");
- #undef X
- return RandomSelection_chosen_string;
+ return RandomItems_GetRandomItemClassNameWithProperty(prefix,
+ instanceOfPowerup);
}
}
return "";
}
+string RandomItems_GetRandomInstagibItemClassName(string prefix)
+{
+ RandomSelection_Init();
+ FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB,
+ {
+ string cvar_name = sprintf("g_%s_%s_probability", prefix,
+ it.m_canonical_spawnfunc);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ continue;
+ }
+ RandomSelection_AddString(it.m_canonical_spawnfunc, cvar(cvar_name), 1);
+ });
+ return RandomSelection_chosen_string;
+}
+
+string RandomItems_GetRandomOverkillItemClassName(string prefix)
+{
+ RandomSelection_Init();
+ FOREACH(Items, (it.spawnflags & ITEM_FLAG_OVERKILL) &&
+ !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED),
+ {
+ string cvar_name = sprintf("g_%s_overkill_%s_probability", prefix,
+ it.m_canonical_spawnfunc);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ continue;
+ }
+ RandomSelection_AddString(it.m_canonical_spawnfunc, cvar(cvar_name), 1);
+ });
+ string cvar_name = sprintf("g_%s_overkill_weapon_hmg_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddString("weapon_hmg", cvar(cvar_name), 1);
+ }
+ cvar_name = sprintf("g_%s_overkill_weapon_rpc_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddString("weapon_rpc", cvar(cvar_name), 1);
+ }
+ return RandomSelection_chosen_string;
+}
+
+//========================= Free functions ====================================
+
+/// \brief Returns list of classnames to replace a map item with.
+/// \param[in] item Item to inspect.
+/// \return List of classnames to replace a map item with.
+string RandomItems_GetItemReplacementClassNames(entity item)
+{
+ string cvar_name = sprintf("g_random_items_replace_%s", item.classname);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ return "";
+ }
+ return cvar_string(cvar_name);
+}
+
+string RandomItems_GetRandomItemClassNameWithProperty(string prefix,
+ .bool item_property)
+{
+ RandomSelection_Init();
+ FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL),
+ {
+ string cvar_name = sprintf("g_%s_%s_probability", prefix,
+ it.m_canonical_spawnfunc);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ continue;
+ }
+ RandomSelection_AddString(it.m_canonical_spawnfunc, cvar(cvar_name), 1);
+ });
+ return RandomSelection_chosen_string;
+}
+
/// \brief Replaces a map item.
/// \param[in] item Item to replace.
/// \return Spawned item on success, NULL otherwise.
string new_classname;
if (new_classnames == "random")
{
- new_classname = RandomItems_GetRandomMapItemClassName();
+ new_classname = RandomItems_GetRandomItemClassName("random_items");
if (new_classname == "")
{
return NULL;
entity new_item;
if (!expr_evaluate(autocvar_g_overkill))
{
- new_item = Item_Create(strzone(new_classname), item.origin);
+ new_item = Item_Create(strzone(new_classname), item.origin,
+ item.noalign);
random_items_is_spawning = false;
if (new_item == NULL)
{
new_item = spawn();
new_item.classname = strzone(new_classname);
new_item.spawnfunc_checked = true;
+ new_item.noalign = item.noalign;
new_item.ok_item = true;
Item_Initialize(new_item, new_classname);
random_items_is_spawning = false;
return new_item;
}
-/// \brief Returns a random classname of the instagib loot item.
-/// \return Random classname of the instagib loot item.
-string RandomItems_GetRandomInstagibLootItemClassName()
-{
- RandomSelection_Init();
- #define X(classname) \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_loot_%s_probability", RandomItems_GetItemVarName(classname))), \
- 1 \
- )
- X("item_vaporizer_cells");
- X("item_invisibility");
- X("item_extralife");
- X("item_speed");
- #undef X
- return RandomSelection_chosen_string;
-}
-
-/// \brief Returns a random classname of the overkill loot item.
-/// \return Random classname of the overkill loot item.
-string RandomItems_GetRandomOverkillLootItemClassName()
-{
- RandomSelection_Init();
- string varname;
- #define X(classname) MACRO_BEGIN \
- if ((varname = RandomItems_GetItemVarName(classname))) \
- { \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_loot_overkill_%s_probability", varname)), \
- 1 \
- ); \
- } \
- MACRO_END
- X("item_health_mega");
- X("item_armor_small");
- X("item_armor_medium");
- X("item_armor_big");
- X("item_armor_mega");
- X("weapon_hmg");
- X("weapon_rpc");
- #undef X
- return RandomSelection_chosen_string;
-}
-
-/// \brief Returns a random classname of the loot item.
-/// \return Random classname of the loot item.
-string RandomItems_GetRandomLootItemClassName()
-{
- if (autocvar_g_instagib)
- {
- return RandomItems_GetRandomInstagibLootItemClassName();
- }
- if (expr_evaluate(autocvar_g_overkill))
- {
- return RandomItems_GetRandomOverkillLootItemClassName();
- }
- RandomSelection_Init();
- #define X(type, name) \
- RandomSelection_AddFloat( \
- RANDOM_ITEM_TYPE_##type, \
- autocvar_g_random_loot_##name##_probability, \
- 1 \
- )
- X(HEALTH, health);
- X(ARMOR, armor);
- X(RESOURCE, resource);
- X(WEAPON, weapon);
- X(POWERUP, powerup);
- #undef X
- int item_type = RandomSelection_chosen_float;
- switch (item_type)
- {
- case RANDOM_ITEM_TYPE_HEALTH:
- {
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfHealth,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_loot_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
- }
- case RANDOM_ITEM_TYPE_ARMOR:
- {
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfArmor,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_loot_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
- }
- case RANDOM_ITEM_TYPE_RESOURCE:
- {
- RandomSelection_Init();
- FOREACH(Items, it.instanceOfAmmo,
- {
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(sprintf("g_random_loot_%s_probability",
- it.m_canonical_spawnfunc)), 1);
- });
- return RandomSelection_chosen_string;
- }
- case RANDOM_ITEM_TYPE_WEAPON:
- {
- RandomSelection_Init();
- FOREACH(Weapons, it != WEP_Null &&
- !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
- {
- string cvar_name = sprintf("g_random_loot_%s_probability",
- it.m_canonical_spawnfunc);
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(cvar_name), 1);
- });
- return RandomSelection_chosen_string;
- }
- case RANDOM_ITEM_TYPE_POWERUP:
- {
- RandomSelection_Init();
- #define X(classname) \
- RandomSelection_AddString( \
- classname, \
- cvar(sprintf("g_random_loot_%s_probability", classname)), \
- 1 \
- )
- X("item_strength");
- X("item_shield");
- X("item_jetpack");
- X("item_fuel_regen");
- #undef X
- return RandomSelection_chosen_string;
- }
- }
- return "";
-}
-
/// \brief Spawns a random loot item.
/// \param[in] position Position of the item.
/// \return No return.
void RandomItems_SpawnLootItem(vector position)
{
- string class_name = RandomItems_GetRandomLootItemClassName();
+ string class_name = RandomItems_GetRandomItemClassName("random_loot");
if (class_name == "")
{
return;
#pragma once
+/// \file
+/// \brief Header file that describes the random items mutator.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
bool autocvar_g_random_items; ///< Whether to enable random items.
+
+/// \brief Returns a random classname of the item.
+/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \return Random classname of the item.
+/// \note This function will automatically detect gamemode and use cvars from
+/// that gamemode.
+string RandomItems_GetRandomItemClassName(string prefix);
+
+/// \brief Returns a random classname of the vanilla item.
+/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \return Random classname of the vanilla item.
+/// \note This includes mutator items that don't change gameplay a lot such as
+/// jetpack and new toys.
+string RandomItems_GetRandomVanillaItemClassName(string prefix);
+
+/// \brief Returns a random classname of the instagib item.
+/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \return Random classname of the instagib item.
+string RandomItems_GetRandomInstagibItemClassName(string prefix);
+
+/// \brief Returns a random classname of the overkill item.
+/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \return Random classname of the overkill item.
+string RandomItems_GetRandomOverkillItemClassName(string prefix);
--- /dev/null
+// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/stale_move_negation/sv_stale_move_negation.qc>
+#endif
--- /dev/null
+// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/stale_move_negation/sv_stale_move_negation.qh>
+#endif
--- /dev/null
+#include "sv_stale_move_negation.qh"
+
+AUTOCVAR(g_smneg, bool, false, "Stale-move negation: penalize repeated use of the same weapon");
+AUTOCVAR(g_smneg_bonus, bool, true, "Stale-move negation: allow weapons to become stronger than their baseline");
+AUTOCVAR(g_smneg_bonus_asymptote, float, 4, "Stale-move negation: damage = infinity at this bonus level");
+AUTOCVAR(g_smneg_cooldown_factor, float, 1 / 4, "Stale-move negation: penalty cooldown factor");
+REGISTER_MUTATOR(mutator_smneg, autocvar_g_smneg);
+
+MUTATOR_HOOKFUNCTION(mutator_smneg, BuildMutatorsString) {
+ M_ARGV(0, string) = strcat(M_ARGV(0, string), ":StaleMoveNegation");
+}
+
+MUTATOR_HOOKFUNCTION(mutator_smneg, BuildMutatorsPrettyString) {
+ M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Stale-move negation");
+}
+
+.float x_smneg_weight[Weapons_MAX];
+
+float smneg_multiplier(float weight) {
+ float a = autocvar_g_smneg_bonus_asymptote;
+ float x = max(
+ (!autocvar_g_smneg_bonus ? 0 : (-a + .1)),
+ weight / start_health
+ );
+ float z = (M_PI / 5) * a;
+ float f = (x > 0)
+ ? (atan(z / x) / (M_PI / 2))
+ : (tan(-(x / z)) + 1);
+ return f;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_smneg, Damage_Calculate) {
+ float deathtype = M_ARGV(3, float);
+ Weapon w = DEATH_WEAPONOF(deathtype);
+ if (w == WEP_Null) return;
+
+ entity frag_attacker = M_ARGV(1, entity);
+ entity c = CS(frag_attacker);
+ float weight = c.x_smneg_weight[w.m_id];
+ float f = smneg_multiplier(weight);
+ float frag_damage = M_ARGV(4, float) = f * M_ARGV(4, float);
+ M_ARGV(6, vector) = f * M_ARGV(6, vector); // force
+
+ c.x_smneg_weight[w.m_id] = weight + frag_damage;
+ float restore = frag_damage * autocvar_g_smneg_cooldown_factor;
+ FOREACH(Weapons, it != WEP_Null && it != w, {
+ c.x_smneg_weight[it.m_id] -= restore;
+ });
+}
--- /dev/null
+#pragma once
STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate", autocvar_sv_airaccelerate);
STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate", autocvar_sv_airstopaccelerate);
STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity", autocvar_sv_jumpvelocity);
+ STAT(MOVEVARS_JUMPVELOCITY_CROUCH, this) = Physics_ClientOption(this, "jumpvelocity_crouch", autocvar_sv_jumpvelocity_crouch);
STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump", autocvar_sv_track_canjump);
}
#endif
#endif
bool doublejump = false;
- float mjumpheight = PHYS_JUMPVELOCITY(this);
+ float mjumpheight = ((PHYS_JUMPVELOCITY_CROUCH(this) && IS_DUCKED(this)) ? PHYS_JUMPVELOCITY_CROUCH(this) : PHYS_JUMPVELOCITY(this));
bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(s) STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
#define PHYS_JUMPVELOCITY(s) STAT(MOVEVARS_JUMPVELOCITY, s)
+#define PHYS_JUMPVELOCITY_CROUCH(s) STAT(MOVEVARS_JUMPVELOCITY_CROUCH, s)
#define PHYS_MAXAIRSPEED(s) STAT(MOVEVARS_MAXAIRSPEED, s)
#define PHYS_MAXAIRSTRAFESPEED(s) STAT(MOVEVARS_MAXAIRSTRAFESPEED, s)
bool autocvar_sv_dodging_frozen;
bool autocvar_sv_dodging_frozen_doubletap;
float autocvar_sv_dodging_height_threshold;
-float autocvar_sv_dodging_horiz_speed;
-float autocvar_sv_dodging_horiz_speed_frozen;
+float autocvar_sv_dodging_horiz_speed_min;
+float autocvar_sv_dodging_horiz_speed_max;
+float autocvar_sv_dodging_horiz_force_slowest;
+float autocvar_sv_dodging_horiz_force_fastest;
+float autocvar_sv_dodging_horiz_force_frozen;
float autocvar_sv_dodging_ramp_time;
float autocvar_sv_dodging_up_speed;
bool autocvar_sv_dodging_wall_dodging;
bool autocvar_sv_dodging_air_dodging;
-float autocvar_sv_dodging_maxspeed = 450;
+float autocvar_sv_dodging_maxspeed;
+float autocvar_sv_dodging_air_maxspeed;
#endif
#if 0
REGISTER_STAT(DODGING, int, g_dodging)
REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay)
REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold)
-REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
+REGISTER_STAT(DODGING_FROZEN_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold)
-REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed)
-REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen)
+REGISTER_STAT(DODGING_HORIZ_SPEED_MIN, float, autocvar_sv_dodging_horiz_speed_min)
+REGISTER_STAT(DODGING_HORIZ_SPEED_MAX, float, autocvar_sv_dodging_horiz_speed_max)
+REGISTER_STAT(DODGING_HORIZ_FORCE_SLOWEST, float, autocvar_sv_dodging_horiz_force_slowest)
+REGISTER_STAT(DODGING_HORIZ_FORCE_FASTEST, float, autocvar_sv_dodging_horiz_force_fastest)
+REGISTER_STAT(DODGING_HORIZ_FORCE_FROZEN, float, autocvar_sv_dodging_horiz_force_frozen)
REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time)
REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed)
REGISTER_STAT(DODGING_WALL, bool, autocvar_sv_dodging_wall_dodging)
REGISTER_STAT(DODGING_AIR, bool, autocvar_sv_dodging_air_dodging)
REGISTER_STAT(DODGING_MAXSPEED, float, autocvar_sv_dodging_maxspeed)
+REGISTER_STAT(DODGING_AIR_MAXSPEED, float, autocvar_sv_dodging_air_maxspeed)
#endif
/** cvar loopback */
REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
// FIXME: Was 0 on server, 1 on client. Still want that?
REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1)
REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float)
+REGISTER_STAT(MOVEVARS_JUMPVELOCITY_CROUCH, float)
REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float)
REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
if(this.spawnflags & DOOR_NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
- this.health = this.health - damage;
- if (this.health <= 0)
+ if (this.spawnflags & BUTTON_DONTACCUMULATEDMG)
{
- this.enemy = attacker;
- button_fire(this);
+ if (this.health <= damage)
+ {
+ this.enemy = attacker;
+ button_fire(this);
+ }
+ }
+ else
+ {
+ this.health = this.health - damage;
+ if (this.health <= 0)
+ {
+ this.enemy = attacker;
+ button_fire(this);
+ }
}
}
#pragma once
+
+const int BUTTON_DONTACCUMULATEDMG = 128;
if (!IS_DEAD(toucher))
if (toucher.triggerhealtime < time)
{
- EXACTTRIGGER_TOUCH(this, toucher);
+ bool is_trigger = !boolean(!this.nottargeted && this.targetname != "");
+ if(is_trigger)
+ EXACTTRIGGER_TOUCH(this, toucher);
toucher.triggerhealtime = time + 1;
if (toucher.health < this.max_health)
}
}
+void trigger_heal_use(entity this, entity actor, entity trigger)
+{
+ trigger_heal_touch(this, actor);
+}
+
spawnfunc(trigger_heal)
{
this.active = ACTIVE_ACTIVE;
this.noise = "misc/mediumhealth.wav";
precache_sound(this.noise);
}
+
+spawnfunc(target_heal)
+{
+ this.active = ACTIVE_ACTIVE;
+ this.use = trigger_heal_use;
+ if (!this.health)
+ this.health = 10;
+ if (!this.max_health)
+ this.max_health = 200; //Max health topoff for field
+ if(this.noise == "")
+ this.noise = "misc/mediumhealth.wav";
+ precache_sound(this.noise);
+}
#endif
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
- grav = PHYS_GRAVITY(other);
- if(PHYS_ENTGRAVITY(other))
- grav *= PHYS_ENTGRAVITY(other);
+ grav = PHYS_GRAVITY(tgt);
+ if(PHYS_ENTGRAVITY(tgt))
+ grav *= PHYS_ENTGRAVITY(tgt);
zdist = torg.z - org.z;
sdist = vlen(torg - org - zdist * '0 0 1');
break;
}
me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt);
+ setZonedTooltip(me.encryptLabel, _("Use the `crypto_aeslevel` cvar to change your preferences"), string_null);
s = crypto_getidfp(me.currentServerCName);
if (!s) { s = _("N/A"); }
float autocvar_sv_jumpspeedcap_max_disable_on_ramps;
string autocvar_sv_jumpspeedcap_min;
float autocvar_sv_jumpvelocity;
+float autocvar_sv_jumpvelocity_crouch;
bool autocvar_sv_logscores_bots;
bool autocvar_sv_logscores_console;
bool autocvar_sv_logscores_file;
.float clientkill_nexttime;
void ClientKill_Now_TeamChange(entity this)
{
- if(CS(this).killindicator_teamchange == -1)
+ if(this.killindicator_teamchange == -1)
{
JoinBestTeam( this, false, true );
}
- else if(CS(this).killindicator_teamchange == -2)
+ else if(this.killindicator_teamchange == -2)
{
if(blockSpectators)
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
PutObserverInServer(this);
}
else
- SV_ChangeTeam(this, CS(this).killindicator_teamchange - 1);
- CS(this).killindicator_teamchange = 0;
+ SV_ChangeTeam(this, this.killindicator_teamchange - 1);
+ this.killindicator_teamchange = 0;
}
void ClientKill_Now(entity this)
if(this.vehicle)
{
vehicles_exit(this.vehicle, VHEF_RELEASE);
- if(!CS(this).killindicator_teamchange)
+ if(!this.killindicator_teamchange)
{
this.vehicle_health = -1;
Damage(this, this, this, 1 , DEATH_KILL.m_id, this.origin, '0 0 0');
this.killindicator = NULL;
- if(CS(this).killindicator_teamchange)
+ if(this.killindicator_teamchange)
ClientKill_Now_TeamChange(this);
if (!IS_SPEC(this) && !IS_OBSERVER(this) && MUTATOR_CALLHOOK(ClientKill_Now, this) == false)
return;
killtime = M_ARGV(1, float);
- CS(this).killindicator_teamchange = targetteam;
+ this.killindicator_teamchange = targetteam;
if(!this.killindicator)
{
ATTRIB(Client, parm_idlesince, int, this.parm_idlesince);
ATTRIB(Client, muted, bool, this.muted);
- ATTRIB(Client, killindicator_teamchange, int, this.killindicator_teamchange);
ATTRIB(Client, idlekick_lasttimeleft, float, this.idlekick_lasttimeleft);
ATTRIB(Client, pm_frametime, float, this.pm_frametime);
ATTRIB(Client, pressedkeys, int, this.pressedkeys);
.float stat_respawn_time = _STAT(RESPAWN_TIME); // shows respawn time, and is negative when awaiting respawn
+.int killindicator_teamchange;
+
void PlayerUseKey(entity this);
USING(spawn_evalfunc_t, vector(entity this, entity player, entity spot, vector current));
{
// regular frag
GameRules_scoring_add(attacker, KILLS, 1);
- if(targ.playerid)
+ if(!warmup_stage && targ.playerid)
PlayerStats_GameReport_Event_Player(attacker, sprintf("kills-%d", targ.playerid), 1);
}
attacker.killsound += 1;
+ // TODO: improve SPREE_ITEM and KILL_SPREE_LIST
+ // these 2 macros are spread over multiple files
#define SPREE_ITEM(counta,countb,center,normal,gentle) \
case counta: \
{ \
Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
- PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ if (!warmup_stage)\
+ {\
+ PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ }\
break; \
}
switch(CS(attacker).killcount)
}
#undef SPREE_ITEM
- if(!checkrules_firstblood)
+ if(!warmup_stage && !checkrules_firstblood)
{
checkrules_firstblood = true;
notif_firstblood = true; // modify the current messages so that they too show firstblood information
if(GameRules_scoring_add(targ, SCORE, 0) == -5)
{
Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
- PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ if (!warmup_stage)
+ {
+ PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ }
}
}
/// this item is on the ground.
.bool m_isexpiring;
-entity Item_Create(string class_name, vector position)
+entity Item_Create(string class_name, vector position, bool no_align)
{
entity item = spawn();
item.classname = class_name;
item.spawnfunc_checked = true;
setorigin(item, position);
+ item.noalign = no_align;
Item_Initialize(item, class_name);
if (wasfreed(item))
{
/// \brief Creates a new item.
/// \param[in] class_name Class name of the item.
/// \param[in] position Position of the item.
+/// \param[in] no_align True if item should be placed directly at specified
+/// position, false to let it drop to the ground.
/// \return Item on success, NULL otherwise.
-entity Item_Create(string class_name, vector position);
+entity Item_Create(string class_name, vector position, bool no_align);
/// \brief Initializes the item according to classname.
/// \param[in,out] item Item to initialize.
ca_LastPlayerForTeam_Notify(frag_target);
if (!allowed_to_spawn)
- frag_target.respawn_flags = RESPAWN_SILENT;
+ {
+ frag_target.respawn_flags = RESPAWN_SILENT;
+ // prevent unwanted sudden rejoin as spectator and move of spectator camera
+ frag_target.respawn_time = time + 2;
+ }
if (!warmup_stage)
eliminatedPlayers.SendFlags |= 1;
if(IS_BOT_CLIENT(frag_target))
if (!IS_DEAD(player))
ca_LastPlayerForTeam_Notify(player);
- if (CS(player).killindicator_teamchange == -2) // player wants to spectate
+ if (player.killindicator_teamchange == -2) // player wants to spectate
player.caplayer = 0;
if (player.caplayer)
player.frags = FRAGS_LMS_LOSER;
{
delete(this.killindicator);
this.killindicator = NULL;
- if(CS(this).killindicator_teamchange)
+ if(this.killindicator_teamchange)
defer_ClientKill_Now_TeamChange = true;
if(this.classname == "body")
if(w != WEP_Null && accuracy_isgooddamage(attacker, this))
CS(attacker).accuracy.(accuracy_frags[w.m_id-1]) += 1;
+ this.respawn_time = 0;
MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, damage);
damage = M_ARGV(4, float);
excess = max(0, damage - take - save);
if(this.health >= 1 || !(IS_PLAYER(this) || this.classname == "body"))
return;
+ if (!this.respawn_time) // can be set in the mutator hook PlayerDies
+ calculate_player_respawn_time(this);
+
// when we get here, player actually dies
Unfreeze(this); // remove any icy remains
STAT(MOVEVARS_SPECIALCOMMAND, this) = false; // sweet release
- // when to allow respawn
- calculate_player_respawn_time(this);
-
this.death_time = time;
if (random() < 0.5)
animdecide_setstate(this, this.anim_state | ANIMSTATE_DEAD1, true);
source_team = Team_TeamToNumber(source_color + 1);
destination_team = Team_TeamToNumber(destination_color + 1);
+ if (destination_team == -1)
+ {
+ return;
+ }
+
CheckAllowedTeams(this);
if (destination_team == 1 && c1 < 0) destination_team = 4;
--- /dev/null
+// Random items mutator config
+
+// Map items
+
+set g_random_items_replace_item_health_small "random" "Classnames to replace small health with."
+set g_random_items_replace_item_health_medium "random" "Classnames to replace medium health with."
+set g_random_items_replace_item_health_big "random" "Classnames to replace big health with."
+set g_random_items_replace_item_health_mega "random" "Classnames to replace mega health with."
+set g_random_items_replace_item_armor_small "random" "Classnames to replace small armor with."
+set g_random_items_replace_item_armor_medium "random" "Classnames to replace medium armor with."
+set g_random_items_replace_item_armor_big "random" "Classnames to replace big armor with."
+set g_random_items_replace_item_armor_mega "random" "Classnames to replace mega armor with."
+set g_random_items_replace_item_shells "random" "Classnames to replace shells with."
+set g_random_items_replace_item_bullets "random" "Classnames to replace bullets with."
+set g_random_items_replace_item_rockets "random" "Classnames to replace rockets with."
+set g_random_items_replace_item_cells "random" "Classnames to replace cells with."
+set g_random_items_replace_item_plasma "random" "Classnames to replace plasma with."
+set g_random_items_replace_item_fuel "random" "Classnames to replace fuel with."
+set g_random_items_replace_weapon_blaster "random" "Classnames to replace blaster with."
+set g_random_items_replace_weapon_shotgun "random" "Classnames to replace shotgun with."
+set g_random_items_replace_weapon_machinegun "random" "Classnames to replace machinegun with."
+set g_random_items_replace_weapon_mortar "random" "Classnames to replace mortar with."
+set g_random_items_replace_weapon_electro "random" "Classnames to replace electro with."
+set g_random_items_replace_weapon_crylink "random" "Classnames to replace crylink with."
+set g_random_items_replace_weapon_vortex "random" "Classnames to replace vortex with."
+set g_random_items_replace_weapon_hagar "random" "Classnames to replace hagar with."
+set g_random_items_replace_weapon_devastator "random" "Classnames to replace devastator with."
+set g_random_items_replace_weapon_shockwave "random" "Classnames to replace shockwave with."
+set g_random_items_replace_weapon_arc "random" "Classnames to replace arc with."
+set g_random_items_replace_weapon_hook "random" "Classnames to replace hook with."
+set g_random_items_replace_weapon_tuba "random" "Classnames to replace tuba with."
+set g_random_items_replace_weapon_porto "random" "Classnames to replace port-o-launch with."
+set g_random_items_replace_weapon_fireball "random" "Classnames to replace fireball with."
+set g_random_items_replace_weapon_minelayer "random" "Classnames to replace mine layer with."
+set g_random_items_replace_weapon_hlac "random" "Classnames to replace HLAC with."
+set g_random_items_replace_weapon_rifle "random" "Classnames to replace rifle with."
+set g_random_items_replace_weapon_seeker "random" "Classnames to replace TAG seeker with."
+set g_random_items_replace_weapon_vaporizer "random" "Classnames to replace vaporizer with."
+set g_random_items_replace_weapon_hmg "random" "Classnames to replace HMG with."
+set g_random_items_replace_weapon_rpc "random" "Classnames to replace RPC with."
+set g_random_items_replace_item_strength "random" "Classnames to replace strength with."
+set g_random_items_replace_item_shield "random" "Classnames to replace shield with."
+set g_random_items_replace_item_fuel_regen "random" "Classnames to replace fuel regeneration with."
+set g_random_items_replace_item_jetpack "random" "Classnames to replace jetpack with."
+set g_random_items_replace_item_vaporizer_cells "random" "Classnames to replace vaporizer cells with."
+set g_random_items_replace_item_invisibility "random" "Classnames to replace invisibility with."
+set g_random_items_replace_item_extralife "random" "Classnames to replace extra life with."
+set g_random_items_replace_item_speed "random" "Classnames to replace speed with."
+set g_random_items_health_probability 1 "Probability of random health items spawning in the map."
+set g_random_items_armor_probability 1 "Probability of random armor items spawning in the map."
+set g_random_items_resource_probability 1 "Probability of random resource items spawning in the map."
+set g_random_items_weapon_probability 1 "Probability of random weapons spawning in the map."
+set g_random_items_powerup_probability 0.15 "Probability of random powerups spawning in the map."
+set g_random_items_item_health_small_probability 10 "Probability of random small health spawning in the map."
+set g_random_items_item_health_medium_probability 4 "Probability of random medium health spawning in the map."
+set g_random_items_item_health_big_probability 2 "Probability of random big health spawning in the map."
+set g_random_items_item_health_mega_probability 1 "Probability of random mega health spawning in the map."
+set g_random_items_item_armor_small_probability 10 "Probability of random small armor spawning in the map."
+set g_random_items_item_armor_medium_probability 4 "Probability of random medium armor spawning in the map."
+set g_random_items_item_armor_big_probability 2 "Probability of random big armor spawning in the map."
+set g_random_items_item_armor_mega_probability 1 "Probability of random mega armor spawning in the map."
+set g_random_items_item_shells_probability 1 "Probability of random shells spawning in the map."
+set g_random_items_item_bullets_probability 1 "Probability of random bullets spawning in the map."
+set g_random_items_item_rockets_probability 1 "Probability of random rockets spawning in the map."
+set g_random_items_item_cells_probability 1 "Probability of random cells spawning in the map."
+set g_random_items_item_plasma_probability 0 "Probability of random plasma spawning in the map."
+set g_random_items_item_fuel_probability 0 "Probability of random fuel spawning in the map."
+set g_random_items_weapon_blaster_probability 0 "Probability of random blaster spawning in the map."
+set g_random_items_weapon_shotgun_probability 0 "Probability of random shotgun spawning in the map."
+set g_random_items_weapon_machinegun_probability 1 "Probability of random machinegun spawning in the map."
+set g_random_items_weapon_mortar_probability 1 "Probability of random mortar spawning in the map."
+set g_random_items_weapon_electro_probability 1 "Probability of random electro spawning in the map."
+set g_random_items_weapon_crylink_probability 1 "Probability of random crylink spawning in the map."
+set g_random_items_weapon_vortex_probability 1 "Probability of random vortex spawning in the map."
+set g_random_items_weapon_hagar_probability 1 "Probability of random hagar spawning in the map."
+set g_random_items_weapon_devastator_probability 1 "Probability of random devastator spawning in the map."
+set g_random_items_weapon_shockwave_probability 0 "Probability of random shockwave spawning in the map."
+set g_random_items_weapon_arc_probability 0 "Probability of random arc spawning in the map."
+set g_random_items_weapon_hook_probability 0 "Probability of random hook spawning in the map."
+set g_random_items_weapon_tuba_probability 0 "Probability of random tuba spawning in the map."
+set g_random_items_weapon_porto_probability 0 "Probability of random port-o-launch spawning in the map."
+set g_random_items_weapon_fireball_probability 0 "Probability of random fireball spawning in the map."
+set g_random_items_weapon_minelayer_probability 0 "Probability of random mine layer spawning in the map."
+set g_random_items_weapon_hlac_probability 0 "Probability of random HLAC spawning in the map."
+set g_random_items_weapon_rifle_probability 0 "Probability of random rifle spawning in the map."
+set g_random_items_weapon_seeker_probability 0 "Probability of random TAG seeker spawning in the map."
+set g_random_items_weapon_vaporizer_probability 0 "Probability of random vaporizer spawning in the map."
+set g_random_items_item_strength_probability 1 "Probability of random strength spawning in the map."
+set g_random_items_item_shield_probability 1 "Probability of random shield spawning in the map."
+set g_random_items_item_fuel_regen_probability 0 "Probability of random fuel regeneration spawning in the map."
+set g_random_items_item_jetpack_probability 0 "Probability of random jetpack spawning in the map."
+set g_random_items_item_vaporizer_cells_probability 20 "Probability of random vaporizer cells spawning in the map."
+set g_random_items_item_invisibility_probability 1 "Probability of random invisibility spawning in the map."
+set g_random_items_item_extralife_probability 1 "Probability of random extra life spawning in the map."
+set g_random_items_item_speed_probability 1 "Probability of random speed spawning in the map."
+set g_random_items_overkill_item_health_mega_probability 1 "Probability of random mega health spawning in the map during overkill."
+set g_random_items_overkill_item_armor_small_probability 10 "Probability of random small armor spawning in the map during overkill."
+set g_random_items_overkill_item_armor_medium_probability 4 "Probability of random medium armor spawning in the map during overkill."
+set g_random_items_overkill_item_armor_big_probability 2 "Probability of random big armor spawning in the map during overkill."
+set g_random_items_overkill_item_armor_mega_probability 1 "Probability of random mega armor spawning in the map during overkill."
+set g_random_items_overkill_weapon_hmg_probability 0.5 "Probability of random HMG spawning in the map during overkill."
+set g_random_items_overkill_weapon_rpc_probability 0.5 "Probability of random RPC spawning in the map during overkill."
+
+// Loot
+
+set g_random_loot_min 0 "Minimum amount of loot items."
+set g_random_loot_max 4 "Maximum amount of loot items."
+set g_random_loot_time 10 "Amount of time the loot will stay in seconds."
+set g_random_loot_spread 200 "How far can loot be thrown."
+set g_random_loot_health_probability 1 "Probability of random health items spawning as loot."
+set g_random_loot_armor_probability 1 "Probability of random armor items spawning as loot."
+set g_random_loot_resource_probability 1 "Probability of random ammo items spawning as loot."
+set g_random_loot_weapon_probability 1 "Probability of random weapons spawning as loot."
+set g_random_loot_powerup_probability 0.2 "Probability of random powerups spawning as loot."
+set g_random_loot_item_health_small_probability 4 "Probability of random small health spawning as loot."
+set g_random_loot_item_health_medium_probability 3 "Probability of random medium health spawning as loot."
+set g_random_loot_item_health_big_probability 2 "Probability of random big health spawning as loot."
+set g_random_loot_item_health_mega_probability 1 "Probability of random mega health spawning as loot."
+set g_random_loot_item_armor_small_probability 4 "Probability of random small armor spawning as loot."
+set g_random_loot_item_armor_medium_probability 3 "Probability of random medium armor spawning as loot."
+set g_random_loot_item_armor_big_probability 2 "Probability of random big armor spawning as loot."
+set g_random_loot_item_armor_mega_probability 1 "Probability of random mega armor spawning as loot."
+set g_random_loot_item_shells_probability 1 "Probability of random shells spawning as loot."
+set g_random_loot_item_bullets_probability 1 "Probability of random bullets spawning as loot."
+set g_random_loot_item_rockets_probability 1 "Probability of random rockets spawning as loot."
+set g_random_loot_item_cells_probability 1 "Probability of random cells spawning as loot."
+set g_random_loot_item_plasma_probability 0 "Probability of random plasma spawning as loot."
+set g_random_loot_item_fuel_probability 0 "Probability of random fuel spawning as loot."
+set g_random_loot_weapon_blaster_probability 0 "Probability of random blaster spawning as loot."
+set g_random_loot_weapon_shotgun_probability 0 "Probability of random shotgun spawning as loot."
+set g_random_loot_weapon_machinegun_probability 1 "Probability of random machinegun spawning as loot."
+set g_random_loot_weapon_mortar_probability 1 "Probability of random mortar spawning as loot."
+set g_random_loot_weapon_electro_probability 1 "Probability of random electro spawning as loot."
+set g_random_loot_weapon_crylink_probability 1 "Probability of random crylink spawning as loot."
+set g_random_loot_weapon_vortex_probability 1 "Probability of random vortex spawning as loot."
+set g_random_loot_weapon_hagar_probability 1 "Probability of random hagar spawning as loot."
+set g_random_loot_weapon_devastator_probability 1 "Probability of random devastator spawning as loot."
+set g_random_loot_weapon_shockwave_probability 0 "Probability of random shockwave spawning as loot."
+set g_random_loot_weapon_arc_probability 0 "Probability of random arc spawning as loot."
+set g_random_loot_weapon_hook_probability 0 "Probability of random hook spawning as loot."
+set g_random_loot_weapon_tuba_probability 0 "Probability of random tuba spawning as loot."
+set g_random_loot_weapon_porto_probability 0 "Probability of random port-o-launch spawning as loot."
+set g_random_loot_weapon_fireball_probability 0 "Probability of random fireball spawning as loot."
+set g_random_loot_weapon_minelayer_probability 0 "Probability of random mine layer spawning as loot."
+set g_random_loot_weapon_hlac_probability 0 "Probability of random HLAC spawning as loot."
+set g_random_loot_weapon_rifle_probability 0 "Probability of random rifle spawning as loot."
+set g_random_loot_weapon_seeker_probability 0 "Probability of random TAG seeker spawning as loot."
+set g_random_loot_weapon_vaporizer_probability 0 "Probability of random vaporizer spawning as loot."
+set g_random_loot_item_strength_probability 1 "Probability of random strength spawning as loot."
+set g_random_loot_item_shield_probability 1 "Probability of random shield spawning as loot."
+set g_random_loot_item_fuel_regen_probability 0 "Probability of random fuel regeneration spawning as loot."
+set g_random_loot_item_jetpack_probability 0 "Probability of random jetpack spawning as loot."
+set g_random_loot_item_vaporizer_cells_probability 20 "Probability of random vaporizer cells spawning as loot."
+set g_random_loot_item_invisibility_probability 1 "Probability of random invisibility spawning as loot."
+set g_random_loot_item_extralife_probability 1 "Probability of random extra life spawning as loot."
+set g_random_loot_item_speed_probability 1 "Probability of random speed spawning as loot."
+set g_random_loot_overkill_item_health_mega_probability 1 "Probability of random mega health spawning as loot during overkill."
+set g_random_loot_overkill_item_armor_small_probability 10 "Probability of random small armor spawning as loot during overkill."
+set g_random_loot_overkill_item_armor_medium_probability 4 "Probability of random medium armor spawning as loot during overkill."
+set g_random_loot_overkill_item_armor_big_probability 2 "Probability of random big armor spawning as loot during overkill."
+set g_random_loot_overkill_item_armor_mega_probability 1 "Probability of random mega armor spawning as loot during overkill."
+set g_random_loot_overkill_weapon_hmg_probability 1 "Probability of random HMG spawning as loot during overkill."
+set g_random_loot_overkill_weapon_rpc_probability 1 "Probability of random RPC spawning as loot during overkill."