]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'martin-t/server-quit' into 'master'
authorMario <mario.mario@y7mail.com>
Sat, 23 May 2020 11:25:34 +0000 (11:25 +0000)
committerMario <mario.mario@y7mail.com>
Sat, 23 May 2020 11:25:34 +0000 (11:25 +0000)
Make dedicated server quit when no config found

See merge request xonotic/xonotic-data.pk3dir!788

134 files changed:
.gitlab-ci.yml
.tx/merge-base
_hud_descriptions.cfg
bal-wep-testing.cfg [deleted file]
balance-mario.cfg
balance-nexuiz25.cfg
balance-overkill.cfg
balance-samual.cfg
balance-testing.cfg
balance-testingxpm.cfg
balance-xdf.cfg
balance-xonotic.cfg
balance-xpm.cfg
check-cvars.sh
commands.cfg
common.ast.po
common.fi.po
common.pl.po
effectinfo.txt
hud_luma.cfg
hud_luminos.cfg
hud_luminos_minimal.cfg
hud_luminos_minimal_xhair.cfg
hud_luminos_old.cfg
hud_nexuiz.cfg
languages.txt
mutators.cfg
physics.cfg
qcsrc/client/autocvars.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud/hud_config.qc
qcsrc/client/hud/panel/centerprint.qc
qcsrc/client/hud/panel/quickmenu.qc
qcsrc/client/hud/panel/racetimer.qc
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/main.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/shownames.qc
qcsrc/common/effects/effectinfo.inc
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc
qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc
qcsrc/common/items/item.qh
qcsrc/common/mapinfo.qc
qcsrc/common/mapobjects/trigger/counter.qc
qcsrc/common/mapobjects/trigger/counter.qh
qcsrc/common/mapobjects/trigger/disablerelay.qc
qcsrc/common/mapobjects/trigger/relay_if.qc
qcsrc/common/mapobjects/trigger/relay_teamcheck.qc
qcsrc/common/mapobjects/trigger/swamp.qc
qcsrc/common/mapobjects/trigger/swamp.qh
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc
qcsrc/common/mutators/mutator/buffs/all.inc
qcsrc/common/mutators/mutator/buffs/cl_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qh
qcsrc/common/mutators/mutator/dodging/cl_dodging.qh
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/multijump/multijump.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/okhmg.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/superspec/sv_superspec.qc
qcsrc/common/notifications/all.inc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/player.qc
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/dpextensions.qh
qcsrc/dpdefs/post.qh
qcsrc/dpdefs/progsdefs.qh
qcsrc/ecs/systems/physics.qc
qcsrc/lib/_all.inc
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/cvar.qh
qcsrc/lib/deglobalization.qh
qcsrc/lib/i18n.qh
qcsrc/lib/intrusivelist.qh
qcsrc/lib/map.qh
qcsrc/lib/matrix/matrix.qc
qcsrc/lib/vector.qh
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/maplist.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/serverlist.qh
qcsrc/menu/xonotic/util.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/bot.qh
qcsrc/server/bot/default/cvars.qh
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/havocbot/havocbot.qh
qcsrc/server/bot/default/havocbot/roles.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/navigation.qh
qcsrc/server/bot/default/scripting.qc
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/default/waypoints.qh
qcsrc/server/campaign.qc
qcsrc/server/cheats.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/command/sv_cmd.qc
qcsrc/server/compat/quake3.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/player.qc
qcsrc/server/scores.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/sv_main.qc
qcsrc/server/weapons/throwing.qc
sound/weapons/hagar_fire.ogg
sound/weapons/rocket_fire.ogg
testing.cfg [new file with mode: 0644]
textures/gib2_gloss.tga [new file with mode: 0644]
textures/gib2_spec.tga [deleted file]
textures/gib3_gloss.tga [new file with mode: 0644]
textures/gib3_spec.tga [deleted file]
textures/gib4_gloss.tga [new file with mode: 0644]
textures/gib4_spec.tga [deleted file]
textures/hagar_gloss.tga [new file with mode: 0644]
textures/hagar_spec.tga [deleted file]
xonotic-client.cfg
xonotic-common.cfg
xonotic-server.cfg

index 15ea0ec5399f86916f9f8545ec80a42087866aea..40d5b0b4072e8ea4a690f6060d9cf528c703ca5c 100644 (file)
@@ -29,7 +29,7 @@ test_sv_game:
     - wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
     - wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
     - make
-    - EXPECT=6535600492e1cb63af8e449570bffe4a
+    - EXPECT=62fd4d2a4124374b7e0cc1aff445cd88
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 6b9bef88e8973e712d8c855c7bfa7228018d7e95..76b17ee0d96cbfc3d0e9f6020d21617e2e0f24b3 100644 (file)
@@ -1 +1 @@
-Sun Mar 29 07:24:37 CEST 2020
+Wed May 13 07:23:38 CEST 2020
index 9bb1b84a620f61cc2672d4d85a52817d384b21a1..3f0355b5fd79cae5ecf2db48b96a386d38e4a36d 100644 (file)
@@ -275,6 +275,7 @@ seta hud_panel_centerprint_bg_padding "" "if set to something else than \"\" = o
 seta hud_panel_centerprint_align "" "text alignment: 0 left, 0.5 center, 1 right"
 seta hud_panel_centerprint_flip "" "invert messages order"
 seta hud_panel_centerprint_fontscale "" "scale the text font by this amount"
+seta hud_panel_centerprint_fontscale_bold "" "scale the bold text font by this amount"
 seta hud_panel_centerprint_time "" "message duration (NOTE: certain messages have a fixed duration)"
 seta hud_panel_centerprint_fade_in "" "how long a message takes to fade in"
 seta hud_panel_centerprint_fade_out "" "how long a message takes to fade out (this time is included in the message duration and can't be > 5)"
diff --git a/bal-wep-testing.cfg b/bal-wep-testing.cfg
deleted file mode 100644 (file)
index abee0b6..0000000
+++ /dev/null
@@ -1,974 +0,0 @@
-// {{{ #1: Blaster
-set g_balance_blaster_primary_animtime 0.1
-set g_balance_blaster_primary_damage 20
-set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 10
-set g_balance_blaster_primary_force 375
-set g_balance_blaster_primary_force_zscale 1
-set g_balance_blaster_primary_lifetime 5
-set g_balance_blaster_primary_radius 60
-set g_balance_blaster_primary_refire 0.7
-set g_balance_blaster_primary_shotangle 0
-set g_balance_blaster_primary_speed 6000
-set g_balance_blaster_primary_spread 0
-set g_balance_blaster_secondary 0
-set g_balance_blaster_secondary_animtime 0.2
-set g_balance_blaster_secondary_damage 25
-set g_balance_blaster_secondary_delay 0
-set g_balance_blaster_secondary_edgedamage 12.5
-set g_balance_blaster_secondary_force 360
-set g_balance_blaster_secondary_force_zscale 1
-set g_balance_blaster_secondary_lifetime 5
-set g_balance_blaster_secondary_radius 70
-set g_balance_blaster_secondary_refire 0.7
-set g_balance_blaster_secondary_shotangle 0
-set g_balance_blaster_secondary_speed 6000
-set g_balance_blaster_secondary_spread 0
-set g_balance_blaster_switchdelay_drop 0.1
-set g_balance_blaster_switchdelay_raise 0.1
-set g_balance_blaster_weaponreplace ""
-set g_balance_blaster_weaponstart 1
-set g_balance_blaster_weaponstartoverride -1
-set g_balance_blaster_weaponthrowable 0
-// }}}
-// {{{ #2: Shotgun
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 12
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_reload_ammo 0
-set g_balance_shotgun_reload_time 2
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
-set g_balance_shotgun_secondary_animtime 1.15
-set g_balance_shotgun_secondary_damage 70
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_melee_delay 0.25
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_weaponreplace ""
-set g_balance_shotgun_weaponstart 1
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
-// }}}
-// {{{ #3: MachineGun
-set g_balance_machinegun_burst 3
-set g_balance_machinegun_burst_ammo 3
-set g_balance_machinegun_burst_animtime 0.3
-set g_balance_machinegun_burst_refire 0.06
-set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_spread 0
-set g_balance_machinegun_first 1
-set g_balance_machinegun_first_ammo 1
-set g_balance_machinegun_first_damage 14
-set g_balance_machinegun_first_force 3
-set g_balance_machinegun_first_refire 0.125
-set g_balance_machinegun_first_spread 0.03
-set g_balance_machinegun_mode 1
-set g_balance_machinegun_reload_ammo 60
-set g_balance_machinegun_reload_time 2
-set g_balance_machinegun_solidpenetration 13.1
-set g_balance_machinegun_spread_add 0.012
-set g_balance_machinegun_spread_max 0.05
-set g_balance_machinegun_spread_min 0.02
-set g_balance_machinegun_sustained_ammo 1
-set g_balance_machinegun_sustained_damage 10
-set g_balance_machinegun_sustained_force 3
-set g_balance_machinegun_sustained_refire 0.1
-set g_balance_machinegun_sustained_spread 0.03
-set g_balance_machinegun_switchdelay_drop 0.2
-set g_balance_machinegun_switchdelay_raise 0.2
-set g_balance_machinegun_weaponreplace ""
-set g_balance_machinegun_weaponstart 0
-set g_balance_machinegun_weaponstartoverride -1
-set g_balance_machinegun_weaponthrowable 1
-// }}}
-// {{{ #4: Mortar
-set g_balance_mortar_bouncefactor 0.5
-set g_balance_mortar_bouncestop 0.075
-set g_balance_mortar_primary_ammo 2
-set g_balance_mortar_primary_animtime 0.3
-set g_balance_mortar_primary_damage 55
-set g_balance_mortar_primary_damageforcescale 0
-set g_balance_mortar_primary_edgedamage 25
-set g_balance_mortar_primary_force 250
-set g_balance_mortar_primary_health 15
-set g_balance_mortar_primary_lifetime 5
-set g_balance_mortar_primary_lifetime_stick 0
-set g_balance_mortar_primary_radius 120
-set g_balance_mortar_primary_refire 0.8
-set g_balance_mortar_primary_remote_minbouncecnt 0
-set g_balance_mortar_primary_speed 1900
-set g_balance_mortar_primary_speed_up 225
-set g_balance_mortar_primary_speed_z 0
-set g_balance_mortar_primary_spread 0
-set g_balance_mortar_primary_type 0
-set g_balance_mortar_reload_ammo 0
-set g_balance_mortar_reload_time 2
-set g_balance_mortar_secondary_ammo 2
-set g_balance_mortar_secondary_animtime 0.3
-set g_balance_mortar_secondary_damage 55
-set g_balance_mortar_secondary_damageforcescale 4
-set g_balance_mortar_secondary_edgedamage 30
-set g_balance_mortar_secondary_force 250
-set g_balance_mortar_secondary_health 30
-set g_balance_mortar_secondary_lifetime 5
-set g_balance_mortar_secondary_lifetime_bounce 0.5
-set g_balance_mortar_secondary_lifetime_stick 0
-set g_balance_mortar_secondary_radius 120
-set g_balance_mortar_secondary_refire 0.7
-set g_balance_mortar_secondary_remote_detonateprimary 0
-set g_balance_mortar_secondary_speed 1400
-set g_balance_mortar_secondary_speed_up 150
-set g_balance_mortar_secondary_speed_z 0
-set g_balance_mortar_secondary_spread 0
-set g_balance_mortar_secondary_type 1
-set g_balance_mortar_switchdelay_drop 0.2
-set g_balance_mortar_switchdelay_raise 0.2
-set g_balance_mortar_weaponreplace ""
-set g_balance_mortar_weaponstart 0
-set g_balance_mortar_weaponstartoverride -1
-set g_balance_mortar_weaponthrowable 1
-// }}}
-// {{{ #5: Mine Layer (MUTATOR WEAPON)
-set g_balance_minelayer_ammo 4
-set g_balance_minelayer_animtime 0.4
-set g_balance_minelayer_damage 40
-set g_balance_minelayer_damageforcescale 0
-set g_balance_minelayer_detonatedelay -1
-set g_balance_minelayer_edgedamage 20
-set g_balance_minelayer_force 250
-set g_balance_minelayer_health 15
-set g_balance_minelayer_lifetime 10
-set g_balance_minelayer_lifetime_countdown 0.5
-set g_balance_minelayer_limit 3
-set g_balance_minelayer_protection 0
-set g_balance_minelayer_proximityradius 150
-set g_balance_minelayer_radius 175
-set g_balance_minelayer_refire 1.5
-set g_balance_minelayer_reload_ammo 0
-set g_balance_minelayer_reload_time 2
-set g_balance_minelayer_remote_damage 45
-set g_balance_minelayer_remote_edgedamage 40
-set g_balance_minelayer_remote_force 300
-set g_balance_minelayer_remote_radius 200
-set g_balance_minelayer_speed 1000
-set g_balance_minelayer_switchdelay_drop 0.2
-set g_balance_minelayer_switchdelay_raise 0.2
-set g_balance_minelayer_time 0.5
-set g_balance_minelayer_weaponreplace ""
-set g_balance_minelayer_weaponstart 0
-set g_balance_minelayer_weaponstartoverride -1
-set g_balance_minelayer_weaponthrowable 1
-// }}}
-// {{{ #6: Electro
-set g_balance_electro_combo_comboradius 300
-set g_balance_electro_combo_comboradius_thruwall 200
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 25
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 150
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_comboradius 300
-set g_balance_electro_primary_damage 40
-set g_balance_electro_primary_edgedamage 20
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_midaircombo_enemy 1
-set g_balance_electro_primary_midaircombo_explode 1
-set g_balance_electro_primary_midaircombo_interval 0.1
-set g_balance_electro_primary_midaircombo_own 1
-set g_balance_electro_primary_midaircombo_radius 0
-set g_balance_electro_primary_midaircombo_speed 2000
-set g_balance_electro_primary_midaircombo_teammate 1
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_reload_ammo 0
-set g_balance_electro_reload_time 2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_bouncefactor 0.3
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_damage 30
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_edgedamage 15
-set g_balance_electro_secondary_force 50
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_lifetime 4
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.6
-set g_balance_electro_secondary_speed 1000
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0
-set g_balance_electro_secondary_stick 0
-set g_balance_electro_secondary_touchexplode 1
-set g_balance_electro_switchdelay_drop 0.2
-set g_balance_electro_switchdelay_raise 0.2
-set g_balance_electro_weaponreplace ""
-set g_balance_electro_weaponstart 0
-set g_balance_electro_weaponstartoverride -1
-set g_balance_electro_weaponthrowable 1
-// }}}
-// {{{ #7: Crylink
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_damage 10
-set g_balance_crylink_primary_edgedamage 5
-set g_balance_crylink_primary_force -50
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_linkexplode 1
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_middle_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_reload_ammo 0
-set g_balance_crylink_reload_time 2
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 3
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_damage 8
-set g_balance_crylink_secondary_edgedamage 4
-set g_balance_crylink_secondary_force -200
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_linkexplode 0
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_middle_lifetime 5
-set g_balance_crylink_secondary_other_fadetime 2
-set g_balance_crylink_secondary_other_lifetime 2
-set g_balance_crylink_secondary_radius 100
-set g_balance_crylink_secondary_refire 0.7
-set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_speed 4000
-set g_balance_crylink_secondary_spread 0.08
-set g_balance_crylink_secondary_spreadtype 0
-set g_balance_crylink_switchdelay_drop 0.2
-set g_balance_crylink_switchdelay_raise 0.2
-set g_balance_crylink_weaponreplace ""
-set g_balance_crylink_weaponstart 0
-set g_balance_crylink_weaponstartoverride -1
-set g_balance_crylink_weaponthrowable 1
-// }}}
-// {{{ #8: Vortex
-set g_balance_vortex_charge 1
-set g_balance_vortex_charge_always 0
-set g_balance_vortex_charge_animlimit 0.5
-set g_balance_vortex_charge_limit 1
-set g_balance_vortex_charge_maxspeed 800
-set g_balance_vortex_charge_mindmg 40
-set g_balance_vortex_charge_minspeed 400
-set g_balance_vortex_charge_rate 0.6
-set g_balance_vortex_charge_rot_pause 0
-set g_balance_vortex_charge_rot_rate 0
-set g_balance_vortex_charge_shot_multiplier 0
-set g_balance_vortex_charge_start 0.5
-set g_balance_vortex_charge_velocity_rate 0
-set g_balance_vortex_primary_ammo 6
-set g_balance_vortex_primary_animtime 0.4
-set g_balance_vortex_primary_armorpierce 0
-set g_balance_vortex_primary_damage 80
-set g_balance_vortex_primary_damagefalloff_forcehalflife 0
-set g_balance_vortex_primary_damagefalloff_halflife 0
-set g_balance_vortex_primary_damagefalloff_maxdist 0
-set g_balance_vortex_primary_damagefalloff_mindist 0
-set g_balance_vortex_primary_force 400
-set g_balance_vortex_primary_refire 1.5
-set g_balance_vortex_reload_ammo 0
-set g_balance_vortex_reload_time 2
-set g_balance_vortex_secondary 0
-set g_balance_vortex_secondary_ammo 2
-set g_balance_vortex_secondary_animtime 0
-set g_balance_vortex_secondary_armorpierce 0
-set g_balance_vortex_secondary_chargepool 0
-set g_balance_vortex_secondary_chargepool_pause_regen 1
-set g_balance_vortex_secondary_chargepool_regen 0.15
-set g_balance_vortex_secondary_damage 0
-set g_balance_vortex_secondary_damagefalloff_forcehalflife 0
-set g_balance_vortex_secondary_damagefalloff_halflife 0
-set g_balance_vortex_secondary_damagefalloff_maxdist 0
-set g_balance_vortex_secondary_damagefalloff_mindist 0
-set g_balance_vortex_secondary_force 0
-set g_balance_vortex_secondary_refire 0
-set g_balance_vortex_switchdelay_drop 0.2
-set g_balance_vortex_switchdelay_raise 0.2
-set g_balance_vortex_weaponreplace ""
-set g_balance_vortex_weaponstart 0
-set g_balance_vortex_weaponstartoverride -1
-set g_balance_vortex_weaponthrowable 1
-// }}}
-// {{{ #9: Hagar
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_refire 0.16667
-set g_balance_hagar_primary_speed 2200
-set g_balance_hagar_primary_spread 0
-set g_balance_hagar_reload_ammo 0
-set g_balance_hagar_reload_time 2
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_secondary_damage 35
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_edgedamage 17.5
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_abort 1
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_speed 2000
-set g_balance_hagar_secondary_spread 0
-set g_balance_hagar_switchdelay_drop 0.2
-set g_balance_hagar_switchdelay_raise 0.2
-set g_balance_hagar_weaponreplace ""
-set g_balance_hagar_weaponstart 0
-set g_balance_hagar_weaponstartoverride -1
-set g_balance_hagar_weaponthrowable 1
-// }}}
-// {{{ #10: Devastator
-set g_balance_devastator_ammo 4
-set g_balance_devastator_animtime 0.4
-set g_balance_devastator_damage 80
-set g_balance_devastator_damageforcescale 1
-set g_balance_devastator_detonatedelay 0.02
-set g_balance_devastator_edgedamage 40
-set g_balance_devastator_force 400
-set g_balance_devastator_guidedelay 0.2
-set g_balance_devastator_guidegoal 512
-set g_balance_devastator_guiderate 90
-set g_balance_devastator_guideratedelay 0.01
-set g_balance_devastator_guidestop 0
-set g_balance_devastator_health 30
-set g_balance_devastator_lifetime 10
-set g_balance_devastator_radius 110
-set g_balance_devastator_refire 1.1
-set g_balance_devastator_reload_ammo 0
-set g_balance_devastator_reload_time 2
-set g_balance_devastator_remote_damage 70
-set g_balance_devastator_remote_edgedamage 35
-set g_balance_devastator_remote_force 300
-set g_balance_devastator_remote_jump 1
-set g_balance_devastator_remote_jump_damage 70
-set g_balance_devastator_remote_jump_force 450
-set g_balance_devastator_remote_jump_radius 100
-set g_balance_devastator_remote_jump_velocity_z_add 0
-set g_balance_devastator_remote_jump_velocity_z_max 1500
-set g_balance_devastator_remote_jump_velocity_z_min 400
-set g_balance_devastator_remote_radius 110
-set g_balance_devastator_speed 1300
-set g_balance_devastator_speedaccel 1300
-set g_balance_devastator_speedstart 1000
-set g_balance_devastator_switchdelay_drop 0.2
-set g_balance_devastator_switchdelay_raise 0.2
-set g_balance_devastator_weaponreplace ""
-set g_balance_devastator_weaponstart 0
-set g_balance_devastator_weaponstartoverride -1
-set g_balance_devastator_weaponthrowable 1
-// }}}
-// {{{ #11: Port-O-Launch
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_speed 1000
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_switchdelay_drop 0.2
-set g_balance_porto_switchdelay_raise 0.2
-set g_balance_porto_weaponreplace ""
-set g_balance_porto_weaponstart 0
-set g_balance_porto_weaponstartoverride -1
-set g_balance_porto_weaponthrowable 1
-// }}}
-// {{{ #12: Vaporizer
-set g_balance_vaporizer_primary_ammo 10
-set g_balance_vaporizer_primary_animtime 0.3
-set g_balance_vaporizer_primary_damage 150
-set g_balance_vaporizer_primary_force 800
-set g_balance_vaporizer_primary_refire 1
-set g_balance_vaporizer_reload_ammo 0
-set g_balance_vaporizer_reload_time 0
-set g_balance_vaporizer_secondary_ammo 0
-set g_balance_vaporizer_secondary_animtime 0.2
-set g_balance_vaporizer_secondary_damage 25
-set g_balance_vaporizer_secondary_delay 0
-set g_balance_vaporizer_secondary_edgedamage 12.5
-set g_balance_vaporizer_secondary_force 480
-set g_balance_vaporizer_secondary_force_zscale 1
-set g_balance_vaporizer_secondary_lifetime 5
-set g_balance_vaporizer_secondary_radius 70
-set g_balance_vaporizer_secondary_refire 0.7
-set g_balance_vaporizer_secondary_shotangle 0
-set g_balance_vaporizer_secondary_speed 6000
-set g_balance_vaporizer_secondary_spread 0
-set g_balance_vaporizer_switchdelay_drop 0.2
-set g_balance_vaporizer_switchdelay_raise 0.2
-set g_balance_vaporizer_weaponreplace ""
-set g_balance_vaporizer_weaponstart 0
-set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 1
-// }}}
-// {{{ #13: Grappling Hook
-set g_balance_hook_primary_ammo 5
-set g_balance_hook_primary_animtime 0.3
-set g_balance_hook_primary_hooked_ammo 5
-set g_balance_hook_primary_hooked_time_free 2
-set g_balance_hook_primary_hooked_time_max 0
-set g_balance_hook_primary_refire 0.2
-set g_balance_hook_secondary_animtime 0.3
-set g_balance_hook_secondary_damage 25
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_secondary_duration 1.5
-set g_balance_hook_secondary_edgedamage 5
-set g_balance_hook_secondary_force -2000
-set g_balance_hook_secondary_gravity 5
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_lifetime 5
-set g_balance_hook_secondary_power 3
-set g_balance_hook_secondary_radius 500
-set g_balance_hook_secondary_refire 3
-set g_balance_hook_secondary_speed 0
-set g_balance_hook_switchdelay_drop 0.2
-set g_balance_hook_switchdelay_raise 0.2
-set g_balance_hook_weaponreplace ""
-set g_balance_hook_weaponstart 0
-set g_balance_hook_weaponstartoverride -1
-set g_balance_hook_weaponthrowable 1
-// }}}
-// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON)
-set g_balance_hlac_primary_ammo 1
-set g_balance_hlac_primary_animtime 0.4
-set g_balance_hlac_primary_damage 18
-set g_balance_hlac_primary_edgedamage 9
-set g_balance_hlac_primary_force 90
-set g_balance_hlac_primary_lifetime 5
-set g_balance_hlac_primary_radius 70
-set g_balance_hlac_primary_refire 0.15
-set g_balance_hlac_primary_speed 9000
-set g_balance_hlac_primary_spread_add 0.0045
-set g_balance_hlac_primary_spread_crouchmod 0.25
-set g_balance_hlac_primary_spread_max 0.25
-set g_balance_hlac_primary_spread_min 0.01
-set g_balance_hlac_reload_ammo 0
-set g_balance_hlac_reload_time 2
-set g_balance_hlac_secondary 1
-set g_balance_hlac_secondary_ammo 10
-set g_balance_hlac_secondary_animtime 0.3
-set g_balance_hlac_secondary_damage 15
-set g_balance_hlac_secondary_edgedamage 7.5
-set g_balance_hlac_secondary_force 90
-set g_balance_hlac_secondary_lifetime 5
-set g_balance_hlac_secondary_radius 70
-set g_balance_hlac_secondary_refire 1
-set g_balance_hlac_secondary_shots 6
-set g_balance_hlac_secondary_speed 9000
-set g_balance_hlac_secondary_spread 0.15
-set g_balance_hlac_secondary_spread_crouchmod 0.5
-set g_balance_hlac_switchdelay_drop 0.2
-set g_balance_hlac_switchdelay_raise 0.2
-set g_balance_hlac_weaponreplace ""
-set g_balance_hlac_weaponstart 0
-set g_balance_hlac_weaponstartoverride -1
-set g_balance_hlac_weaponthrowable 1
-// }}}
-// {{{ #15: @!#%'n Tuba
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_force 40
-set g_balance_tuba_pitchstep 6
-set g_balance_tuba_radius 200
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_switchdelay_drop 0.2
-set g_balance_tuba_switchdelay_raise 0.2
-set g_balance_tuba_volume 1
-set g_balance_tuba_weaponreplace ""
-set g_balance_tuba_weaponstart 0
-set g_balance_tuba_weaponstartoverride -1
-set g_balance_tuba_weaponthrowable 1
-// }}}
-// {{{ #16: Rifle (MUTATOR WEAPON)
-set g_balance_rifle_bursttime 0
-set g_balance_rifle_primary_ammo 10
-set g_balance_rifle_primary_animtime 0.4
-set g_balance_rifle_primary_bullethail 0
-set g_balance_rifle_primary_burstcost 0
-set g_balance_rifle_primary_damage 80
-set g_balance_rifle_primary_force 100
-set g_balance_rifle_primary_refire 1.2
-set g_balance_rifle_primary_shots 1
-set g_balance_rifle_primary_solidpenetration 62.2
-set g_balance_rifle_primary_spread 0
-set g_balance_rifle_primary_tracer 1
-set g_balance_rifle_reload_ammo 80
-set g_balance_rifle_reload_time 2
-set g_balance_rifle_secondary 1
-set g_balance_rifle_secondary_ammo 10
-set g_balance_rifle_secondary_animtime 0.3
-set g_balance_rifle_secondary_bullethail 0
-set g_balance_rifle_secondary_burstcost 0
-set g_balance_rifle_secondary_damage 20
-set g_balance_rifle_secondary_force 50
-set g_balance_rifle_secondary_refire 0.9
-set g_balance_rifle_secondary_reload 0
-set g_balance_rifle_secondary_shots 4
-set g_balance_rifle_secondary_solidpenetration 15.5
-set g_balance_rifle_secondary_spread 0.04
-set g_balance_rifle_secondary_tracer 0
-set g_balance_rifle_switchdelay_drop 0.2
-set g_balance_rifle_switchdelay_raise 0.2
-set g_balance_rifle_weaponreplace ""
-set g_balance_rifle_weaponstart 0
-set g_balance_rifle_weaponstartoverride -1
-set g_balance_rifle_weaponthrowable 1
-// }}}
-// {{{ #17: Fireball
-set g_balance_fireball_primary_animtime 0.4
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.2
-set g_balance_fireball_switchdelay_raise 0.2
-set g_balance_fireball_weaponreplace ""
-set g_balance_fireball_weaponstart 0
-set g_balance_fireball_weaponstartoverride -1
-set g_balance_fireball_weaponthrowable 0
-// }}}
-// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON)
-set g_balance_seeker_flac_ammo 1
-set g_balance_seeker_flac_animtime 0.1
-set g_balance_seeker_flac_damage 15
-set g_balance_seeker_flac_edgedamage 10
-set g_balance_seeker_flac_force 50
-set g_balance_seeker_flac_lifetime 0.1
-set g_balance_seeker_flac_lifetime_rand 0.05
-set g_balance_seeker_flac_radius 100
-set g_balance_seeker_flac_refire 0.1
-set g_balance_seeker_flac_speed 3000
-set g_balance_seeker_flac_speed_up 1000
-set g_balance_seeker_flac_speed_z 0
-set g_balance_seeker_flac_spread 0.4
-set g_balance_seeker_missile_accel 1400
-set g_balance_seeker_missile_ammo 2
-set g_balance_seeker_missile_animtime 0.2
-set g_balance_seeker_missile_count 3
-set g_balance_seeker_missile_damage 30
-set g_balance_seeker_missile_damageforcescale 4
-set g_balance_seeker_missile_decel 1400
-set g_balance_seeker_missile_delay 0.25
-set g_balance_seeker_missile_edgedamage 10
-set g_balance_seeker_missile_force 150
-set g_balance_seeker_missile_health 5
-set g_balance_seeker_missile_lifetime 15
-set g_balance_seeker_missile_proxy 0
-set g_balance_seeker_missile_proxy_delay 0.2
-set g_balance_seeker_missile_proxy_maxrange 45
-set g_balance_seeker_missile_radius 80
-set g_balance_seeker_missile_refire 0.5
-set g_balance_seeker_missile_smart 1
-set g_balance_seeker_missile_smart_mindist 800
-set g_balance_seeker_missile_smart_trace_max 2500
-set g_balance_seeker_missile_smart_trace_min 1000
-set g_balance_seeker_missile_speed 700
-set g_balance_seeker_missile_speed_max 1300
-set g_balance_seeker_missile_speed_up 300
-set g_balance_seeker_missile_speed_z 0
-set g_balance_seeker_missile_spread 0
-set g_balance_seeker_missile_turnrate 0.65
-set g_balance_seeker_reload_ammo 0
-set g_balance_seeker_reload_time 2
-set g_balance_seeker_switchdelay_drop 0.2
-set g_balance_seeker_switchdelay_raise 0.2
-set g_balance_seeker_tag_ammo 1
-set g_balance_seeker_tag_animtime 0.2
-set g_balance_seeker_tag_damageforcescale 4
-set g_balance_seeker_tag_health 5
-set g_balance_seeker_tag_lifetime 15
-set g_balance_seeker_tag_refire 0.75
-set g_balance_seeker_tag_speed 5000
-set g_balance_seeker_tag_spread 0
-set g_balance_seeker_tag_tracker_lifetime 10
-set g_balance_seeker_type 0
-set g_balance_seeker_weaponreplace ""
-set g_balance_seeker_weaponstart 0
-set g_balance_seeker_weaponstartoverride -1
-set g_balance_seeker_weaponthrowable 1
-// }}}
-// {{{ #19: Shockwave
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 40
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 15
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 1
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 100
-set g_balance_shockwave_blast_jump_force_velocitybias 1
-set g_balance_shockwave_blast_jump_force_zscale 1
-set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_jump_multiplier_distance 0.5
-set g_balance_shockwave_blast_jump_multiplier_min 0
-set g_balance_shockwave_blast_jump_radius 150
-set g_balance_shockwave_blast_multiplier_accuracy 0.45
-set g_balance_shockwave_blast_multiplier_distance 0.2
-set g_balance_shockwave_blast_multiplier_min 0
-set g_balance_shockwave_blast_refire 0.75
-set g_balance_shockwave_blast_splash_damage 15
-set g_balance_shockwave_blast_splash_edgedamage 0
-set g_balance_shockwave_blast_splash_force 100
-set g_balance_shockwave_blast_splash_force_forwardbias 50
-set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_splash_multiplier_distance 0.5
-set g_balance_shockwave_blast_splash_multiplier_min 0
-set g_balance_shockwave_blast_splash_radius 70
-set g_balance_shockwave_blast_spread_max 120
-set g_balance_shockwave_blast_spread_min 25
-set g_balance_shockwave_melee_animtime 1.3
-set g_balance_shockwave_melee_damage 80
-set g_balance_shockwave_melee_delay 0.25
-set g_balance_shockwave_melee_force 200
-set g_balance_shockwave_melee_multihit 1
-set g_balance_shockwave_melee_no_doubleslap 1
-set g_balance_shockwave_melee_nonplayerdamage 40
-set g_balance_shockwave_melee_range 120
-set g_balance_shockwave_melee_refire 1.25
-set g_balance_shockwave_melee_swing_side 120
-set g_balance_shockwave_melee_swing_up 30
-set g_balance_shockwave_melee_time 0.15
-set g_balance_shockwave_melee_traces 10
-set g_balance_shockwave_switchdelay_drop 0.2
-set g_balance_shockwave_switchdelay_raise 0.2
-set g_balance_shockwave_weaponreplace ""
-set g_balance_shockwave_weaponstart 0
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_weaponthrowable 0
-// }}}
-// {{{ #20: Arc
-set g_balance_arc_beam_ammo 6
-set g_balance_arc_beam_animtime 0.1
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 100
-set g_balance_arc_beam_degreespersegment 1
-set g_balance_arc_beam_distancepersegment 0
-set g_balance_arc_beam_falloff_halflifedist 0
-set g_balance_arc_beam_falloff_maxdist 0
-set g_balance_arc_beam_falloff_mindist 0
-set g_balance_arc_beam_force 600
-set g_balance_arc_beam_healing_amax 0
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 150
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_heat 0
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1500
-set g_balance_arc_beam_refire 0.25
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.6
-set g_balance_arc_bolt 1
-set g_balance_arc_bolt_ammo 1
-set g_balance_arc_bolt_damage 25
-set g_balance_arc_bolt_damageforcescale 0
-set g_balance_arc_bolt_edgedamage 12.5
-set g_balance_arc_bolt_force 120
-set g_balance_arc_bolt_health 15
-set g_balance_arc_bolt_lifetime 5
-set g_balance_arc_bolt_radius 65
-set g_balance_arc_bolt_refire 0.16667
-set g_balance_arc_bolt_speed 2300
-set g_balance_arc_bolt_spread 0
-set g_balance_arc_burst_ammo 15
-set g_balance_arc_burst_damage 250
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_burst_heat 5
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 0
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
-set g_balance_arc_switchdelay_drop 0.2
-set g_balance_arc_switchdelay_raise 0.2
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
-// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
-set g_balance_okhmg_primary_ammo 1
-set g_balance_okhmg_primary_damage 30
-set g_balance_okhmg_primary_force 10
-set g_balance_okhmg_primary_refire 0.05
-set g_balance_okhmg_primary_solidpenetration 127
-set g_balance_okhmg_primary_spread_add 0.005
-set g_balance_okhmg_primary_spread_max 0.06
-set g_balance_okhmg_primary_spread_min 0.01
-set g_balance_okhmg_reload_ammo 120
-set g_balance_okhmg_reload_time 1
-set g_balance_okhmg_secondary_ammo 0
-set g_balance_okhmg_secondary_animtime 0.2
-set g_balance_okhmg_secondary_damage 25
-set g_balance_okhmg_secondary_delay 0
-set g_balance_okhmg_secondary_edgedamage 12.5
-set g_balance_okhmg_secondary_force 360
-set g_balance_okhmg_secondary_force_zscale 1
-set g_balance_okhmg_secondary_lifetime 5
-set g_balance_okhmg_secondary_radius 70
-set g_balance_okhmg_secondary_refire 0.7
-set g_balance_okhmg_secondary_refire_type 1
-set g_balance_okhmg_secondary_shotangle 0
-set g_balance_okhmg_secondary_speed 6000
-set g_balance_okhmg_secondary_spread 0
-set g_balance_okhmg_switchdelay_drop 0.2
-set g_balance_okhmg_switchdelay_raise 0.2
-set g_balance_okhmg_weaponreplace ""
-set g_balance_okhmg_weaponstart 0
-set g_balance_okhmg_weaponstartoverride 0
-set g_balance_okhmg_weaponthrowable 0
-// }}}
-// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
-set g_balance_okmachinegun_primary_ammo 1
-set g_balance_okmachinegun_primary_damage 25
-set g_balance_okmachinegun_primary_force 5
-set g_balance_okmachinegun_primary_refire 0.1
-set g_balance_okmachinegun_primary_solidpenetration 100
-set g_balance_okmachinegun_primary_spread_add 0.012
-set g_balance_okmachinegun_primary_spread_max 0.05
-set g_balance_okmachinegun_primary_spread_min 0
-set g_balance_okmachinegun_reload_ammo 30
-set g_balance_okmachinegun_reload_time 1.5
-set g_balance_okmachinegun_secondary_animtime 0.2
-set g_balance_okmachinegun_secondary_damage 25
-set g_balance_okmachinegun_secondary_delay 0
-set g_balance_okmachinegun_secondary_edgedamage 12.5
-set g_balance_okmachinegun_secondary_force 360
-set g_balance_okmachinegun_secondary_force_zscale 1
-set g_balance_okmachinegun_secondary_lifetime 5
-set g_balance_okmachinegun_secondary_radius 70
-set g_balance_okmachinegun_secondary_refire 0.7
-set g_balance_okmachinegun_secondary_refire_type 1
-set g_balance_okmachinegun_secondary_shotangle 0
-set g_balance_okmachinegun_secondary_speed 6000
-set g_balance_okmachinegun_secondary_spread 0
-set g_balance_okmachinegun_switchdelay_drop 0.2
-set g_balance_okmachinegun_switchdelay_raise 0.2
-set g_balance_okmachinegun_weaponreplace ""
-set g_balance_okmachinegun_weaponstart 0
-set g_balance_okmachinegun_weaponstartoverride -1
-set g_balance_okmachinegun_weaponthrowable 1
-// }}}
-// {{{ #23: Overkill Nex (MUTATOR WEAPON)
-set g_balance_oknex_charge 0
-set g_balance_oknex_charge_animlimit 0.5
-set g_balance_oknex_charge_limit 1
-set g_balance_oknex_charge_maxspeed 800
-set g_balance_oknex_charge_mindmg 40
-set g_balance_oknex_charge_minspeed 400
-set g_balance_oknex_charge_rate 0.6
-set g_balance_oknex_charge_rot_pause 0
-set g_balance_oknex_charge_rot_rate 0
-set g_balance_oknex_charge_shot_multiplier 0
-set g_balance_oknex_charge_start 0.5
-set g_balance_oknex_charge_velocity_rate 0
-set g_balance_oknex_primary_ammo 10
-set g_balance_oknex_primary_animtime 0.65
-set g_balance_oknex_primary_damage 100
-set g_balance_oknex_primary_damagefalloff_forcehalflife 0
-set g_balance_oknex_primary_damagefalloff_halflife 0
-set g_balance_oknex_primary_damagefalloff_maxdist 0
-set g_balance_oknex_primary_damagefalloff_mindist 0
-set g_balance_oknex_primary_force 500
-set g_balance_oknex_primary_refire 1
-set g_balance_oknex_reload_ammo 50
-set g_balance_oknex_reload_time 2
-set g_balance_oknex_secondary 2
-set g_balance_oknex_secondary_ammo 0
-set g_balance_oknex_secondary_animtime 0.2
-set g_balance_oknex_secondary_chargepool 0
-set g_balance_oknex_secondary_chargepool_pause_regen 1
-set g_balance_oknex_secondary_chargepool_regen 0.15
-set g_balance_oknex_secondary_damage 25
-set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
-set g_balance_oknex_secondary_damagefalloff_halflife 0
-set g_balance_oknex_secondary_damagefalloff_maxdist 0
-set g_balance_oknex_secondary_damagefalloff_mindist 0
-set g_balance_oknex_secondary_delay 0
-set g_balance_oknex_secondary_edgedamage 12.5
-set g_balance_oknex_secondary_force 360
-set g_balance_oknex_secondary_force_zscale 1
-set g_balance_oknex_secondary_lifetime 5
-set g_balance_oknex_secondary_radius 70
-set g_balance_oknex_secondary_refire 0.7
-set g_balance_oknex_secondary_refire_type 1
-set g_balance_oknex_secondary_shotangle 0
-set g_balance_oknex_secondary_speed 6000
-set g_balance_oknex_secondary_spread 0
-set g_balance_oknex_switchdelay_drop 0.2
-set g_balance_oknex_switchdelay_raise 0.2
-set g_balance_oknex_weaponreplace ""
-set g_balance_oknex_weaponstart 0
-set g_balance_oknex_weaponstartoverride -1
-set g_balance_oknex_weaponthrowable 1
-// }}}
-// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
-set g_balance_okrpc_primary_ammo 10
-set g_balance_okrpc_primary_animtime 1
-set g_balance_okrpc_primary_damage 150
-set g_balance_okrpc_primary_damage2 500
-set g_balance_okrpc_primary_damageforcescale 2
-set g_balance_okrpc_primary_edgedamage 50
-set g_balance_okrpc_primary_force 400
-set g_balance_okrpc_primary_health 25
-set g_balance_okrpc_primary_lifetime 30
-set g_balance_okrpc_primary_radius 300
-set g_balance_okrpc_primary_refire 1
-set g_balance_okrpc_primary_speed 2500
-set g_balance_okrpc_primary_speedaccel 5000
-set g_balance_okrpc_reload_ammo 10
-set g_balance_okrpc_reload_time 1
-set g_balance_okrpc_secondary_ammo 0
-set g_balance_okrpc_secondary_animtime 0.2
-set g_balance_okrpc_secondary_damage 25
-set g_balance_okrpc_secondary_delay 0
-set g_balance_okrpc_secondary_edgedamage 12.5
-set g_balance_okrpc_secondary_force 360
-set g_balance_okrpc_secondary_force_zscale 1
-set g_balance_okrpc_secondary_lifetime 5
-set g_balance_okrpc_secondary_radius 70
-set g_balance_okrpc_secondary_refire 0.7
-set g_balance_okrpc_secondary_refire_type 1
-set g_balance_okrpc_secondary_shotangle 0
-set g_balance_okrpc_secondary_speed 6000
-set g_balance_okrpc_secondary_spread 0
-set g_balance_okrpc_switchdelay_drop 0.2
-set g_balance_okrpc_switchdelay_raise 0.2
-set g_balance_okrpc_weaponreplace ""
-set g_balance_okrpc_weaponstart 0
-set g_balance_okrpc_weaponstartoverride 0
-set g_balance_okrpc_weaponthrowable 0
-// }}}
-// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
-set g_balance_okshotgun_primary_ammo 3
-set g_balance_okshotgun_primary_animtime 0.65
-set g_balance_okshotgun_primary_bot_range 512
-set g_balance_okshotgun_primary_bullets 10
-set g_balance_okshotgun_primary_damage 17
-set g_balance_okshotgun_primary_force 80
-set g_balance_okshotgun_primary_refire 0.75
-set g_balance_okshotgun_primary_solidpenetration 3.8
-set g_balance_okshotgun_primary_spread 0.07
-set g_balance_okshotgun_reload_ammo 24
-set g_balance_okshotgun_reload_time 2
-set g_balance_okshotgun_secondary_animtime 0.2
-set g_balance_okshotgun_secondary_damage 25
-set g_balance_okshotgun_secondary_delay 0
-set g_balance_okshotgun_secondary_edgedamage 12.5
-set g_balance_okshotgun_secondary_force 360
-set g_balance_okshotgun_secondary_force_zscale 1
-set g_balance_okshotgun_secondary_lifetime 5
-set g_balance_okshotgun_secondary_radius 70
-set g_balance_okshotgun_secondary_refire 0.7
-set g_balance_okshotgun_secondary_refire_type 1
-set g_balance_okshotgun_secondary_shotangle 0
-set g_balance_okshotgun_secondary_speed 6000
-set g_balance_okshotgun_secondary_spread 0
-set g_balance_okshotgun_switchdelay_drop 0.2
-set g_balance_okshotgun_switchdelay_raise 0.2
-set g_balance_okshotgun_weaponreplace ""
-set g_balance_okshotgun_weaponstart 0
-set g_balance_okshotgun_weaponstartoverride -1
-set g_balance_okshotgun_weaponthrowable 1
-// }}}
index de22d1f7b5f5d71392bee5d050c31a27f877f232..ea4c4dbb600ff07ff440f8e4a84b708999e33af6 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance Mario
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index 81c786ed60cb08e895c964470125c8f061069fd4..b3d856c054bb6493295fdd3f088c2c5819aa8926 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance Nexuiz25
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 150
index 28f8f17d768c4424e5b60261fa5ad639b142906d..7aea6f87f41d7d8db4ee79e8c022955d57af6baf 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance Overkill
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index f98731e01726b4c381c3459974a7bfd2b974e7a2..c177f30ff2502411b4da4886370fba5347f714f9 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance Samual
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index 960211605e7dce56f54ae6f055fd159e8f65e952..9baac183f416d9ff31b85405667f027ac7e279f7 100644 (file)
@@ -1,244 +1,3 @@
+exec balance-xonotic.cfg
 g_mod_balance Testing
-
-// {{{ starting gear
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_plasma 0
-set g_start_ammo_fuel 0
-set g_random_start_weapons_count 0
-set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
-set g_random_start_shells 15
-set g_random_start_bullets 80
-set g_random_start_rockets 40
-set g_random_start_cells 30
-set g_random_start_plasma 30
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_plasma 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_plasma 180
-set g_balance_nix_ammo_fuel 100
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_plasma 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_plasma 30
-set g_pickup_plasma_weapon 30
-set g_pickup_plasma_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 1
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 200
-set g_pickup_armormedium_anyway 1
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 200
-set g_pickup_armorbig_anyway 1
-set g_pickup_armormega 100
-set g_pickup_armormega_max 200
-set g_pickup_armormega_anyway 1
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 1
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 200
-set g_pickup_healthmedium_anyway 1
-set g_pickup_healthbig 50
-set g_pickup_healthbig_max 200
-set g_pickup_healthbig_anyway 1
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 1
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 10
-set g_pickup_respawntime_initial_random 1
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 0
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.02
-set g_balance_health_rotlinear 1
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 200
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.02
-set g_balance_armor_rotlinear 1
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 200
-set g_balance_armor_blockpercent 0.7
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 100
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage -2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 1
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_falldamage_onlyvertical 0
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
-set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.33 // only 1/3rd damage is taken
-set g_balance_powerup_invincible_takeforce 0.33
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_reverse_thrust 0 "if not 0, downward acceleration when crouching with the jetpack"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-set g_balance_grapplehook_nade_time 0.7
-set g_balance_grapplehook_crouchslide 0
-set g_balance_grapplehook_gravity 0
-set g_balance_grapplehook_pull_frozen 0
-// }}}
-
-// {{{ port-o-launch
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-
-exec bal-wep-testing.cfg
+testing_enable
index 4ee3f36cdb6bf4d26960512fb08e27b9fc139177..93cdc11cecae71bc6ee0703243fa2ab1b92d46b4 100644 (file)
@@ -1,244 +1,3 @@
-g_mod_balance XPM
-
-// {{{ starting gear
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_plasma 0
-set g_start_ammo_fuel 0
-set g_random_start_weapons_count 0
-set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
-set g_random_start_shells 15
-set g_random_start_bullets 80
-set g_random_start_rockets 40
-set g_random_start_cells 30
-set g_random_start_plasma 30
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_plasma 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_plasma 180
-set g_balance_nix_ammo_fuel 100
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_plasma 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_plasma 30
-set g_pickup_plasma_weapon 30
-set g_pickup_plasma_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 0
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 100
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 100
-set g_pickup_armorbig_anyway 0
-set g_pickup_armormega 100
-set g_pickup_armormega_max 200
-set g_pickup_armormega_anyway 0
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 0
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthbig 50
-set g_pickup_healthbig_max 100
-set g_pickup_healthbig_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 0
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 10
-set g_pickup_respawntime_initial_random 1
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 0
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.02
-set g_balance_health_rotlinear 1
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 200
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.02
-set g_balance_armor_rotlinear 1
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 200
-set g_balance_armor_blockpercent 0.7
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 100
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage -2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 1
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_falldamage_onlyvertical 0
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
-set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.33 // only 1/3rd damage is taken
-set g_balance_powerup_invincible_takeforce 0.33
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_reverse_thrust 0 "if not 0, downward acceleration when crouching with the jetpack"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-set g_balance_grapplehook_nade_time 0.7
-set g_balance_grapplehook_crouchslide 0
-set g_balance_grapplehook_gravity 0
-set g_balance_grapplehook_pull_frozen 0
-// }}}
-
-// {{{ port-o-launch
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-
-exec bal-wep-testing.cfg
+exec balance-xpm.cfg
+g_mod_balance XPM // XPM is technically modified anyway, this way it'll stay in the right category
+testing_enable
index e866bd11d18ef8ea51f9b029029b15bed328833f..5ba025a88ba04c0c00718a83888c8ec267206a57 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance XDF
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index 2666108f48b2e4163d985cb03f33dcd44dffbeae..8c36402ab5c49cce391eff869608b88b316ab132 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance Xonotic
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index bcd58487892e716a01ba8122360838054ef65777..46e04a9504d5a55160dc20ce3e60f025e357a565 100644 (file)
@@ -1,4 +1,5 @@
 g_mod_balance XPM
+testing_disable
 
 // {{{ starting gear
 set g_balance_health_start 100
index 8525385d98ba3e2b5d6a1638d1168f98e5800ce7..387d93720392d660fccf6b43b8dd9ca37c05a0ad 100755 (executable)
@@ -6,16 +6,20 @@ check_files()
 {
        countw=`awk ''"$3"' { print $2; }' "$1" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32`
        for b in $2; do
+               if [ "$b" = "balance-testing.cfg" ] || [ "$b" = "balance-testingxpm.cfg" ]; then
+                       continue
+               fi
+
                countb=`awk ''"$3"' { print $2; }' "$b" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32`
                if [ "$countw" != "$countb" ]; then
-                       echo "Mismatch between "$1" and $b. Aborting."
+                       echo "Mismatch between $1 and $b. Aborting."
                        echo "Differences are:"
                        echo "< missing in $b"
                        echo "> must get removed from $b"
                        A=`mktemp || echo a.tmp`
                        B=`mktemp || echo b.tmp`
-                       awk ''"$3"' { print $2; }' "$1"      | sort -u | tr -d '\r' > "$A"
-                       awk ''"$3"' { print $2; }' "$b"                     | sort -u | tr -d '\r' > "$B"
+                       awk ''"$3"' { print $2; }' "$1" | sort -u | tr -d '\r' > "$A"
+                       awk ''"$3"' { print $2; }' "$b" | sort -u | tr -d '\r' > "$B"
                        diff "$A" "$B" | grep '^[<>]' | sort
                        rm -f "$A" "$B"
                        errord=true
index d3a22cabc0d41e7c249d6f0927d5b3ae828eda61..1375a78871d11b51c9abb68ccbc2f801f46f1af5 100644 (file)
@@ -88,7 +88,9 @@ alias g_maplist_shufflenow    "qc_cmd_svmenu maplist shuffle"
 alias g_maplist_cleanup        "qc_cmd_svmenu maplist cleanup" // removes maps that don't exist from the map list
 
 alias addfav "qc_cmd_svmenu addtolist net_slist_favorites ${* ?}"
+alias delfav "qc_cmd_svmenu removefromlist net_slist_favorites ${* ?}"
 alias addvote "qc_cmd_svmenu addtolist sv_vote_commands ${* ?}"
+alias delvote "qc_cmd_svmenu removefromlist sv_vote_commands ${* ?}"
 
 
 // ========================
index 1577aa0dc02ff9d09b2e89d551a01259cca05fdd..2e397ca68a06e9e0fc2ac95dbf6b6754292d907d 100644 (file)
@@ -5,6 +5,7 @@
 # Translators:
 # Ximielga <dorian@openmailbox.org>, 2014-2015
 # Ḷḷumex03, 2014
+# Ḷḷumex03, 2014
 # Ḷḷumex03, 2014-2015
 # Tornes Ḷḷume <tornes.llume@openmailbox.org>, 2015-2017
 # Ximielga <dorian@openmailbox.org>, 2014
index 3b406a3e5d5cc8d464cc18602c377a4d54c15bff..1d7275ed7db66a1c43990a94036611437bf591b9 100644 (file)
@@ -5,13 +5,14 @@
 # Translators:
 # Henry 'Exitium' Sanmark <henry.sanmark@gmail.com>, 2011
 # Jonas Sahlberg <fragthelion@gmail.com>, 2015
+# Oi Suomi On! <oisuomion@protonmail.com>, 2020
 msgid ""
 msgstr ""
 "Project-Id-Version: Xonotic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2019-05-19 07:23+0200\n"
-"PO-Revision-Date: 2019-05-19 05:23+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2020-05-12 18:36+0000\n"
+"Last-Translator: Oi Suomi On! <oisuomion@protonmail.com>\n"
 "Language-Team: Finnish (http://www.transifex.com/team-xonotic/xonotic/"
 "language/fi/)\n"
 "Language: fi\n"
@@ -24,16 +25,18 @@ msgstr ""
 #, c-format
 msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)"
 msgstr ""
+"^2Viety onnistuneesti kohteeseen %s! (Huomautus: tallennettu kansioon data/"
+"data/)"
 
 #: qcsrc/client/hud/hud_config.qc:247
 #, c-format
 msgid "^1Couldn't write to %s"
-msgstr ""
+msgstr "^1Ei voitu kirjoittaa kohteeseen %s"
 
 #: qcsrc/client/hud/panel/centerprint.qc:140
 #, c-format
 msgid "^3Countdown message at time %s, seconds left: ^COUNT"
-msgstr ""
+msgstr "^3Laskentaviesti ajassa %s, sekuntia jäljellä: ^COUNT"
 
 #: qcsrc/client/hud/panel/centerprint.qc:142
 #, c-format
@@ -41,184 +44,187 @@ msgid ""
 "^1Multiline message at time %s that\n"
 "^1lasts longer than normal"
 msgstr ""
+"^1Monirivinen viesti ajassa %s joka\n"
+"^1kestää pidempään kuin tavallisesti"
 
 #: qcsrc/client/hud/panel/centerprint.qc:144
 #, c-format
 msgid "Message at time %s"
-msgstr ""
+msgstr "Viesti ajassa %s"
 
 #: qcsrc/client/hud/panel/centerprint.qc:149
 msgid "Generic message"
-msgstr ""
+msgstr "Yleisluontoinen viesti"
 
 #: qcsrc/client/hud/panel/chat.qc:84
 msgid "^3Player^7: This is the chat area."
-msgstr ""
+msgstr "^3Pelaaja^7: Tämä on keskustelualue."
 
 #: qcsrc/client/hud/panel/engineinfo.qc:72
 #, c-format
 msgid "FPS: %.*f"
-msgstr ""
+msgstr "FPS-ruutunopeus: %.*f"
 
 #: qcsrc/client/hud/panel/infomessages.qc:89
 msgid "^1Observing"
-msgstr ""
+msgstr "^1Tarkkailee"
 
 #: qcsrc/client/hud/panel/infomessages.qc:91
 #, c-format
 msgid "^1Spectating: ^7%s"
-msgstr ""
+msgstr "^1Katselee: ^7%s"
 
 #: qcsrc/client/hud/panel/infomessages.qc:102
 #, c-format
 msgid "^1Press ^3%s^1 to spectate"
-msgstr ""
+msgstr "^1Paina ^3%s^1 katsellaksesi"
 
 #: qcsrc/client/hud/panel/infomessages.qc:102
 #: qcsrc/menu/xonotic/keybinder.qc:47
 msgid "primary fire"
-msgstr ""
+msgstr "ensisijainen tulitus"
 
 #: qcsrc/client/hud/panel/infomessages.qc:104
 #, c-format
 msgid "^1Press ^3%s^1 or ^3%s^1 for next or previous player"
 msgstr ""
+"^1Paina ^3%s^1 tai ^3%s^1 siirtyäksesi seuraavaan tai edelliseen pelaajaan"
 
 #: qcsrc/client/hud/panel/infomessages.qc:104
 #: qcsrc/client/hud/panel/infomessages.qc:108
 msgid "next weapon"
-msgstr ""
+msgstr "seuraava ase"
 
 #: qcsrc/client/hud/panel/infomessages.qc:104
 #: qcsrc/client/hud/panel/infomessages.qc:108
 msgid "previous weapon"
-msgstr ""
+msgstr "edellinen ase"
 
 #: qcsrc/client/hud/panel/infomessages.qc:108
 #, c-format
 msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed"
-msgstr ""
+msgstr "^1Käytä ^3%s^1 tai ^3%s^1 muuttaaksesi nopeutta"
 
 #: qcsrc/client/hud/panel/infomessages.qc:110
 #, c-format
 msgid "^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"
-msgstr ""
+msgstr "^1Paina ^3%s^1 tarkkaillaksesi, ^3%s^1 vaihtaaksesi kameratilaa"
 
 #: qcsrc/client/hud/panel/infomessages.qc:110
 #: qcsrc/common/vehicles/cl_vehicles.qc:190
 msgid "drop weapon"
-msgstr ""
+msgstr "pudota ase"
 
 #: qcsrc/client/hud/panel/infomessages.qc:110
 #: qcsrc/menu/xonotic/keybinder.qc:48
 msgid "secondary fire"
-msgstr ""
+msgstr "toissijainen tulitus"
 
 #: qcsrc/client/hud/panel/infomessages.qc:113
 #, c-format
 msgid "^1Press ^3%s^1 for gamemode info"
-msgstr ""
+msgstr "^1Paina ^3%s^1 nähdäksesi pelitilatiedot"
 
 #: qcsrc/client/hud/panel/infomessages.qc:113
 #: qcsrc/menu/xonotic/keybinder.qc:105
 msgid "server info"
-msgstr ""
+msgstr "palvelimen tiedot"
 
 #: qcsrc/client/hud/panel/infomessages.qc:126
 msgid "^1Match has already begun"
-msgstr ""
+msgstr "^1Ottelu on jo alkanut"
 
 #: qcsrc/client/hud/panel/infomessages.qc:128
 msgid "^1You have no more lives left"
-msgstr ""
+msgstr "^1Sinulla ei ole elämiä enää jäljellä"
 
 #: qcsrc/client/hud/panel/infomessages.qc:130
 #: qcsrc/client/hud/panel/infomessages.qc:133
 #, c-format
 msgid "^1Press ^3%s^1 to join"
-msgstr ""
+msgstr "^1Paina ^3%s^1 liittyäksesi"
 
 #: qcsrc/client/hud/panel/infomessages.qc:130
 #: qcsrc/client/hud/panel/infomessages.qc:133
 msgid "jump"
-msgstr ""
+msgstr "hyppää"
 
 #: qcsrc/client/hud/panel/infomessages.qc:141
 #, c-format
 msgid "^1Game starts in ^3%d^1 seconds"
-msgstr ""
+msgstr "^1Peli alkaa ^3%d^1 sekunnin kuluttua"
 
 #: qcsrc/client/hud/panel/infomessages.qc:147
 msgid "^2Currently in ^1warmup^2 stage!"
-msgstr ""
+msgstr "^2Tällä hetkellä ^1lämmittelyssä^2 !"
 
 #: qcsrc/client/hud/panel/infomessages.qc:162
 #, c-format
 msgid "%sPress ^3%s%s to end warmup"
-msgstr ""
+msgstr "%sPaina ^3%s%s päättääksesi lämmittelyn"
 
 #: qcsrc/client/hud/panel/infomessages.qc:162
 #: qcsrc/client/hud/panel/infomessages.qc:164
 #: qcsrc/client/hud/panel/infomessages.qc:177
 #: qcsrc/menu/xonotic/keybinder.qc:101
 msgid "ready"
-msgstr ""
+msgstr "valmis"
 
 #: qcsrc/client/hud/panel/infomessages.qc:164
 #, c-format
 msgid "%sPress ^3%s%s once you are ready"
-msgstr ""
+msgstr "%sPaina ^3%s%s kun olet valmis"
 
 #: qcsrc/client/hud/panel/infomessages.qc:169
 msgid "^2Waiting for others to ready up to end warmup..."
-msgstr ""
+msgstr "^2Odotetaan muita saadakseen lämmittelynsä valmiiksi..."
 
 #: qcsrc/client/hud/panel/infomessages.qc:171
 msgid "^2Waiting for others to ready up..."
-msgstr ""
+msgstr "^2Odotetaan muita valmiiksi..."
 
 #: qcsrc/client/hud/panel/infomessages.qc:177
 #, c-format
 msgid "^2Press ^3%s^2 to end warmup"
-msgstr ""
+msgstr "^2Paina ^3%s^2 lämmittelyn lopettamiseksi"
 
 #: qcsrc/client/hud/panel/infomessages.qc:198
 msgid "Teamnumbers are unbalanced!"
-msgstr ""
+msgstr "Joukkuemäärät ovat epätasapainossa!"
 
 #: qcsrc/client/hud/panel/infomessages.qc:201
 #, c-format
 msgid " Press ^3%s%s to adjust"
-msgstr ""
+msgstr " Paina ^3%s%s säätääksesi"
 
 #: qcsrc/client/hud/panel/infomessages.qc:201
 #: qcsrc/menu/xonotic/keybinder.qc:117
 msgid "team menu"
-msgstr ""
+msgstr "joukkuevalikko"
 
 #: qcsrc/client/hud/panel/infomessages.qc:211
 msgid "^1Spectating this player:"
-msgstr ""
+msgstr "^1Seurataan tätä pelaajaa:"
 
 #: qcsrc/client/hud/panel/infomessages.qc:211
 msgid "^1Spectating you:"
-msgstr ""
+msgstr "^1Sinua seuraa:"
 
 #: qcsrc/client/hud/panel/infomessages.qc:227
 msgid "^7Press ^3ESC ^7to show HUD options."
-msgstr ""
+msgstr "^7Paina ^3ESC ^7nähdäksesi HUD-vaihtoehdot."
 
 #: qcsrc/client/hud/panel/infomessages.qc:228
 msgid "^3Doubleclick ^7a panel for panel-specific options."
-msgstr ""
+msgstr "^3Tuplanapsauta ^7a paneelia paneelikohtaisia valintoja varten."
 
 #: qcsrc/client/hud/panel/infomessages.qc:229
 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
-msgstr ""
+msgstr "^3CTRL ^7kytkee pois yhteenottotestauksen, ^3SHIFT ^7ja"
 
 #: qcsrc/client/hud/panel/infomessages.qc:230
 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
-msgstr ""
+msgstr "^3ALT ^7+ ^3NUOLINÄPPÄIMET ^7hienosäätöä varten."
 
 #: qcsrc/client/hud/panel/modicons.qc:576
 msgid "Personal best"
@@ -232,13 +238,13 @@ msgstr "Serverin Paras"
 #: qcsrc/client/hud/panel/score.qc:63
 #, c-format
 msgid "Player %d"
-msgstr ""
+msgstr "Pelaaja %d"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:591
 #: qcsrc/client/hud/panel/quickmenu.qc:593
 #, c-format
 msgid "Submenu%d"
-msgstr ""
+msgstr "Alivalikko%d"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:598
 #, c-format
@@ -252,281 +258,281 @@ msgstr "Jatka..."
 #: qcsrc/client/hud/panel/quickmenu.qc:781
 #: qcsrc/client/hud/panel/quickmenu.qc:788
 msgid "Chat"
-msgstr ""
+msgstr "Keskustelu"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:782
 msgid "QMCMD^Send public message to"
-msgstr ""
+msgstr "QMCMD^Lähetä julkinen viesti "
 
 #: qcsrc/client/hud/panel/quickmenu.qc:783
 msgid "QMCMD^:-) / nice one"
-msgstr ""
+msgstr "QMCMD^:-) / se oli hieno"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:783
 msgid "QMCMD^nice one"
-msgstr ""
+msgstr "QMCMD^se oli hieno"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:784
 msgid "QMCMD^good game"
-msgstr ""
+msgstr "QMCMD^hyvä peli"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:785
 msgid "QMCMD^hi / good luck"
-msgstr ""
+msgstr "QMCMD^moro / onnea matkaan"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:785
 msgid "QMCMD^hi / good luck and have fun"
-msgstr ""
+msgstr "QMCMD^moro / onnea matkaan ja pidähän hauskaa"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:787
 msgid "QMCMD^Send in English"
-msgstr ""
+msgstr "QMCMD^Lähetä Suomeksi"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:792
 #: qcsrc/client/hud/panel/quickmenu.qc:808
 msgid "QMCMD^Team chat"
-msgstr ""
+msgstr "QMCMD^joukkuekeskustelu"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:793
 msgid "QMCMD^quad soon"
-msgstr ""
+msgstr "QMCMD^kohta neloistila"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:794
 msgid "QMCMD^free item %x^7 (l:%y^7)"
-msgstr ""
+msgstr "QMCMD^vapauta esine %x^7 (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:794
 msgid "QMCMD^free item, icon"
-msgstr ""
+msgstr "QMCMD^vapauta esine, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:795
 msgid "QMCMD^took item (l:%l^7)"
-msgstr ""
+msgstr "QMCMD^otti esineen (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:795
 msgid "QMCMD^took item, icon"
-msgstr ""
+msgstr "QMCMD^otti esineen, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:796
 msgid "QMCMD^negative"
-msgstr ""
+msgstr "QMCMD^negatiivinen"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:797
 msgid "QMCMD^positive"
-msgstr ""
+msgstr "QMCMD^positiivinen"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:798
 msgid "QMCMD^need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
-msgstr ""
+msgstr "QMCMD^avuntarve (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:798
 msgid "QMCMD^need help, icon"
-msgstr ""
+msgstr "QMCMD^avuntarve, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:799
 msgid "QMCMD^enemy seen (l:%y^7)"
-msgstr ""
+msgstr "QMCMD^vihollinen havaittu (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:799
 msgid "QMCMD^enemy seen, icon"
-msgstr ""
+msgstr "QMCMD^vihollinen havaittu, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:800
 msgid "QMCMD^flag seen (l:%y^7)"
-msgstr ""
+msgstr "QMCMD^lippu havaittu (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:800
 msgid "QMCMD^flag seen, icon"
-msgstr ""
+msgstr "QMCMD^lippu havaittu, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:801
 msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
-msgstr ""
+msgstr "QMCMD^puolustaa (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:801
 msgid "QMCMD^defending, icon"
-msgstr ""
+msgstr "QMCMD^puolustaa, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:802
 msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
-msgstr ""
+msgstr "QMCMD^kuljeskelee (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:802
 msgid "QMCMD^roaming, icon"
-msgstr ""
+msgstr "QMCMD^kuljeskelee, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:803
 msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
-msgstr ""
+msgstr "QMCMD^hyökkää (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:803
 msgid "QMCMD^attacking, icon"
-msgstr ""
+msgstr "QMCMD^hyökkää, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:804
 msgid "QMCMD^killed flagcarrier (l:%y^7)"
-msgstr ""
+msgstr "QMCMD^lipunkantaja tapettu (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:804
 msgid "QMCMD^killed flagcarrier, icon"
-msgstr ""
+msgstr "QMCMD^lipunkantaja tapettu, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 #, c-format
 msgid "QMCMD^dropped flag (l:%d^7)"
-msgstr ""
+msgstr "QMCMD^lippu pudotettu (l:%d^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 msgid "QMCMD^dropped flag, icon"
-msgstr ""
+msgstr "QMCMD^lippu pudotettu, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:806
 msgid "QMCMD^drop weapon, icon"
-msgstr ""
+msgstr "QMCMD^pudota ase, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:806
 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
-msgstr ""
+msgstr "QMCMD^ase pudotettu %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:807
 msgid "QMCMD^drop flag/key, icon"
-msgstr ""
+msgstr "QMCMD^pudota lippu/avain, kuvake"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:807
 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
-msgstr ""
+msgstr "QMCMD^pudotettu lippu/avain %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:811
 msgid "QMCMD^Send private message to"
-msgstr ""
+msgstr "QMCMD^Lähetä yksityisviesti"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:813
 #: qcsrc/client/hud/panel/quickmenu.qc:848
 msgid "QMCMD^Settings"
-msgstr ""
+msgstr "QMCMD^Asetukset"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:814
 #: qcsrc/client/hud/panel/quickmenu.qc:821
 msgid "QMCMD^View/HUD settings"
-msgstr ""
+msgstr "QMCMD^Katso/HUD-asetukset"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:815
 msgid "QMCMD^3rd person view"
-msgstr ""
+msgstr "QMCMD^näkymä 3:ssa persoonassa"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^Player models like mine"
-msgstr ""
+msgstr "QMCMD^Pelaajamallit jotka vastaavat omaani"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^Names above players"
-msgstr ""
+msgstr "QMCMD^Nimet pelaajien yläpuolella"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:818
 msgid "QMCMD^Crosshair per weapon"
-msgstr ""
+msgstr "QMCMD^Tähtäin tietyn aseen suhteen"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:819
 msgid "QMCMD^FPS"
-msgstr ""
+msgstr "QMCMD^FPS-ruutunopeus"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:820
 msgid "QMCMD^Net graph"
-msgstr ""
+msgstr "QMCMD^Nettomallinnus"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:823
 #: qcsrc/client/hud/panel/quickmenu.qc:826
 msgid "QMCMD^Sound settings"
-msgstr ""
+msgstr "QMCMD^Ääniasetukset"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:824
 msgid "QMCMD^Hit sound"
-msgstr ""
+msgstr "QMCMD^Osumaääni"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:825
 msgid "QMCMD^Chat sound"
-msgstr ""
+msgstr "QMCMD^Chat-keskustelun ääni"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:830
 #: qcsrc/client/hud/panel/quickmenu.qc:834
 msgid "QMCMD^Spectator camera"
-msgstr ""
+msgstr "QMCMD^Katselijakamera"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:831
 msgid "QMCMD^1st person"
-msgstr ""
+msgstr "QMCMD^Ens1persoona"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:832
 msgid "QMCMD^3rd person around player"
-msgstr ""
+msgstr "QMCMD^3:mas persoona pelaajan ympärillä"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:833
 msgid "QMCMD^3rd person behind"
-msgstr ""
+msgstr "QMCMD^3:mas persoona takaa"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:839
 #: qcsrc/client/hud/panel/quickmenu.qc:844
 msgid "QMCMD^Observer camera"
-msgstr ""
+msgstr "QMCMD^Tarkkailijakamera"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:840
 msgid "QMCMD^Increase speed"
-msgstr ""
+msgstr "QMCMD^Korota nopeutta"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:841
 msgid "QMCMD^Decrease speed"
-msgstr ""
+msgstr "QMCMD^Vähennä nopeutta"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:842
 msgid "QMCMD^Wall collision off"
-msgstr ""
+msgstr "QMCMD^Seinätörmäys pois"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:843
 msgid "QMCMD^Wall collision on"
-msgstr ""
+msgstr "QMCMD^Seinätörmäys päälle"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:847
 msgid "QMCMD^Fullscreen"
-msgstr ""
+msgstr "QMCMD^Kokoruutu"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:850
 #: qcsrc/client/hud/panel/quickmenu.qc:860
 msgid "QMCMD^Call a vote"
-msgstr ""
+msgstr "QMCMD^Pyydä äänestystä"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:851
 msgid "QMCMD^Restart the map"
-msgstr ""
+msgstr "QMCMD^Uudelleenkäynnistä kartta"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:852
 msgid "QMCMD^End match"
-msgstr ""
+msgstr "QMCMD^Lopeta ottelu"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:855
 msgid "QMCMD^Reduce match time"
-msgstr ""
+msgstr "QMCMD^Vähennä otteluaikaa"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:856
 msgid "QMCMD^Extend match time"
-msgstr ""
+msgstr "QMCMD^Lisää otteluaikaa"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:859
 msgid "QMCMD^Shuffle teams"
-msgstr ""
+msgstr "QMCMD^Sekoita joukkueet"
 
 #: qcsrc/client/hud/panel/racetimer.qc:54
 #, c-format
 msgid " (-%dL)"
-msgstr ""
+msgstr " (-%dL)"
 
 #: qcsrc/client/hud/panel/racetimer.qc:59
 #, c-format
 msgid " (+%dL)"
-msgstr ""
+msgstr " (+%dL)"
 
 #: qcsrc/client/hud/panel/racetimer.qc:78
 msgid "Start line"
-msgstr ""
+msgstr "Aloituslinja"
 
 #: qcsrc/client/hud/panel/racetimer.qc:80
 #: qcsrc/client/hud/panel/racetimer.qc:84
@@ -537,62 +543,62 @@ msgstr "Maali"
 #: qcsrc/client/hud/panel/racetimer.qc:151
 #, c-format
 msgid "Intermediate %d"
-msgstr ""
+msgstr "Välimuoto %d"
 
 #: qcsrc/client/hud/panel/racetimer.qc:154
 #: qcsrc/client/hud/panel/racetimer.qc:201
 #: qcsrc/client/hud/panel/racetimer.qc:262
 #, c-format
 msgid "PENALTY: %.1f (%s)"
-msgstr ""
+msgstr "RANGAISTUS: %.1f (%s)"
 
 #: qcsrc/client/hud/panel/racetimer.qc:154 qcsrc/client/main.qc:1129
 msgid "missing a checkpoint"
-msgstr ""
+msgstr "tarkastuspiste sivuutettu"
 
 #: qcsrc/client/hud/panel/radar.qc:373
 msgid "Click to select teleport destination"
-msgstr ""
+msgstr "Napsauta valitaksesi kaukosiirron määränpään"
 
 #: qcsrc/client/hud/panel/radar.qc:377
 msgid "Click to select spawn location"
-msgstr ""
+msgstr "Napsauta valitaksesi saapumismääränpään"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:87
 msgid "Number of ball carrier kills"
-msgstr ""
+msgstr "Pallonkantajatapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:87
 msgid "SCO^bckills"
-msgstr ""
+msgstr "SCO^pktapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:88
 msgid "SCO^bctime"
-msgstr ""
+msgstr "SCO^pkajat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:88
 msgid "Total amount of time holding the ball in Keepaway"
-msgstr ""
+msgstr "Pallon hallussapidon yhteisaika Keepaway:ssa "
 
 #: qcsrc/client/hud/panel/scoreboard.qc:89
 msgid "How often a flag (CTF) or a key (KeyHunt) was captured"
-msgstr ""
+msgstr "Kuinka usein lippu (CTF) tai avain (KeyHunt) saatiin kaapattua"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:89
 msgid "SCO^caps"
-msgstr ""
+msgstr "SCO^kaappaukset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:90
 msgid "SCO^captime"
-msgstr ""
+msgstr "SCO^kaappausaika"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:90
 msgid "Time of fastest capture (CTF)"
-msgstr ""
+msgstr "Nopeimman kaappauksen aika (CTF)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:91
 msgid "Number of deaths"
-msgstr ""
+msgstr "Kuolemien määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:91
 msgid "SCO^deaths"
@@ -600,121 +606,121 @@ msgstr "SCO^kuolemaa"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:92
 msgid "Number of keys destroyed by pushing them into void"
-msgstr ""
+msgstr "Tuhottujen avainten määrä työntämällä ne hukkaan"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:92
 msgid "SCO^destroyed"
-msgstr ""
+msgstr "SCO^tuhotut"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:93
 msgid "SCO^damage"
-msgstr ""
+msgstr "SCO^vaurio"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:93
 msgid "The total damage done"
-msgstr ""
+msgstr "Tehtyjen tuhojen yhteismäärä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:94
 msgid "SCO^dmgtaken"
-msgstr ""
+msgstr "SCO^ttvastaanotot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:94
 msgid "The total damage taken"
-msgstr ""
+msgstr "Kärsityt tuhot kokonaisuudessaan"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:95
 msgid "Number of flag drops"
-msgstr ""
+msgstr "Lippupudotusten määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:95
 msgid "SCO^drops"
-msgstr ""
+msgstr "SCO^pudotukset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:96
 msgid "Player ELO"
-msgstr ""
+msgstr "Pelaaja ELO"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:96
 msgid "SCO^elo"
-msgstr ""
+msgstr "SCO^elo"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:97
 msgid "SCO^fastest"
-msgstr ""
+msgstr "SCO^nopein"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:97
 msgid "Time of fastest lap (Race/CTS)"
-msgstr ""
+msgstr "Nopeimman kierroksen aika (kilpa/CTS)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:98
 msgid "Number of faults committed"
-msgstr ""
+msgstr "Tehtyjen rikkomusten määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:98
 msgid "SCO^faults"
-msgstr ""
+msgstr "SCO^rikkeet"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:99
 msgid "Number of flag carrier kills"
-msgstr ""
+msgstr "Lipunkantajien tappomäärä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:99
 msgid "SCO^fckills"
-msgstr ""
+msgstr "SCO^lktapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:100
 msgid "FPS"
-msgstr ""
+msgstr "FPS-ruutunopeus"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:100
 msgid "SCO^fps"
-msgstr ""
+msgstr "SCO^fpsruutunopeus"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:101
 msgid "Number of kills minus suicides"
-msgstr ""
+msgstr "Tapot poislukien itsemurhat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:101
 msgid "SCO^frags"
-msgstr ""
+msgstr "SCO^tapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:102
 msgid "Number of goals scored"
-msgstr ""
+msgstr "Tehdyt maalit"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:102
 msgid "SCO^goals"
-msgstr ""
+msgstr "SCO^maalit"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:103
 msgid "Number of keys carrier kills"
-msgstr ""
+msgstr "Avaimenkantajatapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:103
 msgid "SCO^kckills"
-msgstr ""
+msgstr "SCO^aktapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:104
 msgid "SCO^k/d"
-msgstr ""
+msgstr "SCO^t/k"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:104
 #: qcsrc/client/hud/panel/scoreboard.qc:105
 #: qcsrc/client/hud/panel/scoreboard.qc:106
 msgid "The kill-death ratio"
-msgstr ""
+msgstr "Suhdeluku tapot-kuolemat "
 
 #: qcsrc/client/hud/panel/scoreboard.qc:105
 msgid "SCO^kdr"
-msgstr ""
+msgstr "SCO^tks"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:106
 msgid "SCO^kdratio"
-msgstr ""
+msgstr "SCO^tksuhdeluku"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:107
 msgid "Number of kills"
-msgstr ""
+msgstr "Tapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:107
 msgid "SCO^kills"
@@ -722,7 +728,7 @@ msgstr "SCO^tappoa"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:108
 msgid "Number of laps finished (Race/CTS)"
-msgstr ""
+msgstr "Loppuunsaatettujen kierrosten lukumäärä (kilpa/CTS)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:108
 msgid "SCO^laps"
@@ -730,24 +736,24 @@ msgstr "SCO^kierrosta"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:109
 msgid "Number of lives (LMS)"
-msgstr ""
+msgstr "Elämien määrä (LMS)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:109
 msgid "SCO^lives"
-msgstr ""
+msgstr "SCO^elämät"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:110
 msgid "Number of times a key was lost"
-msgstr ""
+msgstr "Montako kertaa avain menetettiin"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:110
 msgid "SCO^losses"
-msgstr ""
+msgstr "SCO^menetykset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:111
 #: qcsrc/client/hud/panel/scoreboard.qc:112
 msgid "Player name"
-msgstr ""
+msgstr "Pelaajan nimi"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:111
 msgid "SCO^name"
@@ -755,28 +761,29 @@ msgstr "SCO^nimi"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:112
 msgid "SCO^nick"
-msgstr ""
+msgstr "SCO^lempinimi"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:113
 msgid "Number of objectives destroyed"
-msgstr ""
+msgstr "Tavoitekohteita tuhottu"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:113
 msgid "SCO^objectives"
-msgstr ""
+msgstr "SCO^tavoitteet"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:114
 msgid ""
 "How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up"
 msgstr ""
+"Monastiko lippu (CTF) tai avain (KeyHunt) tai pallo (Keepaway) poimittiin"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:114
 msgid "SCO^pickups"
-msgstr ""
+msgstr "SCO^poiminnat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:115
 msgid "Ping time"
-msgstr ""
+msgstr "Ping-aika"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:115
 msgid "SCO^ping"
@@ -784,63 +791,63 @@ msgstr "Viive"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:116
 msgid "Packet loss"
-msgstr ""
+msgstr "Pakettirokotukset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:116
 msgid "SCO^pl"
-msgstr ""
+msgstr "SCO^pr"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:117
 msgid "Number of players pushed into void"
-msgstr ""
+msgstr "Montako pelaajaa työnnettiin hukkaan"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:117
 msgid "SCO^pushes"
-msgstr ""
+msgstr "SCO^työnnöt"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:118
 msgid "Player rank"
-msgstr ""
+msgstr "Pelaajan taso"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:118
 msgid "SCO^rank"
-msgstr ""
+msgstr "SCO^taso"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:119
 msgid "Number of flag returns"
-msgstr ""
+msgstr "Lipunpalautusten määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:119
 msgid "SCO^returns"
-msgstr ""
+msgstr "SCO^palautukset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:120
 msgid "Number of revivals"
-msgstr ""
+msgstr "Virkoamisten määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:120
 msgid "SCO^revivals"
-msgstr ""
+msgstr "SCO^virkoamiset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:121
 msgid "Number of rounds won"
-msgstr ""
+msgstr "Voitetut kierrokset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:121
 msgid "SCO^rounds won"
-msgstr ""
+msgstr "SCO^voitetut kierrokset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:122
 msgid "SCO^score"
-msgstr ""
+msgstr "SCO^pistemäärä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:122
 msgid "Total score"
-msgstr ""
+msgstr "Yhteispisteet"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:123
 msgid "Number of suicides"
-msgstr ""
+msgstr "Itsemurhat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:123
 msgid "SCO^suicides"
@@ -848,82 +855,88 @@ msgstr "SCO^itsemurhia"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:124
 msgid "Number of kills minus deaths"
-msgstr ""
+msgstr "Tapot poislukien kuolemat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:124
 msgid "SCO^sum"
-msgstr ""
+msgstr "SCO^määrä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:125
 msgid "Number of domination points taken (Domination)"
-msgstr ""
+msgstr "Otetut dominointipisteet (Domination)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:125
 msgid "SCO^takes"
-msgstr ""
+msgstr "SCO^otot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:126
 msgid "Number of teamkills"
-msgstr ""
+msgstr "Joukkuetapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:126
 msgid "SCO^teamkills"
-msgstr ""
+msgstr "SCO^joukkuetapot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:127
 msgid "Number of ticks (Domination)"
-msgstr ""
+msgstr "Tikkausten määrä (Domination)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:127
 msgid "SCO^ticks"
-msgstr ""
+msgstr "SCO^tikkaukset"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:128
 msgid "SCO^time"
-msgstr ""
+msgstr "SCO^aika"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:128
 msgid "Total time raced (Race/CTS)"
-msgstr ""
+msgstr "Kilvan kokonaisaika (kilpa/CTS)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:312
 msgid ""
 "You can modify the scoreboard using the ^2scoreboard_columns_set command."
-msgstr ""
+msgstr "Voit mukauttaa tulostaulua käyttäen ^2scoreboard_columns_set käskyä."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:313
 msgid "Usage:"
-msgstr ""
+msgstr "Käyttö:"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:315
 msgid "^2scoreboard_columns_set ^3field1 field2 ..."
-msgstr ""
+msgstr "^2scoreboard_columns_set ^3field1 field2 ..."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:316
 msgid ""
 "^2scoreboard_columns_set ^7without arguments reads the arguments from the "
 "cvar scoreboard_columns"
 msgstr ""
+"^2scoreboard_columns_set ^7ilman argumentteja otetaan argumentit cvar "
+"scoreboard_columns :sta"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:317
 msgid ""
 "  ^5Note: ^7scoreboard_columns_set without arguments is executed on every "
 "map start"
 msgstr ""
+"  ^5Huomautus: ^7scoreboard_columns_set ilman argumentteja ajetaan jokaisen "
+"kartan aloituksessa"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:318
 msgid ""
 "^2scoreboard_columns_set ^3expand_default ^7loads default layout and expands "
 "it into the cvar scoreboard_columns so you can edit it"
 msgstr ""
+"^2scoreboard_columns_set ^3expand_default ^7lataa vakioulkoasun ja laajentaa "
+"sen muotoon cvar scoreboard_columns jotta voit muokata sitä"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:319
 msgid "You can use a ^3|^7 to start the right-aligned fields."
-msgstr ""
+msgstr "Voit käyttää ^3|^7 aloittaaksesi oikealle tasatut kentät."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:320
 msgid "The following field names are recognized (case insensitive):"
-msgstr ""
+msgstr "Seuraavat kenttänimet tunnistetaan (ei vaatimusta kirjainkoolle):"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:326
 msgid ""
@@ -932,28 +945,41 @@ msgid ""
 "or in all but these game types. You can also specify 'all' as a\n"
 "field to show all fields available for the current game mode."
 msgstr ""
+"Kenttää ennen voit laittaa + tai - merkin, jota seuraa pilkuilla eritelty "
+"lista\n"
+"pelimuodoista, sitten kenoviiva, saadaksesi kentän näkymään vain näissä\n"
+"tai kaikissa näissä pelimuodoissa. Voit myöskin määrittää 'kaikki' "
+"kenttänä \n"
+"näyttääksesi kaikki tarjolla olevat kentät sen hetkiselle pelimuodolle. "
 
 #: qcsrc/client/hud/panel/scoreboard.qc:332
 msgid ""
 "The special game type names 'teams' and 'noteams' can be used to\n"
 "include/exclude ALL teams/noteams game modes."
 msgstr ""
+"Erikoispelimuotojen nimiä 'teams' ja 'noteams' voidaan käyttää\n"
+"sisällyttääksesi/poislukien KAIKKI teams/noteams pelimuodot."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:336
 msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
 msgstr ""
+"Esimerkki: scoreboard_columns_set nimi ping pl | +ctf/kenttä3 -dm/kenttä4"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:337
 msgid ""
 "will display name, ping and pl aligned to the left, and the fields\n"
 "right of the vertical bar aligned to the right."
 msgstr ""
+"näyttää nimen, pingin ja pl:n asemoituna vasemmalle, ja kentät\n"
+"pystysuorapalkista oikealla asemoituna oikealle."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:339
 msgid ""
 "'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
 "other gamemodes except DM."
 msgstr ""
+"'kenttä3' näytetään vain CTF:ssä, ja 'kenttä4' näytetään kaikissa\n"
+"muissa pelimuodoissa poislukien muoto DM."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:603
 #: qcsrc/client/hud/panel/scoreboard.qc:610
@@ -970,117 +996,117 @@ msgstr "N/A"
 #: qcsrc/client/hud/panel/scoreboard.qc:1188
 #, c-format
 msgid "Accuracy stats (average %d%%)"
-msgstr ""
+msgstr "Tarkkuustilastot (keskimäärin %d%%)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1336
 msgid "Map stats:"
-msgstr ""
+msgstr "Kartan tilastot:"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1366
 msgid "Monsters killed:"
-msgstr ""
+msgstr "Hirviöitä tapettu:"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1373
 msgid "Secrets found:"
-msgstr ""
+msgstr "Salaisuuksia löydettiin:"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1395
 msgid "Capture time rankings"
-msgstr ""
+msgstr "Kaappausten aikatasot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1395
 msgid "Rankings"
-msgstr ""
+msgstr "Rankkaustasot"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1613
 #, c-format
 msgid "^3%1.0f minutes"
-msgstr ""
+msgstr "^3%1.0f minuuttia"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1622
 #: qcsrc/client/hud/panel/scoreboard.qc:1629
 #, c-format
 msgid "^5%s %s"
-msgstr ""
+msgstr "^5%s %s"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1623
 #: qcsrc/client/hud/panel/scoreboard.qc:1630
 #: qcsrc/client/hud/panel/scoreboard.qc:1642
 #: qcsrc/client/hud/panel/scoreboard.qc:1649
 msgid "SCO^points"
-msgstr ""
+msgstr "SCO^pisteet"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1624
 #: qcsrc/client/hud/panel/scoreboard.qc:1631
 #: qcsrc/client/hud/panel/scoreboard.qc:1643
 #: qcsrc/client/hud/panel/scoreboard.qc:1650
 msgid "SCO^is beaten"
-msgstr ""
+msgstr "SCO^on päihitetty"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1641
 #: qcsrc/client/hud/panel/scoreboard.qc:1648
 #, c-format
 msgid "^2+%s %s"
-msgstr ""
+msgstr "^2+%s %s"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1659
 #, c-format
 msgid "^7Map: ^2%s"
-msgstr ""
+msgstr "^7Kartta: ^2%s"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1798
 #, c-format
 msgid "Speed award: %d%s ^7(%s^7)"
-msgstr ""
+msgstr "Nopeuspalkinto: %d%s ^7(%s^7)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1802
 #, c-format
 msgid "All-time fastest: %d%s ^7(%s^7)"
-msgstr ""
+msgstr "Kaikkien aikojen nopein: %d%s ^7(%s^7)"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1818
 #, c-format
 msgid "Spectators"
-msgstr ""
+msgstr "Katselijat"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1845
 #, c-format
 msgid "^1Respawning in ^3%s^1..."
-msgstr ""
+msgstr "^1Virkoaminen tapahtuu ^3%s^1..."
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1855
 #, c-format
 msgid "You are dead, wait ^3%s^7 before respawning"
-msgstr ""
+msgstr "Olet kuollut, odota ^3%s^7 ennen uudelleenvirkoamista"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1864
 #, c-format
 msgid "You are dead, press ^2%s^7 to respawn"
-msgstr ""
+msgstr "Olet kuollut, paina ^2%s^7 virotaksesi uudelleen"
 
 #: qcsrc/client/hud/panel/timer.qc:67
 msgid "WARMUP"
-msgstr ""
+msgstr "LÄMMITTELY"
 
 #: qcsrc/client/hud/panel/vote.qc:27
 msgid "^1You must answer before entering hud configure mode"
-msgstr ""
+msgstr "^1Sinun tulee vastata ennen sisäänkäyntiä hud-asetus tilaan"
 
 #: qcsrc/client/hud/panel/vote.qc:30
 msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats"
-msgstr ""
+msgstr "^2Nimi ^7tämän sijasta \"^1Nimetön pelaaja^7\" tilastoissa"
 
 #: qcsrc/client/hud/panel/vote.qc:116
 msgid "A vote has been called for:"
-msgstr ""
+msgstr "Äänestys on tullut tulokseen:"
 
 #: qcsrc/client/hud/panel/vote.qc:118
 msgid "Allow servers to store and display your name?"
-msgstr ""
+msgstr "Salli palvelimien tallentaa ja näyttää nimesi?"
 
 #: qcsrc/client/hud/panel/vote.qc:122
 msgid "^1Configure the HUD"
-msgstr ""
+msgstr "^1Määrittele HUD"
 
 #: qcsrc/client/hud/panel/vote.qc:126 qcsrc/menu/xonotic/dialog_firstrun.qc:82
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:18
@@ -1106,15 +1132,15 @@ msgstr "Ei"
 
 #: qcsrc/client/hud/panel/weapons.qc:546
 msgid "Out of ammo"
-msgstr ""
+msgstr "Ammukset loppu"
 
 #: qcsrc/client/hud/panel/weapons.qc:550
 msgid "Don't have"
-msgstr ""
+msgstr "Ei ole"
 
 #: qcsrc/client/hud/panel/weapons.qc:554
 msgid "Unavailable"
-msgstr ""
+msgstr "Ei saatavissa"
 
 #: qcsrc/client/main.qc:1027
 msgid " qu/s"
@@ -1134,12 +1160,12 @@ msgstr "mph"
 
 #: qcsrc/client/main.qc:1035
 msgid " knots"
-msgstr ""
+msgstr "solmut"
 
 #: qcsrc/client/main.qc:1282
 #, c-format
 msgid "%s (not bound)"
-msgstr ""
+msgstr "%s (ei sidottu)"
 
 #: qcsrc/client/mapvoting.qc:52
 msgid " (1 vote)"
@@ -1152,11 +1178,11 @@ msgstr "(%d ääntä)"
 
 #: qcsrc/client/mapvoting.qc:274
 msgid "Don't care"
-msgstr ""
+msgstr "Aivan sama"
 
 #: qcsrc/client/mapvoting.qc:375
 msgid "Decide the gametype"
-msgstr ""
+msgstr "Valitse pelitila"
 
 #: qcsrc/client/mapvoting.qc:375
 msgid "Vote for a map"
@@ -1170,120 +1196,123 @@ msgstr "%d sekuntia jäljellä"
 #: qcsrc/client/mapvoting.qc:505
 msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!"
 msgstr ""
+"mv_mapdownload: ^3Sinun ei ole tarkoitus käyttää tätä käskyä omin päin!"
 
 #: qcsrc/client/mapvoting.qc:515
 msgid "^1Error:^7 Couldn't find pak index."
-msgstr ""
+msgstr "^1Virhe:^7 Ei löytynyt: pak index."
 
 #: qcsrc/client/mapvoting.qc:524
 msgid "Requesting preview..."
-msgstr ""
+msgstr "Pyydetään esikatselua..."
 
 #: qcsrc/client/miscfunctions.qc:111
 msgid "Trying to remove a team which is not in the teamlist!"
-msgstr ""
+msgstr "Koetetaan poistaa joukkuetta joka ei ole joukkuelistassa!"
 
 #: qcsrc/client/view.qc:1518
 msgid "Nade timer"
-msgstr ""
+msgstr "Naattiajastin"
 
 #: qcsrc/client/view.qc:1523
 msgid "Capture progress"
-msgstr ""
+msgstr "Kaappauksen edistyminen"
 
 #: qcsrc/client/view.qc:1528
 msgid "Revival progress"
-msgstr ""
+msgstr "Elpymisen edistyminen"
 
 #: qcsrc/common/command/generic.qc:156
 msgid "error creating curl handle"
-msgstr ""
+msgstr "virhe luodessa: curl handle"
 
 #: qcsrc/common/command/generic.qc:412
 msgid "Notification restart command only works with cl_cmd and sv_cmd."
 msgstr ""
+"Ilmoituksen uudelleenkäynnistyskäsky toimii vain tämän kanssa cl_cmd and "
+"sv_cmd."
 
 #: qcsrc/common/gamemodes/gamemode/nexball/weapon.qh:7
 msgid "Ball Stealer"
-msgstr ""
+msgstr "Pallovaras"
 
 #: qcsrc/common/items/item/ammo.qh:66
 msgid "bullets"
-msgstr ""
+msgstr "luodit"
 
 #: qcsrc/common/items/item/ammo.qh:96
 msgid "cells"
-msgstr ""
+msgstr "kennot"
 
 #: qcsrc/common/items/item/ammo.qh:126
 msgid "plasma"
-msgstr ""
+msgstr "plasma"
 
 #: qcsrc/common/items/item/ammo.qh:156
 msgid "rockets"
-msgstr ""
+msgstr "raketit"
 
 #: qcsrc/common/items/item/ammo.qh:190
 msgid "shells"
-msgstr ""
+msgstr "ammukset"
 
 #: qcsrc/common/items/item/armor.qh:42
 msgid "Small armor"
-msgstr ""
+msgstr "Pieni panssari"
 
 #: qcsrc/common/items/item/armor.qh:80
 msgid "Medium armor"
-msgstr ""
+msgstr "Keskiluokan panssari"
 
 #: qcsrc/common/items/item/armor.qh:118 qcsrc/common/items/item/armor.qh:121
 msgid "Big armor"
-msgstr ""
+msgstr "Iso panssari"
 
 #: qcsrc/common/items/item/armor.qh:158 qcsrc/common/items/item/armor.qh:161
 msgid "Mega armor"
-msgstr ""
+msgstr "Mahtipanssari"
 
 #: qcsrc/common/items/item/health.qh:42
 msgid "Small health"
-msgstr ""
+msgstr "Pieni terveyspalautus"
 
 #: qcsrc/common/items/item/health.qh:80
 msgid "Medium health"
-msgstr ""
+msgstr "Keskiluokan terveyspalautus"
 
 #: qcsrc/common/items/item/health.qh:118 qcsrc/common/items/item/health.qh:121
 msgid "Big health"
-msgstr ""
+msgstr "Suuri terveyspalautus"
 
 #: qcsrc/common/items/item/health.qh:158 qcsrc/common/items/item/health.qh:161
 msgid "Mega health"
-msgstr ""
+msgstr "Mahtava terveyspalautus"
 
 #: qcsrc/common/items/item/jetpack.qh:38 qcsrc/common/items/item/jetpack.qh:41
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:213
 msgid "Jetpack"
-msgstr ""
+msgstr "Lentopakkaus"
 
 #: qcsrc/common/items/item/jetpack.qh:71
 msgid "fuel"
-msgstr ""
+msgstr "polttoaine"
 
 #: qcsrc/common/items/item/jetpack.qh:96
 msgid "Fuel regenerator"
-msgstr ""
+msgstr "Polttoaineen uusiovalmistin"
 
 #: qcsrc/common/items/item/jetpack.qh:99
 msgid "Fuel regen"
-msgstr ""
+msgstr "Polttoaineen uusvalmistin"
 
 #: qcsrc/common/items/item/powerup.qh:43 qcsrc/common/items/item/powerup.qh:46
 msgid "Strength"
-msgstr ""
+msgstr "Voima"
 
 #: qcsrc/common/items/item/powerup.qh:79 qcsrc/common/items/item/powerup.qh:82
 msgid "Shield"
-msgstr ""
+msgstr "Suoja"
 
 #: qcsrc/common/mapinfo.qc:626
 #, no-c-format
@@ -1299,7 +1328,7 @@ msgstr "Tapporaja:"
 #: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:333
 #: qcsrc/common/mapinfo.qh:528
 msgid "The amount of frags needed before the match will end"
-msgstr ""
+msgstr "Tarvittava tappojen määrä ennen ottelun päättymistä"
 
 #: qcsrc/common/mapinfo.qh:114
 msgid "Deathmatch"
@@ -1307,7 +1336,7 @@ msgstr "Mättö (Deathmatch)"
 
 #: qcsrc/common/mapinfo.qh:114
 msgid "Score as many frags as you can"
-msgstr ""
+msgstr "Tee niin monta tappoa kuin pystyt"
 
 #: qcsrc/common/mapinfo.qh:127
 msgid "Last Man Standing"
@@ -1315,7 +1344,7 @@ msgstr "Viimeiseen mieheen (Last Man Standing)"
 
 #: qcsrc/common/mapinfo.qh:127
 msgid "Survive and kill until the enemies have no lives left"
-msgstr ""
+msgstr "Selviydy ja tapa kunnes vihollisilla ei ole enää elämiä jäljellä"
 
 #: qcsrc/common/mapinfo.qh:136
 msgid "Lives:"
@@ -1327,7 +1356,7 @@ msgstr "Kilpailu (RACE)"
 
 #: qcsrc/common/mapinfo.qh:148
 msgid "Race against other players to the finish line"
-msgstr ""
+msgstr "Kisaa toisia pelaajia vastaan kohti maaliviivaa"
 
 #: qcsrc/common/mapinfo.qh:175
 msgid "Laps:"
@@ -1339,7 +1368,7 @@ msgstr "Kilpailu CTS (RACE CTS)"
 
 #: qcsrc/common/mapinfo.qh:188
 msgid "Race for fastest time."
-msgstr ""
+msgstr "Kisaa saavuttaaksesi nopeimman ajan."
 
 #: qcsrc/common/mapinfo.qh:205 qcsrc/common/mapinfo.qh:256
 #: qcsrc/common/mapinfo.qh:372 qcsrc/common/mapinfo.qh:415
@@ -1350,7 +1379,7 @@ msgstr "Pisteraja:"
 
 #: qcsrc/common/mapinfo.qh:218
 msgid "Help your team score the most frags against the enemy team"
-msgstr ""
+msgstr "Auta joukkuettasi tekemään eniten tappoja vihollisjoukkuetta vastaan"
 
 #: qcsrc/common/mapinfo.qh:218
 msgid "Team Deathmatch"
@@ -1359,7 +1388,7 @@ msgstr "Joukkuemättö (Team Deatchmatch)"
 #: qcsrc/common/mapinfo.qh:256 qcsrc/common/mapinfo.qh:372
 #: qcsrc/common/mapinfo.qh:415
 msgid "The amount of points needed before the match will end"
-msgstr ""
+msgstr "Tarvittava pistemäärä ennen kuin ottelu loppuu"
 
 #: qcsrc/common/mapinfo.qh:270
 msgid "Capture the Flag"
@@ -1370,6 +1399,8 @@ msgid ""
 "Find and bring the enemy flag to your base to capture it, defend your base "
 "from the other team"
 msgstr ""
+"Löydä ja toimita vihollisen lippu tukikohtaasi kaapataksesi sen, puolusta "
+"tukikohtaasi toiselta joukkueelta"
 
 #: qcsrc/common/mapinfo.qh:288
 msgid "Capture limit:"
@@ -1377,7 +1408,7 @@ msgstr "Lipunryöstöraja"
 
 #: qcsrc/common/mapinfo.qh:288
 msgid "The amount of captures needed before the match will end"
-msgstr ""
+msgstr "Tarvittava kaappausten määrä ennen kuin ottelu loppuu"
 
 #: qcsrc/common/mapinfo.qh:305
 msgid "Clan Arena"
@@ -1385,11 +1416,11 @@ msgstr "Klaaniareena (Clan Arena)"
 
 #: qcsrc/common/mapinfo.qh:305
 msgid "Kill all enemy teammates to win the round"
-msgstr ""
+msgstr "Tapa kaikki vihollisjoukkueen jäsenet voittaaksesi kierroksen"
 
 #: qcsrc/common/mapinfo.qh:349
 msgid "Capture and defend all the control points to win"
-msgstr ""
+msgstr "Valtaa kaikki hallintapisteet ja puolusta niitä voittaaksesi"
 
 #: qcsrc/common/mapinfo.qh:349
 msgid "Domination"
@@ -1397,7 +1428,7 @@ msgstr "Hallinta (Domination)"
 
 #: qcsrc/common/mapinfo.qh:387
 msgid "Gather all the keys to win the round"
-msgstr ""
+msgstr "Kerää kaikki avaimet voittaaksesi kierroksen"
 
 #: qcsrc/common/mapinfo.qh:387
 msgid "Key Hunt"
@@ -1412,10 +1443,12 @@ msgid ""
 "Destroy obstacles to find and destroy the enemy power core before time runs "
 "out"
 msgstr ""
+"Tuhoa esteet löytääksesi ja tuhotaksesi vihollisen ytimen ennen kuin aika "
+"loppuu"
 
 #: qcsrc/common/mapinfo.qh:451
 msgid "Capture control points to reach and destroy the enemy generator"
-msgstr ""
+msgstr "Valtaa hallintapisteet päästäksesi vihollisen generaattorille"
 
 #: qcsrc/common/mapinfo.qh:451
 msgid "Onslaught"
@@ -1427,7 +1460,7 @@ msgstr "Nexpallo (Nexball)"
 
 #: qcsrc/common/mapinfo.qh:473
 msgid "Shoot and kick the ball into the enemies goal, keep your goal clean"
-msgstr ""
+msgstr "Ammu ja potkaise pallo vihollisen maaliin, pidä oma maalisi puhtaana"
 
 #: qcsrc/common/mapinfo.qh:487
 msgid "Goals:"
@@ -1435,7 +1468,7 @@ msgstr "Maalit:"
 
 #: qcsrc/common/mapinfo.qh:487
 msgid "The amount of goals needed before the match will end"
-msgstr ""
+msgstr "Tarvittava maalimäärä ennen kuin ottelu loppuu"
 
 #: qcsrc/common/mapinfo.qh:500
 msgid "Freeze Tag"
@@ -1446,10 +1479,13 @@ msgid ""
 "Kill enemies to freeze them, stand next to frozen teammates to revive them; "
 "freeze all enemies to win"
 msgstr ""
+"Tapa viholliset heidät jäädyttääksesi, seiso jäädytettyjen "
+"joukkuekavereidesi vieressä elvyttääksesi heidät; jäädytä kaikki viholliset "
+"voittaaksesi"
 
 #: qcsrc/common/mapinfo.qh:544
 msgid "Hold the ball to get points for kills"
-msgstr ""
+msgstr "Pidä palloa saadaksesi tappopisteitä"
 
 #: qcsrc/common/mapinfo.qh:544
 msgid "Keepaway"
@@ -1457,23 +1493,24 @@ msgstr "Pakomatka (Keepaway)"
 
 #: qcsrc/common/mapinfo.qh:559
 msgid "Invasion"
-msgstr ""
+msgstr "Tunkeutuminen"
 
 #: qcsrc/common/mapinfo.qh:559
 msgid "Survive against waves of monsters"
-msgstr ""
+msgstr "Selviydy hirviöaaltoja vastaan"
 
 #: qcsrc/common/mapinfo.qh:589
 msgid "Duel"
-msgstr ""
+msgstr "Kaksintaistelu"
 
 #: qcsrc/common/mapinfo.qh:589
 msgid "Fight in a one versus one arena battle to decide the winner"
 msgstr ""
+"Taistele areenalla yksi-vastaan-yksi kamppailu voittajan selvittämiseksi"
 
 #: qcsrc/common/minigames/cl_minigames.qc:383
 msgid "It's your turn"
-msgstr ""
+msgstr "Sinun vuorosi"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:346
 #: qcsrc/menu/xonotic/dialog_quit.qh:6
@@ -1482,15 +1519,15 @@ msgstr "Lopeta"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:351
 msgid "Invite"
-msgstr ""
+msgstr "Kutsu"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:390
 msgid "Current Game"
-msgstr ""
+msgstr "Tämänhetkinen peli"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:415
 msgid "Exit Menu"
-msgstr ""
+msgstr "Poistu"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:427
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:16
@@ -1503,57 +1540,57 @@ msgstr "Liity"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:506
 msgid "Minigames"
-msgstr ""
+msgstr "Pienpelit"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:567
 msgid "Minigame message"
-msgstr ""
+msgstr "Pienpeliviesti"
 
 #: qcsrc/common/minigames/minigame/bd.qc:2
 msgid "Bulldozer"
-msgstr ""
+msgstr "Jyrä"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1092
 #: qcsrc/common/minigames/minigame/ps.qc:421
 #: qcsrc/common/minigames/minigame/ps.qc:427
 msgid "Game over!"
-msgstr ""
+msgstr "Peli on ohi!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1095
 msgid "Well done! Click 'Next Level' to continue"
-msgstr ""
+msgstr "Hienosti meni! Napsauta 'Seuraava Taso' jatkaaksesi"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1162
 msgid "Better luck next time!"
-msgstr ""
+msgstr "Paremmin ensi kerralla!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1167
 msgid "Tubular! Press \"Next Level\" to continue!"
-msgstr ""
+msgstr "Se meni putkeen! Paina \"Seuraava Taso\" jatkaaksesi!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1169
 msgid "Wicked! Press \"Next Level\" to continue!"
-msgstr ""
+msgstr "Päheetä! Paina \"Seuraava taso\" jatkaaksesi!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1173
 msgid "Press the space bar to change your currently selected tile"
-msgstr ""
+msgstr "Paina välilyöntiä vaihtaaksesi valitsemasi murikan"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1176
 msgid "Push the boulders onto the targets"
-msgstr ""
+msgstr "Työnnä lohkareet kohteita kohti"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1398
 msgid "Next Level"
-msgstr ""
+msgstr "Seuraava Taso"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1399
 msgid "Restart"
-msgstr ""
+msgstr "Aloita uudelleen"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1400
 msgid "Editor"
-msgstr ""
+msgstr "Muokkain"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1401
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:37
@@ -1562,7 +1599,7 @@ msgstr "Tallenna"
 
 #: qcsrc/common/minigames/minigame/c4.qc:2
 msgid "Connect Four"
-msgstr ""
+msgstr "Neljän suora"
 
 #: qcsrc/common/minigames/minigame/c4.qc:311
 #: qcsrc/common/minigames/minigame/c4.qc:317
@@ -1572,205 +1609,209 @@ msgstr ""
 #: qcsrc/common/minigames/minigame/pp.qc:368
 #, c-format
 msgid "%s^7 won the game!"
-msgstr ""
+msgstr "%s^7 voitti pelin!"
 
 #: qcsrc/common/minigames/minigame/c4.qc:373
 #: qcsrc/common/minigames/minigame/pp.qc:438
 #: qcsrc/common/minigames/minigame/ttt.qc:319
 msgid "Draw"
-msgstr ""
+msgstr "Tasapeli"
 
 #: qcsrc/common/minigames/minigame/c4.qc:378
 #: qcsrc/common/minigames/minigame/nmm.qc:606
 #: qcsrc/common/minigames/minigame/pp.qc:443
 #: qcsrc/common/minigames/minigame/ttt.qc:324
 msgid "You lost the game!"
-msgstr ""
+msgstr "Hävisit pelin!"
 
 #: qcsrc/common/minigames/minigame/c4.qc:379
 #: qcsrc/common/minigames/minigame/nmm.qc:607
 #: qcsrc/common/minigames/minigame/pp.qc:444
 #: qcsrc/common/minigames/minigame/ttt.qc:325
 msgid "You win!"
-msgstr ""
+msgstr "Voitto on sinun!"
 
 #: qcsrc/common/minigames/minigame/c4.qc:383
 #: qcsrc/common/minigames/minigame/nmm.qc:611
 #: qcsrc/common/minigames/minigame/pp.qc:455
 #: qcsrc/common/minigames/minigame/ttt.qc:336
 msgid "Wait for your opponent to make their move"
-msgstr ""
+msgstr "Odota että vastustajasi toteuttaa liikkeensä"
 
 #: qcsrc/common/minigames/minigame/c4.qc:386
 #: qcsrc/common/minigames/minigame/nmm.qc:613
 #: qcsrc/common/minigames/minigame/pp.qc:458
 #: qcsrc/common/minigames/minigame/ttt.qc:339
 msgid "Click on the game board to place your piece"
-msgstr ""
+msgstr "Napsauta pelilaudalla asettaaksesi nappulasi"
 
 #: qcsrc/common/minigames/minigame/nmm.qc:7
 msgid "Nine Men's Morris"
-msgstr ""
+msgstr "Mylly"
 
 #: qcsrc/common/minigames/minigame/nmm.qc:615
 msgid ""
 "You can select one of your pieces to move it in one of the surrounding places"
 msgstr ""
+"Voit valita nappuloistasi yhden siirtääksesi sen yhteen ympäröivistä "
+"paikoista"
 
 #: qcsrc/common/minigames/minigame/nmm.qc:617
 msgid "You can select one of your pieces to move it anywhere on the board"
 msgstr ""
+"Voit valita yhden nappuloistasi siirtääksesi sen laudalla mihin tahansa "
 
 #: qcsrc/common/minigames/minigame/nmm.qc:619
 msgid "You can take one of the opponent's pieces"
-msgstr ""
+msgstr "Voit syödä yhden vastustajasi nappuloista"
 
 #: qcsrc/common/minigames/minigame/pong.qc:2
 msgid "Pong"
-msgstr ""
+msgstr "Pong-mailapeli"
 
 #: qcsrc/common/minigames/minigame/pong.qc:589
 #: qcsrc/common/minigames/minigame/ttt.qc:299
 msgid "AI"
-msgstr ""
+msgstr "AI-tekoäly"
 
 #: qcsrc/common/minigames/minigame/pong.qc:606
 msgid "Press ^1Start Match^7 to start the match with the current players"
 msgstr ""
+"Paina ^1Aloita Ottelu^7 aloittaaksesi ottelun tämänhetkisillä pelaajilla"
 
 #: qcsrc/common/minigames/minigame/pong.qc:674
 msgid "Start Match"
-msgstr ""
+msgstr "Aloita Ottelu"
 
 #: qcsrc/common/minigames/minigame/pong.qc:675
 msgid "Add AI player"
-msgstr ""
+msgstr "Lisää AI-tekoälypelaajia"
 
 #: qcsrc/common/minigames/minigame/pong.qc:676
 msgid "Remove AI player"
-msgstr ""
+msgstr "Poista AI-tekoälypelaaja"
 
 #: qcsrc/common/minigames/minigame/pp.qc:2
 msgid "Push-Pull"
-msgstr ""
+msgstr "Työnnä-Vedä"
 
 #: qcsrc/common/minigames/minigame/pp.qc:443
 #: qcsrc/common/minigames/minigame/ttt.qc:324
 msgid "Select \"^1Next Match^7\" on the menu for a rematch!"
-msgstr ""
+msgstr "Valitse valikossa \"^1Seuraava Ottelu^7\" uusintaottelua varten!"
 
 #: qcsrc/common/minigames/minigame/pp.qc:444
 #: qcsrc/common/minigames/minigame/pp.qc:450
 #: qcsrc/common/minigames/minigame/ttt.qc:325
 #: qcsrc/common/minigames/minigame/ttt.qc:331
 msgid "Select \"^1Next Match^7\" on the menu to start a new match!"
-msgstr ""
+msgstr "Valitse valikossa \"^1Seuraava Ottelu^7\" aloittaaksesi uuden ottelun!"
 
 #: qcsrc/common/minigames/minigame/pp.qc:451
 #: qcsrc/common/minigames/minigame/ttt.qc:332
 msgid "Wait for your opponent to confirm the rematch"
-msgstr ""
+msgstr "Odota vastustajasi vahvistusta uusintaottelulle"
 
 #: qcsrc/common/minigames/minigame/pp.qc:581
 #: qcsrc/common/minigames/minigame/ttt.qc:664
 msgid "Next Match"
-msgstr ""
+msgstr "Seuraava Ottelu"
 
 #: qcsrc/common/minigames/minigame/ps.qc:2
 msgid "Peg Solitaire"
-msgstr ""
+msgstr "Lautapasianssi"
 
 #: qcsrc/common/minigames/minigame/ps.qc:414
 msgid "All pieces cleared!"
-msgstr ""
+msgstr "Kaikki nappulat poisputsattu!"
 
 #: qcsrc/common/minigames/minigame/ps.qc:416
 msgid "Remaining pieces:"
-msgstr ""
+msgstr "Jäljelläolevat nappulat:"
 
 #: qcsrc/common/minigames/minigame/ps.qc:481
 #, c-format
 msgid "Pieces left: %s"
-msgstr ""
+msgstr "Nappuloita jäljellä: %s"
 
 #: qcsrc/common/minigames/minigame/ps.qc:491
 msgid "No more valid moves"
-msgstr ""
+msgstr "Ei enempää kelvollisia siirtoja"
 
 #: qcsrc/common/minigames/minigame/ps.qc:494
 msgid "Well done, you win!"
-msgstr ""
+msgstr "Hienosti meni, voitto on sinun!"
 
 #: qcsrc/common/minigames/minigame/ps.qc:497
 msgid "Jump a piece over another to capture it"
-msgstr ""
+msgstr "Pompsauta nappula toisen päälle kaapataksesi sen"
 
 #: qcsrc/common/minigames/minigame/ttt.qc:2
 msgid "Tic Tac Toe"
-msgstr ""
+msgstr "Ristinolla"
 
 #: qcsrc/common/minigames/minigame/ttt.qc:665
 msgid "Single Player"
-msgstr ""
+msgstr "Yksinpeli"
 
 #: qcsrc/common/monsters/monster/mage.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:18
 msgid "Mage"
-msgstr ""
+msgstr "Velho"
 
 #: qcsrc/common/monsters/monster/mage.qh:29
 msgid "Mage spike"
-msgstr ""
+msgstr "Velhontähkä"
 
 #: qcsrc/common/monsters/monster/shambler.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:17
 msgid "Shambler"
-msgstr ""
+msgstr "Värisyttäjä"
 
 #: qcsrc/common/monsters/monster/spider.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:16
 msgid "Spider"
-msgstr ""
+msgstr "Hämähäkki"
 
 #: qcsrc/common/monsters/monster/spider.qh:28
 msgid "Spider attack"
-msgstr ""
+msgstr "Hämähäkin hyökkäys"
 
 #: qcsrc/common/monsters/monster/wyvern.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:19
 msgid "Wyvern"
-msgstr ""
+msgstr "Lohikäärme"
 
 #: qcsrc/common/monsters/monster/wyvern.qh:28
 msgid "Wyvern attack"
-msgstr ""
+msgstr "Lohikäärmeen hyökkäys"
 
 #: qcsrc/common/monsters/monster/zombie.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:15
 msgid "Zombie"
-msgstr ""
+msgstr "Zombie"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:15
 msgid "Ammo"
-msgstr ""
+msgstr "Ammukset"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:24
 msgid "Resistance"
-msgstr ""
+msgstr "Vastarinta"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:33
 #: qcsrc/common/mutators/mutator/instagib/items.qh:126
 #: qcsrc/common/mutators/mutator/instagib/items.qh:129
 msgid "Speed"
-msgstr ""
+msgstr "Nopeus"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:43
 msgid "Medic"
-msgstr ""
+msgstr "Lääkintämies"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:54
 msgid "Bash"
-msgstr ""
+msgstr "Murjaisu"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:62
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:83
@@ -1780,67 +1821,67 @@ msgstr "Vampyyri"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:70
 msgid "Disability"
-msgstr ""
+msgstr "Vammaisuus"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:78
 msgid "Vengeance"
-msgstr ""
+msgstr "Kosto"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:86
 msgid "Jump"
-msgstr ""
+msgstr "Hyppy"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:95
 msgid "Invisible"
-msgstr ""
+msgstr "Näkymätön"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:104
 msgid "Inferno"
-msgstr ""
+msgstr "Pätsi"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:112
 msgid "Swapper"
-msgstr ""
+msgstr "Vaihdokki"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:120
 msgid "Magnet"
-msgstr ""
+msgstr "Magneetti"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:128
 msgid "Luck"
-msgstr ""
+msgstr "Lykästys"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:136
 msgid "Flight"
-msgstr ""
+msgstr "Lento"
 
 #: qcsrc/common/mutators/mutator/buffs/buffs.qh:7
 msgid "Buff"
-msgstr ""
+msgstr "Puhvi"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:8
 msgid "Damage text"
-msgstr ""
+msgstr "Vahinkoteksti"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:18
 msgid "Draw damage numbers"
-msgstr ""
+msgstr "Piirrä vahinkonumerot"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:20
 msgid "Font size minimum:"
-msgstr ""
+msgstr "Pienin kirjasinkoko:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:25
 msgid "Font size maximum:"
-msgstr ""
+msgstr "Suurin kirjasinkoko:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:30
 msgid "Accumulate range:"
-msgstr ""
+msgstr "Kerääntymän kantama:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:38
 msgid "Lifetime:"
-msgstr ""
+msgstr "Elinaika:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:43
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:53
@@ -1854,164 +1895,164 @@ msgstr "Väri:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:50
 msgid "Draw damage numbers for friendly fire"
-msgstr ""
+msgstr "Piirrä vahinkonumerot koskien vahinkolaukauksia"
 
 #: qcsrc/common/mutators/mutator/instagib/items.qh:33
 msgid "Vaporizer ammo"
-msgstr ""
+msgstr "Höyrystimen ammukset"
 
 #: qcsrc/common/mutators/mutator/instagib/items.qh:59
 #: qcsrc/common/mutators/mutator/instagib/items.qh:62
 msgid "Extra life"
-msgstr ""
+msgstr "Lisäelämä"
 
 #: qcsrc/common/mutators/mutator/instagib/items.qh:91
 #: qcsrc/common/mutators/mutator/instagib/items.qh:94
 msgid "Invisibility"
-msgstr ""
+msgstr "Näkymättömyys"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:18
 msgid "Napalm grenade"
-msgstr ""
+msgstr "Napalmikranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:26
 msgid "Ice grenade"
-msgstr ""
+msgstr "Jääkranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:34
 msgid "Translocate grenade"
-msgstr ""
+msgstr "Erikohdistuskranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:42
 msgid "Spawn grenade"
-msgstr ""
+msgstr "Uudelleensyntykranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:50
 msgid "Heal grenade"
-msgstr ""
+msgstr "Toipumiskranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:58
 msgid "Monster grenade"
-msgstr ""
+msgstr "Hirviökranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:66
 msgid "Entrap grenade"
-msgstr ""
+msgstr "Ansakranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.inc:74
 msgid "Veil grenade"
-msgstr ""
+msgstr "Huntukranaatti"
 
 #: qcsrc/common/mutators/mutator/nades/nades.qh:34
 msgid "Grenade"
-msgstr ""
+msgstr "Kranaatti"
 
 #: qcsrc/common/mutators/mutator/overkill/okhmg.qh:20
 msgid "Overkill Heavy Machine Gun"
-msgstr ""
+msgstr "Ylimalkaallinen raskaskonepistooli"
 
 #: qcsrc/common/mutators/mutator/overkill/okmachinegun.qh:18
 msgid "Overkill MachineGun"
-msgstr ""
+msgstr "Ylimalkaallinen konepistooli"
 
 #: qcsrc/common/mutators/mutator/overkill/oknex.qh:19
 msgid "Overkill Nex"
-msgstr ""
+msgstr "Ylimalkaallinen Nex"
 
 #: qcsrc/common/mutators/mutator/overkill/okrpc.qh:20
 msgid "Overkill Rocket Propelled Chainsaw"
-msgstr ""
+msgstr "Ylimalkaallinen rakettikäyttöinen moottorisaha"
 
 #: qcsrc/common/mutators/mutator/overkill/okshotgun.qh:18
 msgid "Overkill Shotgun"
-msgstr ""
+msgstr "Ylimalkaallinen haulikko"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:3
 msgid "Waypoint"
-msgstr ""
+msgstr "Välietappi"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:4
 msgid "Help me!"
-msgstr ""
+msgstr "Auta minua!"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:5
 msgid "Here"
-msgstr ""
+msgstr "Tässä"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:6
 msgid "DANGER"
-msgstr ""
+msgstr "VAARA"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:8
 msgid "Frozen!"
-msgstr ""
+msgstr "Jäässä!"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:10
 msgid "Item"
-msgstr ""
+msgstr "Esine"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:12
 msgid "Checkpoint"
-msgstr ""
+msgstr "Jatkopiste"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:13
 #: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
 msgid "Finish"
-msgstr ""
+msgstr "Loppu"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:14
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:15
 #: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
 msgid "Start"
-msgstr ""
+msgstr "Alku"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:17
 msgid "Defend"
-msgstr ""
+msgstr "Puolusta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:18
 msgid "Destroy"
-msgstr ""
+msgstr "Tuhoa"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:19
 msgid "Push"
-msgstr ""
+msgstr "Työnnä"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:21
 msgid "Flag carrier"
-msgstr ""
+msgstr "Lipunkantaja"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:22
 msgid "Enemy carrier"
-msgstr ""
+msgstr "Viholliskantaja"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:23
 msgid "Dropped flag"
-msgstr ""
+msgstr "Pudotettu lippu"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:24
 msgid "White base"
-msgstr ""
+msgstr "Valkoinen tukikohta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:25
 msgid "Red base"
-msgstr ""
+msgstr "Punainen tukikohta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:26
 msgid "Blue base"
-msgstr ""
+msgstr "Sininen tukikohta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:27
 msgid "Yellow base"
-msgstr ""
+msgstr "Keltainen tukikohta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:28
 msgid "Pink base"
-msgstr ""
+msgstr "Vaaleanpunainen tukikohta"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:29
 msgid "Return flag here"
-msgstr ""
+msgstr "Palauta lippu tänne"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:31
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:32
@@ -2022,11 +2063,11 @@ msgstr ""
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:52
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:53
 msgid "Control point"
-msgstr ""
+msgstr "Hallintapiste"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:37
 msgid "Dropped key"
-msgstr ""
+msgstr "Pudotettu avain"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:38
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:40
@@ -2034,54 +2075,54 @@ msgstr ""
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:42
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:43
 msgid "Key carrier"
-msgstr ""
+msgstr "Avaimenkantaja"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:39
 msgid "Run here"
-msgstr ""
+msgstr "Juokse tänne"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:45
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:48
 msgid "Ball"
-msgstr ""
+msgstr "Pallo"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:46
 msgid "Ball carrier"
-msgstr ""
+msgstr "Pallonkantaja"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:49
 msgid "Goal"
-msgstr ""
+msgstr "Maali"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:54
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:55
 msgid "Generator"
-msgstr ""
+msgstr "Generaattori"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:57
 msgid "Weapon"
-msgstr ""
+msgstr "Ase"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:59
 msgid "Monster"
-msgstr ""
+msgstr "Hirviö"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:61
 msgid "Vehicle"
-msgstr ""
+msgstr "Ajoneuvo"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:62
 msgid "Intruder!"
-msgstr ""
+msgstr "Tunkeutuja!"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:64
 msgid "Tagged"
-msgstr ""
+msgstr "Korvamerkitty"
 
 #: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:695
 #, c-format
 msgid "%s needing help!"
-msgstr ""
+msgstr "%s avuntarpeessa!"
 
 #: qcsrc/common/net_notice.qc:90
 msgid "^1Server notices:"
@@ -2090,11 +2131,12 @@ msgstr "^1Palvelimen ilmoitukset:"
 #: qcsrc/common/notifications/all.inc:239
 msgid "^F4NOTE: ^BGSpectator chat is not sent to players during the match"
 msgstr ""
+"^F4HUOMAUTUS: ^BGKatselijakeskustelua ei lähetetä pelaajille ottelun aikana"
 
 #: qcsrc/common/notifications/all.inc:241
 #, c-format
 msgid "^BG%s^BG captured the ^TC^TT^BG flag"
-msgstr ""
+msgstr "^BG%s^BG kaappasi ^TC^TT^BG lipun"
 
 #: qcsrc/common/notifications/all.inc:242
 #, c-format
@@ -2102,16 +2144,18 @@ msgid ""
 "^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG"
 "%s^BG's previous record of ^F2%s^BG seconds"
 msgstr ""
+"^BG%s^BG kaappasi ^TC^TT^BG lipun ^F1%s^BG sekunnissa, rikkoen ^BG%s^BG's "
+"edellisen ennätyksen ^F2%s^BG sekuntia"
 
 #: qcsrc/common/notifications/all.inc:243
 #, c-format
 msgid "^BG%s^BG captured the flag"
-msgstr ""
+msgstr "^BG%s^BG kaappasi lipun"
 
 #: qcsrc/common/notifications/all.inc:244
 #, c-format
 msgid "^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"
-msgstr ""
+msgstr "^BG%s^BG kaappasi ^TC^TT^BG lipun ^F1%s^BG sekunnissa"
 
 #: qcsrc/common/notifications/all.inc:245
 #, c-format
@@ -2119,40 +2163,43 @@ msgid ""
 "^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break "
 "^BG%s^BG's previous record of ^F1%s^BG seconds"
 msgstr ""
+"^BG%s^BG kaappasi ^TC^TT^BG lipun ^F2%s^BG sekunnissa, onnistumatta "
+"rikkomaan ^BG%s^BG's edellistä ennätystä ^F1%s^BG sekuntia"
 
 #: qcsrc/common/notifications/all.inc:246
 msgid "^BGThe ^TC^TT^BG flag was returned to base by its owner"
-msgstr ""
+msgstr "^BGThe ^TC^TT^BG lippu palautettiin tukikohtaan omistajansa toimesta"
 
 #: qcsrc/common/notifications/all.inc:247
 msgid "^BGThe flag was returned by its owner"
-msgstr ""
+msgstr "^BGLippu palautettiin omistajansa toimesta"
 
 #: qcsrc/common/notifications/all.inc:248
 msgid "^BGThe ^TC^TT^BG flag was destroyed and returned to base"
-msgstr ""
+msgstr "^BGLippu ^TC^TT^BG tuhottiin ja palautettiin tukikohtaan"
 
 #: qcsrc/common/notifications/all.inc:249
 msgid "^BGThe flag was destroyed and returned to base"
-msgstr ""
+msgstr "^BGLippu tuhottiin ja palautettiin tukikohtaan"
 
 #: qcsrc/common/notifications/all.inc:250
 msgid "^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"
-msgstr ""
+msgstr "^BGLippu ^TC^TT^BG pudotettiin tukikohtaan palauttaen itse itsensä"
 
 #: qcsrc/common/notifications/all.inc:251
 msgid "^BGThe flag was dropped in the base and returned itself"
-msgstr ""
+msgstr "^BGLippu pudotettiin tukikohtaan palauttaen itsensä"
 
 #: qcsrc/common/notifications/all.inc:252
 msgid ""
 "^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to "
 "base"
 msgstr ""
+"^BGLippu ^TC^TT^BG putosi johonkin saavuttamattomiin tukikohtapalautukselle"
 
 #: qcsrc/common/notifications/all.inc:253
 msgid "^BGThe flag fell somewhere it couldn't be reached and returned to base"
-msgstr ""
+msgstr "^BGLippu putosi johonkin saavuttamattomiin tukikohtapalautukselle"
 
 #: qcsrc/common/notifications/all.inc:254
 #, c-format
@@ -2160,825 +2207,844 @@ msgid ""
 "^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned "
 "itself"
 msgstr ""
+"^BGLippu ^TC^TT^BG muuttui malttamattomaksi ^F1%.2f^BG sekunnin jälkeen "
+"palauttaen itsensä"
 
 #: qcsrc/common/notifications/all.inc:255
 #, c-format
 msgid ""
 "^BGThe flag became impatient after ^F1%.2f^BG seconds and returned itself"
 msgstr ""
+"^BGLippu muuttui malttamattomaksi ^F1%.2f^BG sekunnin jälkeen palauttaen "
+"itsensä"
 
 #: qcsrc/common/notifications/all.inc:256
 msgid "^BGThe ^TC^TT^BG flag has returned to the base"
-msgstr ""
+msgstr "^BGLippu ^TC^TT^BG palautui tukikohtaan"
 
 #: qcsrc/common/notifications/all.inc:257
 msgid "^BGThe flag has returned to the base"
-msgstr ""
+msgstr "^BGLippu palautui tukikohtaan"
 
 #: qcsrc/common/notifications/all.inc:258
 #, c-format
 msgid "^BG%s^BG lost the ^TC^TT^BG flag"
-msgstr ""
+msgstr "^BG%s^BG menetti ^TC^TT^BG lipun"
 
 #: qcsrc/common/notifications/all.inc:259
 #, c-format
 msgid "^BG%s^BG lost the flag"
-msgstr ""
+msgstr "^BG%s^BG menetti lipun"
 
 #: qcsrc/common/notifications/all.inc:260
 #, c-format
 msgid "^BG%s^BG got the ^TC^TT^BG flag"
-msgstr ""
+msgstr "^BG%s^BG sai ^TC^TT^BG lipun"
 
 #: qcsrc/common/notifications/all.inc:261
 #, c-format
 msgid "^BG%s^BG got the flag"
-msgstr ""
+msgstr "^BG%s^BG sai lipun"
 
 #: qcsrc/common/notifications/all.inc:262
 #: qcsrc/common/notifications/all.inc:263
 #, c-format
 msgid "^BG%s^BG returned the ^TC^TT^BG flag"
-msgstr ""
+msgstr "^BG%s^BG palautti ^TC^TT^BG lipun"
 
 #: qcsrc/common/notifications/all.inc:265
 #: qcsrc/common/notifications/all.inc:557
 #, c-format
 msgid "^F2Throwing coin... Result: %s^F2!"
-msgstr ""
+msgstr "^F2Kolikonheitto... Tulos: %s^F2!"
 
 #: qcsrc/common/notifications/all.inc:267
 msgid "^BGYou don't have any fuel for the ^F1Jetpack"
-msgstr ""
+msgstr "^BGSinulla ei ole polttoainetta ^F1Lentopakkaukseen"
 
 #: qcsrc/common/notifications/all.inc:269
 msgid "^F2You lack a UID, superspec options will not be saved/restored"
-msgstr ""
+msgstr "^F2Sinulta uupuu UID, superspes valintoja ei tallenneta/palauteta"
 
 #: qcsrc/common/notifications/all.inc:271
 msgid "^F1Round already started, you will join the game in the next round"
-msgstr ""
+msgstr "^F1Kierros on jo alkanut, pääset mukaan ensi kierrokselle"
 
 #: qcsrc/common/notifications/all.inc:272
 msgid "^F2You will spectate in the next round"
-msgstr ""
+msgstr "^F2Seuraava kierros menee sinun osaltasi katsellessa"
 
 #: qcsrc/common/notifications/all.inc:274
 #, c-format
 msgid "^BG%s%s^K1 was killed by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 tapettiin ^BG%s^K1's ^BG%s^K1 puhvilla ^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:274
 #, c-format
 msgid "^BG%s%s^K1 was scored against by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 otettiin pisteitä pois ^BG%s^K1's ^BG%s^K1 puhvilla ^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:275
 #, c-format
 msgid "^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 lopetettiin epärehellisesti ja syyllinen oli ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:276
 #, c-format
 msgid "^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 hukutettiin syyllisen ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:277
 #, c-format
 msgid "^BG%s%s^K1 was grounded by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 palautettiin maanpinnalle syyllisen ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:278
 #, c-format
 msgid "^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s"
 msgstr ""
+"^BG%s%s^K1 tunsi mitä se on kun tekee poppaa ^BG%s^K1's tulen polttaessa^K1%s"
+"%s"
 
 #: qcsrc/common/notifications/all.inc:278
 #, c-format
 msgid "^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"
 msgstr ""
+"^BG%s%s^K1 poltettiin täydeksi paistiksi syyllisen ollessa ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:279
 #, c-format
 msgid "^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 päätyi murkinaksi kokin ollessa ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:280
 #, c-format
 msgid "^BG%s%s^K1 was pushed in front of a monster by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 työnnettiin hirviön eteen ja tekijä oli ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:281
 #, c-format
 msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 posautettiin taivaan tuuliin ^BG%s^K1's Naatilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:282
 #, c-format
 msgid "^BG%s%s^K1 got too close to a napalm explosion%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle napalmiräjähdystä%s%s"
 
 #: qcsrc/common/notifications/all.inc:282
 #, c-format
 msgid "^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"
 msgstr ""
+"^BG%s%s^K1 poltettiin kuoliaaksi ^BG%s^K1's Napalminaatin toimesta %s%s"
 
 #: qcsrc/common/notifications/all.inc:283
 #, c-format
 msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 posautettiin ^BG%s^K1's Jäänaatin toimesta %s%s"
 
 #: qcsrc/common/notifications/all.inc:284
 #, c-format
 msgid "^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 jäätyi pakastelihaksi ^BG%s^K1's Jäänaatin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:285
 #, c-format
 msgid "^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ei tervehtynyt ^BG%s^K1's Terveysnaatista %s%s"
 
 #: qcsrc/common/notifications/all.inc:286
 #, c-format
 msgid "^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"
 msgstr ""
+"^BG%s%s^K1 ammuttiin planeettaa kiertävälle radalle syyllisen ollen ^BG"
+"%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:287
 #, c-format
 msgid "^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 limakyllästettiin ja tekijä oli ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:288
 #, c-format
 msgid "^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 säilöttiin säilöjän ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:289
 #, c-format
 msgid "^BG%s%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s"
 msgstr ""
+"^BG%s%s^K1 yritti koijailla ^BG%s^K1's etäsiirtomääränpään tonteilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:289
 #, c-format
 msgid "^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 etäsurmattiin syyllisen ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:290
 #, c-format
 msgid "^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 menehtyi onnettomuudessa ja kanssansa oli ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:291
 #, c-format
 msgid ""
 "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Bumblebee exploded%s%s"
 msgstr ""
+"^BG%s%s^K1 otti osumaa töräyksestä kun ^BG%s^K1'n Bumblebee räjähti%s%s"
 
 #: qcsrc/common/notifications/all.inc:292
 #, c-format
 msgid "^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s"
 msgstr ""
+"^BG%s%s^K1 koki kauniit valot joita ^BG%s^K1'n Bumblebee-ase tuottaa%s%s"
 
 #: qcsrc/common/notifications/all.inc:293
 #, c-format
 msgid "^BG%s%s^K1 was crushed by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 tuli rusennetuksi syypään ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:294
 #, c-format
 msgid "^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 sai maistaa sirpalepommia ^BG%s^K1'n Raptorin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:295
 #, c-format
 msgid "^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ei voinut vastustaa ^BG%s^K1'n purppurakimpaleita%s%s"
 
 #: qcsrc/common/notifications/all.inc:296
 #, c-format
 msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Raptor exploded%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 otti osumaa töräyksestä kun ^BG%s^K1'n Raptor räjähti%s%s"
 
 #: qcsrc/common/notifications/all.inc:297
 #, c-format
 msgid ""
 "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Spiderbot exploded%s%s"
 msgstr ""
+"^BG%s%s^K1 otti osumaa töräyksestä kun ^BG%s^K1'n Hämisbotti räjähti%s%s"
 
 #: qcsrc/common/notifications/all.inc:298
 #, c-format
 msgid "^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 silppuuntui ^BG%s^K1'n Hämisbotin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:299
 #, c-format
 msgid "^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 posautettiin päreiksi ^BG%s^K1'n Hämisbotin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:300
 #, c-format
 msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 otti osumaa töräyksestä kun ^BG%s^K1'n Kilpuri räjähti%s%s"
 
 #: qcsrc/common/notifications/all.inc:301
 #, c-format
 msgid "^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 iskettiin alas ^BG%s^K1'n Kilpurin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:302
 #, c-format
 msgid "^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ei löytänyt suojaa ^BG%s^K1'n Kilpurilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:303
 #, c-format
 msgid "^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s"
 msgstr ""
+"^BG%s%s^K1 linkaistiin tuskien taipaleelle syyllisen ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:305
 #, c-format
 msgid "^BG%s^K1 was moved into the %s%s"
-msgstr ""
+msgstr "^BG%s^K1 siirrettiin tänne %s%s"
 
 #: qcsrc/common/notifications/all.inc:306
 #, c-format
 msgid "^BG%s^K1 became enemies with the Lord of Teamplay%s%s"
-msgstr ""
+msgstr "^BG%s^K1 tuli viholliseksi Joukkuepelin Isännän kanssa %s%s"
 
 #: qcsrc/common/notifications/all.inc:307
 #, c-format
 msgid "^BG%s^K1 thought they found a nice camping ground%s%s"
-msgstr ""
+msgstr "^BG%s^K1 luulivat löytäneensä lokoisan retkeilyalueen%s%s"
 
 #: qcsrc/common/notifications/all.inc:308
 #, c-format
 msgid "^BG%s^K1 unfairly eliminated themself%s%s"
-msgstr ""
+msgstr "^BG%s^K1 lopettivat itsensä epäreilusti%s%s"
 
 #: qcsrc/common/notifications/all.inc:310
 #, c-format
 msgid "^BG%s^K1 couldn't catch their breath%s%s"
-msgstr ""
+msgstr "^BG%s^K1 eivät saaneet henkeä%s%s"
 
 #: qcsrc/common/notifications/all.inc:310
 #, c-format
 msgid "^BG%s^K1 was in the water for too long%s%s"
-msgstr ""
+msgstr "^BG%s^K1 oli vedessä liian pitkään%s%s"
 
 #: qcsrc/common/notifications/all.inc:311
 #, c-format
 msgid "^BG%s^K1 hit the ground with a bit too much force%s%s"
-msgstr ""
+msgstr "^BG%s^K1 kohtasi maankamaran hiukan liiallisella voimalla%s%s"
 
 #: qcsrc/common/notifications/all.inc:311
 #, c-format
 msgid "^BG%s^K1 hit the ground with a crunch%s%s"
-msgstr ""
+msgstr "^BG%s^K1 kohtasi maankamaran kanssa niin että narskui%s%s"
 
 #: qcsrc/common/notifications/all.inc:312
 #, c-format
 msgid "^BG%s^K1 became a bit too crispy%s%s"
-msgstr ""
+msgstr "^BG%s^K1 muuttui hiukan liian rapeaksi%s%s"
 
 #: qcsrc/common/notifications/all.inc:312
 #, c-format
 msgid "^BG%s^K1 felt a little hot%s%s"
-msgstr ""
+msgstr "^BG%s^K1 tunsi pientä kuumotusta%s%s"
 
 #: qcsrc/common/notifications/all.inc:313
 #, c-format
 msgid "^BG%s^K1 died%s%s"
-msgstr ""
+msgstr "^BG%s^K1 delasi%s%s"
 
 #: qcsrc/common/notifications/all.inc:314
 #, c-format
 msgid "^BG%s^K1 found a hot place%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ja kuumat paikat%s%s"
 
 #: qcsrc/common/notifications/all.inc:314
 #, c-format
 msgid "^BG%s^K1 turned into hot slag%s%s"
-msgstr ""
+msgstr "^BG%s^K1 muuntui kuumaksi kuonaksi%s%s"
 
 #: qcsrc/common/notifications/all.inc:315
 #, c-format
 msgid "^BG%s^K1 was exploded by a Mage%s%s"
-msgstr ""
+msgstr "^BG%s^K1 joutui Velhon räjäyttämäksi%s%s"
 
 #: qcsrc/common/notifications/all.inc:316
 #, c-format
 msgid "^BG%s^K1's innards became outwards by a Shambler%s%s"
-msgstr ""
+msgstr "^BG%s^K1'n sisimmät tulivat ulos Värisyttäjän toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:317
 #, c-format
 msgid "^BG%s^K1 was smashed by a Shambler%s%s"
-msgstr ""
+msgstr "^BG%s^K1 murskattiin Värisyttäjän toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:318
 #, c-format
 msgid "^BG%s^K1 was zapped to death by a Shambler%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai kuolettavan sähköiskun Värisyttäjän toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:319
 #, c-format
 msgid "^BG%s^K1 was bitten by a Spider%s%s"
-msgstr ""
+msgstr "^BG%s^K1 purtiin Hämähäkin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:320
 #, c-format
 msgid "^BG%s^K1 was fireballed by a Wyvern%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai Lohikäärmeen tulipallon kohtalokseen%s%s"
 
 #: qcsrc/common/notifications/all.inc:321
 #, c-format
 msgid "^BG%s^K1 joins the Zombies%s%s"
-msgstr ""
+msgstr "^BG%s^K1 liittyi eläviin kuolleisiin%s%s"
 
 #: qcsrc/common/notifications/all.inc:322
 #, c-format
 msgid "^BG%s^K1 was given kung fu lessons by a Zombie%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai kung fu -oppia Zombielta%s%s"
 
 #: qcsrc/common/notifications/all.inc:323
 #: qcsrc/common/notifications/all.inc:325
 #, c-format
 msgid "^BG%s^K1 mastered the art of self-nading%s%s"
 msgstr ""
+"^BG%s^K1 saavutti mestarillisuuden itsenaatittamisen jalossa taidossa%s%s"
 
 #: qcsrc/common/notifications/all.inc:324
 #, c-format
 msgid ""
 "^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s"
-msgstr ""
+msgstr "^BG%s^K1 päätti katsoa napalmiräjäytyksensä tulokset%s%s"
 
 #: qcsrc/common/notifications/all.inc:324
 #, c-format
 msgid "^BG%s^K1 was burned to death by their own Napalm Nade%s%s"
-msgstr ""
+msgstr "^BG%s^K1 paloi poroksi omien Napalminaattiensa ansiosta%s%s"
 
 #: qcsrc/common/notifications/all.inc:326
 #, c-format
 msgid "^BG%s^K1 felt a little chilly%s%s"
-msgstr ""
+msgstr "^BG%s^K1 tunsi pientä kylmetystä%s%s"
 
 #: qcsrc/common/notifications/all.inc:326
 #, c-format
 msgid "^BG%s^K1 was frozen to death by their own Ice Nade%s%s"
-msgstr ""
+msgstr "^BG%s^K1 jäätyi kuoliaaksi omien Jäänaattiensa takia%s%s"
 
 #: qcsrc/common/notifications/all.inc:327
 #, c-format
 msgid "^BG%s^K1's Healing Nade didn't quite heal them%s%s"
-msgstr ""
+msgstr "^BG%s^K1'n Terveysnaatti ei heitä aivan tervehdyttänyt%s%s"
 
 #: qcsrc/common/notifications/all.inc:328
 #, c-format
 msgid "^BG%s^K1 died%s%s. What's the point of living without ammo?"
-msgstr ""
+msgstr "^BG%s^K1 kuoli%s%s. Onko elämällä jokin tarkoitus ilman ammuksia?"
 
 #: qcsrc/common/notifications/all.inc:328
 #, c-format
 msgid "^BG%s^K1 ran out of ammo%s%s"
-msgstr ""
+msgstr "^BG%s^K1 huomasi ammustensa loppuneen%s%s"
 
 #: qcsrc/common/notifications/all.inc:329
 #, c-format
 msgid "^BG%s^K1 rotted away%s%s"
-msgstr ""
+msgstr "^BG%s^K1 mätäni pois%s%s"
 
 #: qcsrc/common/notifications/all.inc:330
 #, c-format
 msgid "^BG%s^K1 became a shooting star%s%s"
-msgstr ""
+msgstr "^BG%s^K1 muuttui tähdenlennoksi%s%s"
 
 #: qcsrc/common/notifications/all.inc:331
 #, c-format
 msgid "^BG%s^K1 was slimed%s%s"
-msgstr ""
+msgstr "^BG%s^K1 kuorrutettiin limalla%s%s"
 
 #: qcsrc/common/notifications/all.inc:332
 #, c-format
 msgid "^BG%s^K1 couldn't take it anymore%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai tarpeekseen%s%s"
 
 #: qcsrc/common/notifications/all.inc:333
 #, c-format
 msgid "^BG%s^K1 is now preserved for centuries to come%s%s"
-msgstr ""
+msgstr "^BG%s^K1 on nyt säilötty tuleville sukupolville%s%s"
 
 #: qcsrc/common/notifications/all.inc:334
 #, c-format
 msgid "^BG%s^K1 switched to the %s%s"
-msgstr ""
+msgstr "^BG%s^K1 vaihtoi tähän %s%s"
 
 #: qcsrc/common/notifications/all.inc:335
 #, c-format
 msgid "^BG%s^K1 died in an accident%s%s"
-msgstr ""
+msgstr "^BG%s^K1 menehtyi onnettomuudessa%s%s"
 
 #: qcsrc/common/notifications/all.inc:336
 #, c-format
 msgid "^BG%s^K1 ran into a turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 porhalsi tykkitorniin%s%s"
 
 #: qcsrc/common/notifications/all.inc:337
 #, c-format
 msgid "^BG%s^K1 was blasted away by an eWheel turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 töräytettiin taivaan tuuliin eWheel-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:338
 #, c-format
 msgid "^BG%s^K1 got caught up in the FLAC turret fire%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa FLAC-tykkitornin tulesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:339
 #, c-format
 msgid "^BG%s^K1 was blasted away by a Hellion turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 töräytettiin taivaan tuuliin Hellion-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:340
 #, c-format
 msgid "^BG%s^K1 could not hide from the Hunter turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ei kyennyt piiloutumaan Hunter-tykkitornilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:341
 #, c-format
 msgid "^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ammuttiin seulaksi Machinegun-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:342
 #, c-format
 msgid "^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 muuntui kyteviksi viipaleiksi MLRS-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:343
 #, c-format
 msgid "^BG%s^K1 was phased out by a turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 poistettiin tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:344
 #, c-format
 msgid "^BG%s^K1 got served some superheated plasma from a turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai tykkitornin tarjoamaa äärikuumennettua plasmaa %s%s"
 
 #: qcsrc/common/notifications/all.inc:345
 #, c-format
 msgid "^BG%s^K1 was electrocuted by a Tesla turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai shokkihoitoa Tesla-tykkitornilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:346
 #, c-format
 msgid "^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 sai tuta lyijyn arvon Walker-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:347
 #, c-format
 msgid "^BG%s^K1 was impaled by a Walker turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 seivästettiin Walker-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:348
 #, c-format
 msgid "^BG%s^K1 was blasted away by a Walker turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 posautettiin taivaan tuuliin Walker-tykkitornin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:349
 #, c-format
 msgid "^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa Bumblebee:n töräyksestä%s%s"
 
 #: qcsrc/common/notifications/all.inc:350
 #, c-format
 msgid "^BG%s^K1 was crushed by a vehicle%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ajautui ajoneuvon murskaamaksi%s%s"
 
 #: qcsrc/common/notifications/all.inc:351
 #, c-format
 msgid "^BG%s^K1 was caught in a Raptor cluster bomb%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa Raptor-sirpalepommista%s%s"
 
 #: qcsrc/common/notifications/all.inc:352
 #, c-format
 msgid "^BG%s^K1 got caught in the blast of a Raptor explosion%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa Raptor:in töräyksestä%s%s"
 
 #: qcsrc/common/notifications/all.inc:353
 #, c-format
 msgid "^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa Hämisbot:in räjähdyksen töräyksestä%s%s"
 
 #: qcsrc/common/notifications/all.inc:354
 #, c-format
 msgid "^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s"
-msgstr ""
+msgstr "^BG%s^K1 posautettiin palasiksi Hämisbot:in raketin toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:355
 #, c-format
 msgid "^BG%s^K1 got caught in the blast of a Racer explosion%s%s"
-msgstr ""
+msgstr "^BG%s^K1 otti osumaa Kilpurin räjähdyksestä%s%s"
 
 #: qcsrc/common/notifications/all.inc:356
 #, c-format
 msgid "^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ei löytänyt suojaa Kilpurin raketin edessä%s%s"
 
 #: qcsrc/common/notifications/all.inc:359
 #, c-format
 msgid "^BG%s^K1 was betrayed by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s^K1 petettiin ja syyllinen on ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:361
 #, c-format
 msgid "^BG%s^BG%s^BG (%s %s every %s seconds)"
-msgstr ""
+msgstr "^BG%s^BG%s^BG (%s %s joka %s sekunti)"
 
 #: qcsrc/common/notifications/all.inc:363
 #, c-format
 msgid "^BG%s^K1 was frozen by ^BG%s"
-msgstr ""
+msgstr "^BG%s^K1 jäädytettiin ja pakkasukkona toimi ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:364
 #, c-format
 msgid "^BG%s^K3 was revived by ^BG%s"
-msgstr ""
+msgstr "^BG%s^K3 elvytettiin ja auttaja oli ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:365
 #, c-format
 msgid "^BG%s^K3 was revived by falling"
-msgstr ""
+msgstr "^BG%s^K3 elvytettiin kaatumalla"
 
 #: qcsrc/common/notifications/all.inc:366
 #, c-format
 msgid "^BG%s^K3 was revived by their Nade explosion"
-msgstr ""
+msgstr "^BG%s^K3 elvytettiin heidän Naattiräjähdyksellään"
 
 #: qcsrc/common/notifications/all.inc:367
 #, c-format
 msgid "^BG%s^K3 was automatically revived after %s second(s)"
-msgstr ""
+msgstr "^BG%s^K3 elvytettiin automaattisesti %s sekunnin (sekuntien) kuluttua"
 
 #: qcsrc/common/notifications/all.inc:368
 #, c-format
 msgid "^BG%s^K1 froze themself"
-msgstr ""
+msgstr "^BG%s^K1 jäädyttivät itsensä"
 
 #: qcsrc/common/notifications/all.inc:370
 #: qcsrc/common/notifications/all.inc:688
 msgid "^TC^TT^BG team wins the round"
-msgstr ""
+msgstr "^TC^TT^BG joukkue voitti kierroksen"
 
 #: qcsrc/common/notifications/all.inc:371
 #: qcsrc/common/notifications/all.inc:689
 #, c-format
 msgid "^BG%s^BG wins the round"
-msgstr ""
+msgstr "^BG%s^BG voitti kierroksen"
 
 #: qcsrc/common/notifications/all.inc:372
 #: qcsrc/common/notifications/all.inc:552
 msgid "^BGRound tied"
-msgstr ""
+msgstr "^BGKierros päättyi tasapeliin"
 
 #: qcsrc/common/notifications/all.inc:373
 #: qcsrc/common/notifications/all.inc:553
 msgid "^BGRound over, there's no winner"
-msgstr ""
+msgstr "^BGKierros ohi, ei voittajaa"
 
 #: qcsrc/common/notifications/all.inc:375
 #, c-format
 msgid "^BGGodmode saved you %s units of damage, cheater!"
-msgstr ""
+msgstr "^BGJumaltila pelasti sinut %s yksikköä vahinkoa, huiputtaja!"
 
 #: qcsrc/common/notifications/all.inc:377
 #, c-format
 msgid "^BG%s^BG got the %s^BG buff!"
-msgstr ""
+msgstr "^BG%s^BG sai %s^BG puhvin!"
 
 #: qcsrc/common/notifications/all.inc:378
 #, c-format
 msgid "^BG%s^BG lost the %s^BG buff!"
-msgstr ""
+msgstr "^BG%s^BG menetti %s^BG puhvin!"
 
 #: qcsrc/common/notifications/all.inc:379
 #: qcsrc/common/notifications/all.inc:696
 #, c-format
 msgid "^BGYou dropped the %s^BG buff!"
-msgstr ""
+msgstr "^BGSinä pudotit %s^BG puhvin!"
 
 #: qcsrc/common/notifications/all.inc:380
 #: qcsrc/common/notifications/all.inc:697
 #, c-format
 msgid "^BGYou got the %s^BG buff!"
-msgstr ""
+msgstr "^BGSinulla on %s^BG puhvi!"
 
 #: qcsrc/common/notifications/all.inc:382
 #: qcsrc/common/notifications/all.inc:700
 #, c-format
 msgid "^BGYou do not have the ^F1%s"
-msgstr ""
+msgstr "^BGSinulla ei ole ^F1%s"
 
 #: qcsrc/common/notifications/all.inc:383
 #: qcsrc/common/notifications/all.inc:701
 #, c-format
 msgid "^BGYou dropped the ^F1%s^BG%s"
-msgstr ""
+msgstr "^BGSinä pudotit ^F1%s^BG%s"
 
 #: qcsrc/common/notifications/all.inc:384
 #: qcsrc/common/notifications/all.inc:702
 #, c-format
 msgid "^BGYou got the ^F1%s"
-msgstr ""
+msgstr "^BGSinulla on ^F1%s"
 
 #: qcsrc/common/notifications/all.inc:385
 #: qcsrc/common/notifications/all.inc:703
 #, c-format
 msgid "^BGYou don't have enough ammo for the ^F1%s"
-msgstr ""
+msgstr "^BGSinulla ei ole tarpeeksi ammuksia tähän ^F1%s"
 
 #: qcsrc/common/notifications/all.inc:386
 #: qcsrc/common/notifications/all.inc:704
 #, c-format
 msgid "^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"
 msgstr ""
+"^F1%s %s^BG on kykenemätön tulittamaan, mutta sen ^F1%s^BG kykenee siihen"
 
 #: qcsrc/common/notifications/all.inc:387
 #: qcsrc/common/notifications/all.inc:705
 #, c-format
 msgid "^F1%s^BG is ^F4not available^BG on this map"
-msgstr ""
+msgstr "^F1%s^BG ei ^F4ole saatavissa^BG tässä kartassa"
 
 #: qcsrc/common/notifications/all.inc:389
 #, c-format
 msgid "^BG%s^BG is connecting..."
-msgstr ""
+msgstr "^BG%s^BG yhdistää..."
 
 #: qcsrc/common/notifications/all.inc:390
 #, c-format
 msgid "^BG%s^F3 connected"
-msgstr ""
+msgstr "^BG%s^F3 yhdistetty"
 
 #: qcsrc/common/notifications/all.inc:391
 #, c-format
 msgid "^BG%s^F3 is now playing"
-msgstr ""
+msgstr "^BG%s^F3 on nyt pelaamassa"
 
 #: qcsrc/common/notifications/all.inc:392
 #, c-format
 msgid "^BG%s^F3 is now playing on the ^TC^TT team"
-msgstr ""
+msgstr "^BG%s^F3 pelaa nyt ^TC^TT joukkueessa"
 
 #: qcsrc/common/notifications/all.inc:394
 #: qcsrc/common/notifications/all.inc:710
 #, c-format
 msgid "^BG%s^BG has dropped the ball!"
-msgstr ""
+msgstr "^BG%s^BG on pudottanut pallon!"
 
 #: qcsrc/common/notifications/all.inc:395
 #: qcsrc/common/notifications/all.inc:711
 #, c-format
 msgid "^BG%s^BG has picked up the ball!"
-msgstr ""
+msgstr "^BG%s^BG on poiminut pallon!"
 
 #: qcsrc/common/notifications/all.inc:397
 #, c-format
 msgid "^BG%s^BG captured the keys for the ^TC^TT team"
-msgstr ""
+msgstr "^BG%s^BG kaappasi avaimet ^TC^TT joukkueelle"
 
 #: qcsrc/common/notifications/all.inc:398
 #, c-format
 msgid "^BG%s^BG dropped the ^TC^TT Key"
-msgstr ""
+msgstr "^BG%s^BG pudotti ^TC^TT Avaimen"
 
 #: qcsrc/common/notifications/all.inc:399
 #, c-format
 msgid "^BG%s^BG lost the ^TC^TT Key"
-msgstr ""
+msgstr "^BG%s^BG menetti ^TC^TT Avaimen"
 
 #: qcsrc/common/notifications/all.inc:400
 #, c-format
 msgid "^BG%s^BG pushed %s^BG causing the ^TC^TT Key ^BGdestruction"
-msgstr ""
+msgstr "^BG%s^BG työnsi %s^BG aiheuttaen ^TC^TT Avaimen ^BGtuhoutumisen"
 
 #: qcsrc/common/notifications/all.inc:401
 #, c-format
 msgid "^BG%s^BG destroyed the ^TC^TT Key"
-msgstr ""
+msgstr "^BG%s^BG tuhosi ^TC^TT Avaimen"
 
 #: qcsrc/common/notifications/all.inc:402
 #, c-format
 msgid "^BG%s^BG picked up the ^TC^TT Key"
-msgstr ""
+msgstr "^BG%s^BG poimi ^TC^TT Avaimen"
 
 #: qcsrc/common/notifications/all.inc:404
 #, c-format
 msgid "^BG%s^F3 forfeited"
-msgstr ""
+msgstr "^BG%s^F3 luovutti"
 
 #: qcsrc/common/notifications/all.inc:405
 #, c-format
 msgid "^BG%s^F3 has no more lives left"
-msgstr ""
+msgstr "^BG%s^F3 on menettänyt kaikki elämänsä"
 
 #: qcsrc/common/notifications/all.inc:407
 msgid "^BGMonsters are currently disabled"
-msgstr ""
+msgstr "^BGHirviöt ovat tällä hetkellä otettu pelistä pois"
 
 #: qcsrc/common/notifications/all.inc:409
 msgid "^BGThe ^TC^TT^BG team held the ball for too long"
-msgstr ""
+msgstr "^BGJoukkue ^TC^TT^BG piti palloa hallussa liian pitkään "
 
 #: qcsrc/common/notifications/all.inc:411
 #, c-format
 msgid "^BG%s^BG captured %s^BG control point"
-msgstr ""
+msgstr "^BG%s^BG kaappasi %s^BG hallintapisteen"
 
 #: qcsrc/common/notifications/all.inc:412
 #, c-format
 msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s"
-msgstr ""
+msgstr "^TC^TT^BG joukkueen %s^BG hallintapiste on tuhottu täten %s"
 
 #: qcsrc/common/notifications/all.inc:413
 msgid "^TC^TT^BG generator has been destroyed"
-msgstr ""
+msgstr "^TC^TT^BG generaattori on tuhottu"
 
 #: qcsrc/common/notifications/all.inc:414
 msgid "^TC^TT^BG generator spontaneously combusted due to overtime!"
-msgstr ""
+msgstr "^TC^TT^BG generaattori syttyi oma-aloitteisesti yliajan johdosta!"
 
 #: qcsrc/common/notifications/all.inc:416
 #, c-format
 msgid "^BG%s^K1 picked up Invisibility"
-msgstr ""
+msgstr "^BG%s^K1 poimi Näkymättömyyden"
 
 #: qcsrc/common/notifications/all.inc:417
 #, c-format
 msgid "^BG%s^K1 picked up Shield"
-msgstr ""
+msgstr "^BG%s^K1 poimi Suojan"
 
 #: qcsrc/common/notifications/all.inc:418
 #, c-format
 msgid "^BG%s^K1 picked up Speed"
-msgstr ""
+msgstr "^BG%s^K1 keräsi Nopeutta"
 
 #: qcsrc/common/notifications/all.inc:419
 #, c-format
 msgid "^BG%s^K1 picked up Strength"
-msgstr ""
+msgstr "^BG%s^K1 keräsi Vahvennusta"
 
 #: qcsrc/common/notifications/all.inc:421
 #, c-format
 msgid "^BG%s^F3 disconnected"
-msgstr ""
+msgstr "^BG%s^F3 yhteys katkesi"
 
 #: qcsrc/common/notifications/all.inc:422
 #, c-format
 msgid "^BG%s^F3 was kicked for idling"
-msgstr ""
+msgstr "^BG%s^F3 potkaistiin joutilaisuuden takia"
 
 #: qcsrc/common/notifications/all.inc:423
 msgid ""
 "^F2You were kicked from the server because you are a spectator and "
 "spectators aren't allowed at the moment."
 msgstr ""
+"^F2Sinut potkaistiin palvelimelta koska olet katsoja ja katsojat eivät ole "
+"sallittuja tällä hetkellä."
 
 #: qcsrc/common/notifications/all.inc:424
 #, c-format
 msgid "^BG%s^F3 was kicked for excessive teamkilling"
-msgstr ""
+msgstr "^BG%s^F3 potkaistiin jatkuvien oman joukkueen jäsenten tappamisesta"
 
 #: qcsrc/common/notifications/all.inc:425
 #, c-format
 msgid "^BG%s^F3 is now spectating"
-msgstr ""
+msgstr "^BG%s^F3 katselee "
 
 #: qcsrc/common/notifications/all.inc:427
 #, c-format
 msgid "^BG%s^BG has abandoned the race"
-msgstr ""
+msgstr "^BG%s^BG hylkäsi kilvan"
 
 #: qcsrc/common/notifications/all.inc:428
 #, c-format
 msgid "^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"
-msgstr ""
+msgstr "^BG%s^BG eivät kyenneet rikkomaan %s%s^BG sijoitusennätystä %s%s %s"
 
 #: qcsrc/common/notifications/all.inc:429
 #, c-format
 msgid "^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"
-msgstr ""
+msgstr "^BG%s^BG ei kyennyt rikkomaan %s%s^BG sijoitusennätystään %s%s%s"
 
 #: qcsrc/common/notifications/all.inc:430
 #, c-format
 msgid "^BG%s^BG has finished the race"
-msgstr ""
+msgstr "^BG%s^BG sai kisan päätökseen"
 
 #: qcsrc/common/notifications/all.inc:431
 #, c-format
 msgid "^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"
-msgstr ""
+msgstr "^BG%s^BG rikkoi %s^BG's %s%s^BG sijoitusennätyksen ajassa %s%s %s"
 
 #: qcsrc/common/notifications/all.inc:432
 #, c-format
 msgid "^BG%s^BG improved their %s%s^BG place record with %s%s %s"
-msgstr ""
+msgstr "^BG%s^BG paransivat %s%s^BG sijoitusennätystään %s%s %s"
 
 #: qcsrc/common/notifications/all.inc:433
 #, c-format
@@ -2986,6 +3052,8 @@ msgid ""
 "^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID "
 "and will be lost."
 msgstr ""
+"^BG%s^BG laittoi tiskiin uuden ennätyksen ^F2%s^BG, mutta valitettavasti UID "
+"uupuu joten se hukataan."
 
 #: qcsrc/common/notifications/all.inc:434
 #, c-format
@@ -2993,11 +3061,13 @@ msgid ""
 "^BG%s^BG scored a new record with ^F2%s^BG, but is anonymous and will be "
 "lost."
 msgstr ""
+"^BG%s^BG laittoi tiskiin uuden ennätyksen ^F2%s^BG, mutta ollen anonyymi, se "
+"hukataan."
 
 #: qcsrc/common/notifications/all.inc:435
 #, c-format
 msgid "^BG%s^BG set the %s%s^BG place record with %s%s"
-msgstr ""
+msgstr "^BG%s^BG pisti %s%s^BG sijoitusennätyksen %s%s"
 
 #: qcsrc/common/notifications/all.inc:437
 #, c-format
@@ -3005,10 +3075,12 @@ msgid ""
 "^F4You have been invited by ^BG%s^F4 to join their game of ^F2%s^F4 "
 "(^F1%s^F4)"
 msgstr ""
+"^F4Sinut kutsuttiin ^BG%s^F4 :n toimesta liittymään peliinsä  ^F2%s^F4 "
+"(^F1%s^F4)"
 
 #: qcsrc/common/notifications/all.inc:439
 msgid "^TC^TT ^BGteam scores!"
-msgstr ""
+msgstr "^TC^TT ^BGjoukkue maalaa!"
 
 #: qcsrc/common/notifications/all.inc:441
 #, c-format
@@ -3016,19 +3088,21 @@ msgid ""
 "^F2You have to become a player within the next %s, otherwise you will be "
 "kicked, because spectating isn't allowed at this time!"
 msgstr ""
+"^F2Sinun täytyy alkaa pelaamaan ajan %ssisällä, muutoin sinut potkaistaan "
+"ulos koska katseleminen ei ole sallittua tällä kertaa!"
 
 #: qcsrc/common/notifications/all.inc:443
 #, c-format
 msgid "^BG%s^K1 picked up a Superweapon"
-msgstr ""
+msgstr "^BG%s^K1 poimi Mahtiaseen"
 
 #: qcsrc/common/notifications/all.inc:445
 msgid "^BGYou cannot change to a larger team"
-msgstr ""
+msgstr "^BGEt voi vaihtaa isompaan joukkueeseen"
 
 #: qcsrc/common/notifications/all.inc:446
 msgid "^BGYou are not allowed to change teams"
-msgstr ""
+msgstr "^BGJoukkueiden vaihtaminen ei ole sallittua"
 
 #: qcsrc/common/notifications/all.inc:448
 #, c-format
@@ -3036,12 +3110,16 @@ msgid ""
 "^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have "
 "^F2Xonotic %s"
 msgstr ""
+"^F4NOTE: ^BGPalvelin ajaa ^F1Xonotic:in %s (beta-versiota)^BG, sinulla on "
+"^F2Xonotic %s"
 
 #: qcsrc/common/notifications/all.inc:449
 #, c-format
 msgid ""
 "^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"
 msgstr ""
+"^F4NOTE: ^BGPalvelin ajaa ^F1Xonotic:in versiota %s^BG, sinulla on "
+"^F2Xonotic %s"
 
 #: qcsrc/common/notifications/all.inc:450
 #, c-format
@@ -3049,221 +3127,236 @@ msgid ""
 "^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get "
 "the update from ^F3http://www.xonotic.org/^BG!"
 msgstr ""
+"^F4HUOMAUTUS: ^F1Xonotic %s^BG on julkaistu, ja sinulla on edelleen "
+"^F2Xonotic %s^BG - hae päivitys osoitteesta ^F3http://www.xonotic.org/^BG!"
 
 #: qcsrc/common/notifications/all.inc:452
 #, c-format
 msgid "^F3SVQC Build information: ^F4%s"
-msgstr ""
+msgstr "^F3SVQC Kokooman tiedot: ^F4%s"
 
 #: qcsrc/common/notifications/all.inc:454
 #, c-format
 msgid ""
 "^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"
 msgstr ""
+"^BG%s%s^K1 kuoli syyn ollen ^BG%s^K1 on mahtava soittamaan @!#%%'n Haitaria%s"
+"%s"
 
 #: qcsrc/common/notifications/all.inc:455
 #, c-format
 msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"
-msgstr ""
+msgstr "^BG%s^K1 koki korvien vihlontaa @!#%% Haitarin takia%s%s"
 
 #: qcsrc/common/notifications/all.inc:456
 #, c-format
 msgid "^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 sai shokkihoitoa ^BG%s^K1'n Arc:in toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:457
 #, c-format
 msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Arc bolts%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 joutui läjäytetyksi ^BG%s^K1'n Arc-salamoista%s%s"
 
 #: qcsrc/common/notifications/all.inc:458
 #, c-format
 msgid "^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ammuttiin kuoliaaksi ^BG%s^K1'n Läjäyttimellä%s%s"
 
 #: qcsrc/common/notifications/all.inc:459
 #, c-format
 msgid "^BG%s^K1 shot themself to hell with their Blaster%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ampuivat itsensä hornan tuuttiin Läjäyttimillään%s%s"
 
 #: qcsrc/common/notifications/all.inc:460
 #, c-format
 msgid "^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 sai tuntea vahvaa vetoa ^BG%s^K1'n Crylink:in toimesta%s%s"
 
 #: qcsrc/common/notifications/all.inc:461
 #, c-format
 msgid "^BG%s^K1 felt the strong pull of their Crylink%s%s"
-msgstr ""
+msgstr "^BG%s^K1 saivat tuntea vahvaa vetoa Crylink:eistään%s%s"
 
 #: qcsrc/common/notifications/all.inc:462
 #, c-format
 msgid "^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 söi ^BG%s^K1'n raketin%s%s"
 
 #: qcsrc/common/notifications/all.inc:463
 #, c-format
 msgid "^BG%s%s^K1 got too close to ^BG%s^K1's rocket%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle ^BG%s^K1'n rakettia%s%s"
 
 #: qcsrc/common/notifications/all.inc:464
 #, c-format
 msgid "^BG%s^K1 blew themself up with their Devastator%s%s"
-msgstr ""
+msgstr "^BG%s^K1 räjäyttivät itsensä ilmavoimiin Devastator:illaan%s%s"
 
 #: qcsrc/common/notifications/all.inc:465
 #, c-format
 msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 päätyi läjäytetyksi ^BG%s^K1'n Sähkösalaman voimasta%s%s"
 
 #: qcsrc/common/notifications/all.inc:466
 #, c-format
 msgid "^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"
 msgstr ""
+"^BG%s%s^K1 tunsi sähköä ilmassa ^BG%s^K1'n Sähköyhdistelmän voimasta%s%s"
 
 #: qcsrc/common/notifications/all.inc:467
 #, c-format
 msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle ^BG%s^K1'n Sähköpalloa%s%s"
 
 #: qcsrc/common/notifications/all.inc:468
 #, c-format
 msgid "^BG%s^K1 played with Electro bolts%s%s"
-msgstr ""
+msgstr "^BG%s^K1 leikki Sähkösalamoilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:469
 #, c-format
 msgid "^BG%s^K1 could not remember where they put their Electro orb%s%s"
-msgstr ""
+msgstr "^BG%s^K1 unohtivat mihin olivat Sähköpallonsa laittaneet%s%s"
 
 #: qcsrc/common/notifications/all.inc:470
 #, c-format
 msgid "^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle ^BG%s^K1'n tulipalloa%s%s"
 
 #: qcsrc/common/notifications/all.inc:471
 #, c-format
 msgid "^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 paloi poroksi ^BG%s^K1'n tulimiinaan käveltyään%s%s"
 
 #: qcsrc/common/notifications/all.inc:472
 #, c-format
 msgid "^BG%s^K1 should have used a smaller gun%s%s"
-msgstr ""
+msgstr "^BG%s^K1 huomasi että olisi pitänyt käyttää pienempää pyssyä%s%s"
 
 #: qcsrc/common/notifications/all.inc:473
 #, c-format
 msgid "^BG%s^K1 forgot about their firemine%s%s"
-msgstr ""
+msgstr "^BG%s^K1 unohtivat tulimiinansa olemassaolon%s%s"
 
 #: qcsrc/common/notifications/all.inc:474
 #, c-format
 msgid "^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s"
 msgstr ""
+"^BG%s%s^K1 tuli nuijituksi tärskäyksellä ^BG%s^K1'n Hagar-raketteja%s%s"
 
 #: qcsrc/common/notifications/all.inc:475
 #, c-format
 msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s"
 msgstr ""
+"^BG%s%s^K1 tuli nuijituksi tärskäyksellä ^BG%s^K1'n Hagar-raketteja%s%s"
 
 #: qcsrc/common/notifications/all.inc:476
 #, c-format
 msgid "^BG%s^K1 played with tiny Hagar rockets%s%s"
-msgstr ""
+msgstr "^BG%s^K1 leikitteli pienenpienillä Hagar-raketeilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:477
 #, c-format
 msgid "^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 päätyi viillokiksi ^BG%s^K1'n HLAC:ien tehosta%s%s"
 
 #: qcsrc/common/notifications/all.inc:478
 #, c-format
 msgid "^BG%s^K1 got a little jumpy with their HLAC%s%s"
-msgstr ""
+msgstr "^BG%s^K1 äityivät hiukan säikyiksi HLAC:iensa kanssa%s%s"
 
 #: qcsrc/common/notifications/all.inc:479
 #, c-format
 msgid "^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 otti osumaa ^BG%s^K1'n Hook-painovoimapommista%s%s"
 
 #: qcsrc/common/notifications/all.inc:480
 #, c-format
 msgid ""
 "^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"
 msgstr ""
+"^BG%s%s^K1 kuoli ^BG%s^K1'n huikean pelaamisen johdosta @!#%%'n Klein-"
+"pullolla%s%s"
 
 #: qcsrc/common/notifications/all.inc:481
 #, c-format
 msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"
-msgstr ""
+msgstr "^BG%s^K1 hajottivat omat korvansa @!#%%'n Klein-pullolla%s%s"
 
 #: qcsrc/common/notifications/all.inc:482
 #, c-format
 msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 laitettiin nippuun ^BG%s^K1'n Konekiväärillä %s%s"
 
 #: qcsrc/common/notifications/all.inc:483
 #, c-format
 msgid "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 koristeltiin reikiä täyteen ^BG%s^K1'n Konekiväärillä%s%s"
 
 #: qcsrc/common/notifications/all.inc:484
 #: qcsrc/common/notifications/all.inc:794
 #, c-format
 msgid "^BGYou cannot place more than ^F2%s^BG mines at a time"
-msgstr ""
+msgstr "^BGEt voi asettaa enempää kuin ^F2%s^BG miinaa kerrallaan"
 
 #: qcsrc/common/notifications/all.inc:485
 #, c-format
 msgid "^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle ^BG%s^K1'n miinaa%s%s"
 
 #: qcsrc/common/notifications/all.inc:486
 #, c-format
 msgid "^BG%s^K1 forgot about their mine%s%s"
-msgstr ""
+msgstr "^BG%s^K1 unohtivat miinojensa olemassaolon%s%s"
 
 #: qcsrc/common/notifications/all.inc:487
 #, c-format
 msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 erehtyi liian lähelle ^BG%s^K1'n Mörssärikranaattia%s%s"
 
 #: qcsrc/common/notifications/all.inc:488
 #, c-format
 msgid "^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 hotkaisi ^BG%s^K1'n Mörssärikranaatin%s%s"
 
 #: qcsrc/common/notifications/all.inc:489
 #, c-format
 msgid "^BG%s^K1 didn't see their own Mortar grenade%s%s"
-msgstr ""
+msgstr "^BG%s^K1 eivät huomanneet omaa Mörssärikranaattiaan%s%s"
 
 #: qcsrc/common/notifications/all.inc:490
 #, c-format
 msgid "^BG%s^K1 blew themself up with their own Mortar%s%s"
-msgstr ""
+msgstr "^BG%s^K1 räjäyttivät itsensä omalla Mörssärillään%s%s"
 
 #: qcsrc/common/notifications/all.inc:491
 #, c-format
 msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
 msgstr ""
+"^BG%s%s^K1 niputettiin ^BG%s^K1'n Ylimalkaallisen Raskaalla Konekiväärillä%s"
+"%s"
 
 #: qcsrc/common/notifications/all.inc:492
 #, c-format
 msgid ""
 "^BG%s%s^K1 was torn to bits by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
 msgstr ""
+"^BG%s%s^K1 revittiin palasiksi ^BG%s^K1'n Ylimalkaallisella "
+"raskaskonekiväärillä%s%s"
 
 #: qcsrc/common/notifications/all.inc:493
 #, c-format
 msgid ""
 "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Overkill Machine Gun%s%s"
 msgstr ""
+"^BG%s%s^K1 ropisi täyteen reikiä ^BG%s^K1'n Ylimalkaallisella konekiväärillä"
+"%s%s"
 
 #: qcsrc/common/notifications/all.inc:494
 #, c-format
 msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Overkill Nex%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 höyrytettiin ^BG%s^K1'n Ylimalkaallisella Nex:illä%s%s"
 
 #: qcsrc/common/notifications/all.inc:495
 #, c-format
@@ -3271,146 +3364,158 @@ msgid ""
 "^BG%s%s^K1 was sawn in half by ^BG%s^K1's Overkill Rocket Propelled Chainsaw"
 "%s%s"
 msgstr ""
+"^BG%s%s^K1 sahattiin kahtia ^BG%s^K1'n Ylimalkaallisella rakettikäyttöisellä "
+"moottorisahalla%s%s"
 
 #: qcsrc/common/notifications/all.inc:496
 #, c-format
 msgid ""
 "^BG%s%s^K1 almost dodged ^BG%s^K1's Overkill Rocket Propelled Chainsaw%s%s"
 msgstr ""
+"^BG%s%s^K1 sai lähes väistettyä ^BG%s^K1'n Ylimalkaallisen rakettikäyttöisen "
+"mootorisahan toiminnassaan%s%s"
 
 #: qcsrc/common/notifications/all.inc:497
 #, c-format
 msgid ""
 "^BG%s^K1 was sawn in half by their own Overkill Rocket Propelled Chainsaw%s%s"
 msgstr ""
+"^BG%s^K1 sahasi itsensä kahtia omalla Ylimalkaallisella rakettikäyttöisellä "
+"moottorisahallaan%s%s"
 
 #: qcsrc/common/notifications/all.inc:498
 #, c-format
 msgid ""
 "^BG%s^K1 blew themself up with their Overkill Rocket Propelled Chainsaw%s%s"
 msgstr ""
+"^BG%s^K1 räjäyttivät itsensä omalla Ylimalkaallisella rakettikäyttöisellä "
+"moottorisahallaan%s%s"
 
 #: qcsrc/common/notifications/all.inc:500
 #, c-format
 msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Overkill Shotgun%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ammuttiin ^BG%s^K1'n Ylimalkaallisella haulikolla%s%s"
 
 #: qcsrc/common/notifications/all.inc:501
 #, c-format
 msgid "^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 niputettiin kiväärillä syyllisen ollen ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:502
 #, c-format
 msgid "^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 kuoli ^BG%s^K1'n Kiväärin luoti-ilmiössä%s%s"
 
 #: qcsrc/common/notifications/all.inc:503
 #, c-format
 msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"
 msgstr ""
+"^BG%s%s^K1 ei onnistunut piiloutumisyrityksessään ^BG%s^K1'n Kiväärin luoti-"
+"ilmiön edessä%s%s"
 
 #: qcsrc/common/notifications/all.inc:504
 #, c-format
 msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ei onnistunut välttämään ^BG%s^K1'n Kiväärin toimintaa%s%s"
 
 #: qcsrc/common/notifications/all.inc:505
 #, c-format
 msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 nuijittiin ^BG%s^K1'n Hakeutuvilla raketeilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:506
 #, c-format
 msgid "^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 korvamerkittiin ^BG%s^K1's Hakeutuvalla ammuksella%s%s"
 
 #: qcsrc/common/notifications/all.inc:507
 #, c-format
 msgid "^BG%s^K1 played with tiny Seeker rockets%s%s"
-msgstr ""
+msgstr "^BG%s^K1 leikitteli pienenpienillä Hakeutuvilla raketeilla%s%s"
 
 #: qcsrc/common/notifications/all.inc:508
 #, c-format
 msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 päätyi kanveesiin ^BG%s^K1'n Shokkihoidon tiimoilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:509
 #, c-format
 msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"
 msgstr ""
+"^BG%s%s^K1 tunsi tukkansa pölisevän ^BG%s^K1 ison Paineaallon tiimoilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:510
 #, c-format
 msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 ammuttiin ^BG%s^K1'n Haulikolla%s%s"
 
 #: qcsrc/common/notifications/all.inc:511
 #, c-format
 msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 sai kuin avarista ^BG%s^K1 ison Haulikon tiimoilta%s%s"
 
 #: qcsrc/common/notifications/all.inc:512
 #, c-format
 msgid "^BG%s^K1 is now thinking with portals%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ajattelee tällä hetkellä uusia ulottuvuuksia%s%s"
 
 #: qcsrc/common/notifications/all.inc:513
 #, c-format
 msgid "^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"
 msgstr ""
+"^BG%s%s^K1 sai tarpeekseen ^BG%s^K1'n upeasta @!#%%'n Tuubakonsertosta%s%s"
 
 #: qcsrc/common/notifications/all.inc:514
 #, c-format
 msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"
-msgstr ""
+msgstr "^BG%s^K1 ja korvansa kovilla @!#%%'n Tuubasta%s%s"
 
 #: qcsrc/common/notifications/all.inc:515
 #, c-format
 msgid "^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 härmistyi by ^BG%s^K1'n Höyryttimestä%s%s"
 
 #: qcsrc/common/notifications/all.inc:516
 #, c-format
 msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"
-msgstr ""
+msgstr "^BG%s%s^K1 pöllytettiin ^BG%s^K1'n Pyörremyrskyllä%s%s"
 
 #: qcsrc/common/notifications/all.inc:541
 msgid "^F4You are now alone!"
-msgstr ""
+msgstr "^F4Olet nyt yksin!"
 
 #: qcsrc/common/notifications/all.inc:543
 msgid "^BGYou are attacking!"
-msgstr ""
+msgstr "^BGSinä hyökkäät!"
 
 #: qcsrc/common/notifications/all.inc:544
 msgid "^BGYou are defending!"
-msgstr ""
+msgstr "^BGSinä puolustat!"
 
 #: qcsrc/common/notifications/all.inc:545
 #, c-format
 msgid "^BGObjective destroyed in ^F4%s^BG!"
-msgstr ""
+msgstr "^BGKohde tuhottu ^F4%s^BG!"
 
 #: qcsrc/common/notifications/all.inc:547
 msgid "^F4Begin!"
-msgstr ""
+msgstr "^F4Alkaa!"
 
 #: qcsrc/common/notifications/all.inc:548
 msgid "^F4Game starts in ^COUNT"
-msgstr ""
+msgstr "^F4Peli alkaa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:549
 msgid "^F4Round starts in ^COUNT"
-msgstr ""
+msgstr "^F4Kierros alkaa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:550
 msgid "^F4Round cannot start"
-msgstr ""
+msgstr "^F4Kierros ei voi alkaa"
 
 #: qcsrc/common/notifications/all.inc:555
 msgid "^F2Don't camp!"
-msgstr ""
+msgstr "^F2Älähän kämppää!"
 
 #: qcsrc/common/notifications/all.inc:559
 msgid ""
@@ -3418,10 +3523,13 @@ msgid ""
 "^BGFeel free to ^F2try to capture^BG the flag again\n"
 "^BGif you think you will succeed."
 msgstr ""
+"^BGSinut on vapautettu.\n"
+"^BGNyt voit ^F2yrittää kaapata^BG lipun jälleen\n"
+"^BGmikäli uskot sen onnistuvan."
 
 #: qcsrc/common/notifications/all.inc:560
 msgid "^BGThis flag is currently inactive"
-msgstr ""
+msgstr "^BGTämä lippu ei ole toiminnassa mukana tällä hetkellä"
 
 #: qcsrc/common/notifications/all.inc:561
 msgid ""
@@ -3429,216 +3537,221 @@ msgid ""
 "^BGfor ^F2too many unsuccessful attempts^BG to capture.\n"
 "^BGMake some defensive scores before trying again."
 msgstr ""
+"^BGOlet nyt ^F1suojakerrotettu^BG lipulta (lipuilta)\n"
+"^BGfor ^F2liian monta epäonnistunutta yritystä^BG kaappauksissa.\n"
+"^BGHanki puolustuspisteitä ennen kuin yrität uudelleen."
 
 #: qcsrc/common/notifications/all.inc:562
 msgid "^BGYou captured the ^TC^TT^BG flag!"
-msgstr ""
+msgstr "^BGSinä kaappasit ^TC^TT^BG lipun!"
 
 #: qcsrc/common/notifications/all.inc:563
 msgid "^BGYou captured the flag!"
-msgstr ""
+msgstr "^BGSinä kaappasit lipun!"
 
 #: qcsrc/common/notifications/all.inc:564
 #, c-format
 msgid "^BGToo many flag throws! Throwing disabled for %s."
-msgstr ""
+msgstr "^BGLiian monta lipun heittoa! Heittäminen evätty %s."
 
 #: qcsrc/common/notifications/all.inc:565
 #, c-format
 msgid "^BG%s^BG passed the ^TC^TT^BG flag to %s"
-msgstr ""
+msgstr "^BG%s^BG antoi ^TC^TT^BG lipun eteenpäin -  %s"
 
 #: qcsrc/common/notifications/all.inc:566
 #, c-format
 msgid "^BG%s^BG passed the flag to %s"
-msgstr ""
+msgstr "^BG%s^BG antoi lipun eteenpäin - %s"
 
 #: qcsrc/common/notifications/all.inc:567
 #, c-format
 msgid "^BGYou received the ^TC^TT^BG flag from %s"
-msgstr ""
+msgstr "^BGSinä sait ^TC^TT^BG lipun %s:lta"
 
 #: qcsrc/common/notifications/all.inc:568
 #, c-format
 msgid "^BGYou received the flag from %s"
-msgstr ""
+msgstr "^BGSinä sait lipun %s :lta"
 
 #: qcsrc/common/notifications/all.inc:569
 #, c-format
 msgid "^BGPress ^F2%s^BG to receive the flag from %s^BG"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG ottaaksesi lipun vastaan %s^BG :lta"
 
 #: qcsrc/common/notifications/all.inc:570
 #, c-format
 msgid "^BGRequesting %s^BG to pass you the flag"
-msgstr ""
+msgstr "^BGPyydetään %s^BG :ta antamaan lippu sinulle"
 
 #: qcsrc/common/notifications/all.inc:571
 #, c-format
 msgid "^BGYou passed the ^TC^TT^BG flag to %s"
-msgstr ""
+msgstr "^BGSinä annoit ^TC^TT^BG lipun %s :lle"
 
 #: qcsrc/common/notifications/all.inc:572
 #, c-format
 msgid "^BGYou passed the flag to %s"
-msgstr ""
+msgstr "^BGSinä annoit lipun %s :lle"
 
 #: qcsrc/common/notifications/all.inc:573
 msgid "^BGYou got the ^TC^TT^BG flag!"
-msgstr ""
+msgstr "^BGSinulla on ^TC^TT^BG lippu!"
 
 #: qcsrc/common/notifications/all.inc:574
 msgid "^BGYou got the flag!"
-msgstr ""
+msgstr "^BGSinulla on lippu!"
 
 #: qcsrc/common/notifications/all.inc:575
 #, c-format
 msgid "^BGYou got your %steam^BG's flag, return it!"
-msgstr ""
+msgstr "^BGSinulla on %sjoukkueesi^BG's lippu, palauta se!"
 
 #: qcsrc/common/notifications/all.inc:576
 #, c-format
 msgid "^BGYou got the %senemy^BG's flag, return it!"
-msgstr ""
+msgstr "^BGSinulla on %svihollisen^BG's lippu, palauta se!"
 
 #: qcsrc/common/notifications/all.inc:577
 #, c-format
 msgid "^BGThe %senemy^BG got your flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollisella %senemy^BG on lippusi! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:578
 #, c-format
 msgid "^BGThe %senemy (^BG%s%s)^BG got your flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollinen %ssai (^BG%s%s)^BG lippusi! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:579
 #, c-format
 msgid "^BGThe %senemy^BG got the flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollinen %ssai^BG lipun! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:580
 #, c-format
 msgid "^BGThe %senemy (^BG%s%s)^BG got the flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollinen %ssai (^BG%s%s)^BG lipun! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:581
 #, c-format
 msgid "^BGThe %senemy^BG got their flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollinen %ssai^BG lippunsa! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:582
 #, c-format
 msgid "^BGThe %senemy (^BG%s%s)^BG got their flag! Retrieve it!"
-msgstr ""
+msgstr "^BGVihollinen %ssai (^BG%s%s)^BG lippunsa! Nouda se!"
 
 #: qcsrc/common/notifications/all.inc:583
 #, c-format
 msgid "^BGYour %steam mate^BG got the ^TC^TT^BG flag! Protect them!"
-msgstr ""
+msgstr "^BGSinun %sjoukkuekaverisi^BG sai ^TC^TT^BG lipun! Suojelua!"
 
 #: qcsrc/common/notifications/all.inc:584
 #, c-format
 msgid "^BGYour %steam mate (^BG%s%s)^BG got the ^TC^TT^BG flag! Protect them!"
-msgstr ""
+msgstr "^BGSinun %sjoukkuekaverisi (^BG%s%s)^BG sai ^TC^TT^BG lipun! Suojelua!"
 
 #: qcsrc/common/notifications/all.inc:585
 #, c-format
 msgid "^BGYour %steam mate^BG got the flag! Protect them!"
-msgstr ""
+msgstr "^BGSinun %sjoukkuekaverisi^BG sai lipun! Suojelua!"
 
 #: qcsrc/common/notifications/all.inc:586
 #, c-format
 msgid "^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"
-msgstr ""
+msgstr "^BGSinun %sjoukkuekaverisi (^BG%s%s)^BG sai lipun! Suojelua!"
 
 #: qcsrc/common/notifications/all.inc:587
 msgid "^BGEnemies can now see you on radar!"
-msgstr ""
+msgstr "^BGNäyt nyt vihollisten tutkassa!"
 
 #: qcsrc/common/notifications/all.inc:588
 msgid "^BGYou returned the ^TC^TT^BG flag!"
-msgstr ""
+msgstr "^BGSinä palautit ^TC^TT^BG lipun!"
 
 #: qcsrc/common/notifications/all.inc:589
 msgid "^BGStalemate! Enemies can now see you on radar!"
-msgstr ""
+msgstr "^BGPattitilanne! Näyt nyt vihollisten tutkassa!"
 
 #: qcsrc/common/notifications/all.inc:590
 msgid "^BGStalemate! Flag carriers can now be seen by enemies on radar!"
 msgstr ""
+"^BGPattitilanne! Lipunkantajat ovat nyt vihollisten nähtävissä tutkassa!"
 
 #: qcsrc/common/notifications/all.inc:594
 #, c-format
 msgid "^K3%sYou fragged ^BG%s"
-msgstr ""
+msgstr "^K3%sFrägäsit: ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:595
 #: qcsrc/common/notifications/all.inc:604
 #: qcsrc/common/notifications/all.inc:613
 #, c-format
 msgid "^K3%sYou scored against ^BG%s"
-msgstr ""
+msgstr "^K3%sTeit pisteitä ^BG%s:n kustannuksella"
 
 #: qcsrc/common/notifications/all.inc:596
 #, c-format
 msgid "^K1%sYou were fragged by ^BG%s"
-msgstr ""
+msgstr "^K1%sSinut frägättiin ^BG%s:n toimesta"
 
 #: qcsrc/common/notifications/all.inc:597
 #: qcsrc/common/notifications/all.inc:606
 #: qcsrc/common/notifications/all.inc:615
 #, c-format
 msgid "^K1%sYou were scored against by ^BG%s"
-msgstr ""
+msgstr "^K1%sKustannuksellasi tehtiin pisteitä tekijän ollen ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:603
 #, c-format
 msgid "^K3%sYou burned ^BG%s"
-msgstr ""
+msgstr "^K3%sSinä paloit ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:605
 #, c-format
 msgid "^K1%sYou were burned by ^BG%s"
-msgstr ""
+msgstr "^K1%sTulit poltetuksi ^BG%s:n toimesta"
 
 #: qcsrc/common/notifications/all.inc:612
 #, c-format
 msgid "^K3%sYou froze ^BG%s"
-msgstr ""
+msgstr "^K3%sJäädyit ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:614
 #, c-format
 msgid "^K1%sYou were frozen by ^BG%s"
-msgstr ""
+msgstr "^K1%sSinut jäädytettiin ^BG%s :n toimesta"
 
 #: qcsrc/common/notifications/all.inc:621
 #, c-format
 msgid "^K1%sYou typefragged ^BG%s"
-msgstr ""
+msgstr "^K1%sSinä kirjoittelunaikaisfrägäsit ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:622
 #, c-format
 msgid "^K1%sYou scored against ^BG%s^K1 while they were typing"
 msgstr ""
+"^K1%sOtitte hyödyn irti ^BG%s^K1 :n kustannuksella heidän kirjoitellessaan"
 
 #: qcsrc/common/notifications/all.inc:623
 #, c-format
 msgid "^K1%sYou were typefragged by ^BG%s"
-msgstr ""
+msgstr "^K1%sSinut kirjoittelunaikaisfrägättiin ^BG%s:n toimesta"
 
 #: qcsrc/common/notifications/all.inc:624
 #, c-format
 msgid "^K1%sYou were scored against by ^BG%s^K1 while typing"
-msgstr ""
+msgstr "^K1%sSinusta revittiin hyöty irti ^BG%s^K1 kirjoitellessasi"
 
 #: qcsrc/common/notifications/all.inc:630
 #, c-format
 msgid "^BGPress ^F2%s^BG again to toss the nade!"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG uudestaan viskataksesi naatin!"
 
 #: qcsrc/common/notifications/all.inc:631
 msgid "^F2You got a ^K1BONUS GRENADE^F2!"
-msgstr ""
+msgstr "^F2Sinä sait ^K1LISÄETU-KRANAATIN^F2!"
 
 #: qcsrc/common/notifications/all.inc:633
 #, c-format
@@ -3646,342 +3759,358 @@ msgid ""
 "^BGYou have been moved into a different team\n"
 "You are now on: %s"
 msgstr ""
+"^BGSinut siirrettiin eri joukkueeseen\n"
+"Olet nyt joukkueessa: %s"
 
 #: qcsrc/common/notifications/all.inc:634
 msgid "^K1Don't go against your team mates!"
-msgstr ""
+msgstr "^K1Älä käy joukkuekavereitasi vastaan!"
 
 #: qcsrc/common/notifications/all.inc:634
 msgid "^K1Don't shoot your team mates!"
-msgstr ""
+msgstr "^K1Älä joukkuekavereitasi ammu!"
 
 #: qcsrc/common/notifications/all.inc:635
 msgid "^K1Die camper!"
-msgstr ""
+msgstr "^K1Kuole senkin kämpperi!"
 
 #: qcsrc/common/notifications/all.inc:635
 msgid "^K1Reconsider your tactics, camper!"
-msgstr ""
+msgstr "^K1Kelaapa suunnitelmasi uusiksi, kämpperi!"
 
 #: qcsrc/common/notifications/all.inc:636
 msgid "^K1You unfairly eliminated yourself!"
-msgstr ""
+msgstr "^K1Sinä hyvin epärehellisesti poistit itsesi!"
 
 #: qcsrc/common/notifications/all.inc:637
 #, c-format
 msgid "^K1You were %s"
-msgstr ""
+msgstr "^K1Sinulle kävi nyt näin %s"
 
 #: qcsrc/common/notifications/all.inc:638
 msgid "^K1You couldn't catch your breath!"
-msgstr ""
+msgstr "^K1Et saanut henkeä!"
 
 #: qcsrc/common/notifications/all.inc:639
 msgid "^K1You hit the ground with a crunch!"
-msgstr ""
+msgstr "^K1Kohtasit maankamaran kanssa että raksui vain!"
 
 #: qcsrc/common/notifications/all.inc:640
 msgid "^K1You felt a little too hot!"
-msgstr ""
+msgstr "^K1Meni vähän liian kuumaksi!"
 
 #: qcsrc/common/notifications/all.inc:640
 msgid "^K1You got a little bit too crispy!"
-msgstr ""
+msgstr "^K1Nyt oli hiukan liian rapeaa!"
 
 #: qcsrc/common/notifications/all.inc:641
 msgid "^K1You killed your own dumb self!"
-msgstr ""
+msgstr "^K1Latvakakkonen tappoi itsensä!"
 
 #: qcsrc/common/notifications/all.inc:641
 msgid "^K1You need to be more careful!"
-msgstr ""
+msgstr "^K1Olisit piirunverran huolellisempi!"
 
 #: qcsrc/common/notifications/all.inc:642
 msgid "^K1You couldn't stand the heat!"
-msgstr ""
+msgstr "^K1Et kestänyt löylyä!"
 
 #: qcsrc/common/notifications/all.inc:643
 msgid "^K1You need to watch out for monsters!"
-msgstr ""
+msgstr "^K1Sinun pitää varoa hirviöitä!"
 
 #: qcsrc/common/notifications/all.inc:643
 msgid "^K1You were killed by a monster!"
-msgstr ""
+msgstr "^K1Hirviö tappoi sinut!"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1Tastes like chicken!"
-msgstr ""
+msgstr "^K1Maistuu ihan kotkotilta!"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1You forgot to put the pin back in!"
-msgstr ""
+msgstr "^K1Taisi unohtua laittaa tappi takaisin!"
 
 #: qcsrc/common/notifications/all.inc:645
 msgid "^K1Hanging around a napalm explosion is bad!"
-msgstr ""
+msgstr "^K1Sen siitä saa kun velttoilee napalmiräjähdysalueella!"
 
 #: qcsrc/common/notifications/all.inc:646
 msgid "^K1You felt a little chilly!"
-msgstr ""
+msgstr "^K1Nyt tuli holotna!"
 
 #: qcsrc/common/notifications/all.inc:646
 msgid "^K1You got a little bit too cold!"
-msgstr ""
+msgstr "^K1Nyt vilustuit!"
 
 #: qcsrc/common/notifications/all.inc:647
 msgid "^K1Your Healing Nade is a bit defective"
-msgstr ""
+msgstr "^K1Terveysnaattisi vaikuttaa jokseenkin kotikutoiselta"
 
 #: qcsrc/common/notifications/all.inc:648
 msgid "^K1You are respawning for running out of ammo..."
-msgstr ""
+msgstr "^K1Jälleensyntymä ammusten loppumisen takia..."
 
 #: qcsrc/common/notifications/all.inc:648
 msgid "^K1You were killed for running out of ammo..."
-msgstr ""
+msgstr "^K1Ei ammuksia jäljellä joten sinut tapettiin..."
 
 #: qcsrc/common/notifications/all.inc:649
 msgid "^K1You grew too old without taking your medicine"
-msgstr ""
+msgstr "^K1Nytpä äityivät aivot vanhoiksi ilman lääkitystäsi"
 
 #: qcsrc/common/notifications/all.inc:649
 msgid "^K1You need to preserve your health"
-msgstr ""
+msgstr "^K1Sinun täytyy ajatella terveyttäsi"
 
 #: qcsrc/common/notifications/all.inc:650
 msgid "^K1You became a shooting star!"
-msgstr ""
+msgstr "^K1Sinusta tuli tähdenlento!"
 
 #: qcsrc/common/notifications/all.inc:651
 msgid "^K1You melted away in slime!"
-msgstr ""
+msgstr "^K1Kohtaloksesi koitui sulaminen limassa!"
 
 #: qcsrc/common/notifications/all.inc:652
 msgid "^K1You committed suicide!"
-msgstr ""
+msgstr "^K1Otit itse itseltäsi nirrin pois!"
 
 #: qcsrc/common/notifications/all.inc:652
 msgid "^K1You ended it all!"
-msgstr ""
+msgstr "^K1Lopetit kaiken!"
 
 #: qcsrc/common/notifications/all.inc:653
 msgid "^K1You got stuck in a swamp!"
-msgstr ""
+msgstr "^K1Lauloit itsesi suohon!"
 
 #: qcsrc/common/notifications/all.inc:654
 #, c-format
 msgid "^BGYou are now on: %s"
-msgstr ""
+msgstr "^BGOlet nyt: %s :ssa"
 
 #: qcsrc/common/notifications/all.inc:655
 msgid "^K1You died in an accident!"
-msgstr ""
+msgstr "^K1Kuolit onnettomuudessa!"
 
 #: qcsrc/common/notifications/all.inc:656
 msgid "^K1You had an unfortunate run in with a turret!"
-msgstr ""
+msgstr "^K1Treffit tykkitornin kanssa eivät päättyneet hyvin!"
 
 #: qcsrc/common/notifications/all.inc:656
 msgid "^K1You were fragged by a turret!"
-msgstr ""
+msgstr "^K1Tykkitorni vei sinut!"
 
 #: qcsrc/common/notifications/all.inc:657
 msgid "^K1You had an unfortunate run in with an eWheel turret!"
-msgstr ""
+msgstr "^K1Ikävämmänpuoleinen kohtaaminen eWheel-tykkitornin kanssa!"
 
 #: qcsrc/common/notifications/all.inc:657
 msgid "^K1You were fragged by an eWheel turret!"
-msgstr ""
+msgstr "^K1Sinut frägäsi eWheel-tykkitorni!"
 
 #: qcsrc/common/notifications/all.inc:658
 msgid "^K1You had an unfortunate run in with a Walker turret!"
-msgstr ""
+msgstr "^K1Ikävämmänpuoleinen kohtaaminen Walker-tykkitornin kanssa! "
 
 #: qcsrc/common/notifications/all.inc:658
 msgid "^K1You were fragged by a Walker turret!"
-msgstr ""
+msgstr "^K1Sinut frägäsi Walker-tykkitorni! "
 
 #: qcsrc/common/notifications/all.inc:659
 msgid "^K1You got caught in the blast of a Bumblebee explosion!"
-msgstr ""
+msgstr "^K1Otit osumaa Bumblebee:n töräyksestä!"
 
 #: qcsrc/common/notifications/all.inc:660
 msgid "^K1You were crushed by a vehicle!"
-msgstr ""
+msgstr "^K1Ajauduit ajoneuvon murskaamaksi!"
 
 #: qcsrc/common/notifications/all.inc:661
 msgid "^K1You were caught in a Raptor cluster bomb!"
-msgstr ""
+msgstr "^K1YOtit osumaa Raptor-sirpalepommista!"
 
 #: qcsrc/common/notifications/all.inc:662
 msgid "^K1You got caught in the blast of a Raptor explosion!"
-msgstr ""
+msgstr "^K1YOtit osumaa Raptor:in töräyksestä!"
 
 #: qcsrc/common/notifications/all.inc:663
 msgid "^K1You got caught in the blast of a Spiderbot explosion!"
-msgstr ""
+msgstr "^K1Otit osumaa Hämisbot:in räjähdyksen töräyksestä!"
 
 #: qcsrc/common/notifications/all.inc:664
 msgid "^K1You were blasted to bits by a Spiderbot rocket!"
-msgstr ""
+msgstr "^K1Sinut posautettiin palasiksi Hämisbot:in raketin toimesta!"
 
 #: qcsrc/common/notifications/all.inc:665
 msgid "^K1You got caught in the blast of a Racer explosion!"
-msgstr ""
+msgstr "^K1Otit osumaa Kilpurin räjähdyksen töräyksestä! "
 
 #: qcsrc/common/notifications/all.inc:666
 msgid "^K1You couldn't find shelter from a Racer rocket!"
-msgstr ""
+msgstr "^K1Et löytänyt suojaa Kilpurin raketilta!"
 
 #: qcsrc/common/notifications/all.inc:667
 msgid "^K1Watch your step!"
-msgstr ""
+msgstr "^K1Katso mihin astut!"
 
 #: qcsrc/common/notifications/all.inc:669
 #, c-format
 msgid "^K1Moron! You fragged ^BG%s^K1, a team mate!"
-msgstr ""
+msgstr "^K1Vatipää! Frägäsit ^BG%s^K1, joukkuekaverin!"
 
 #: qcsrc/common/notifications/all.inc:669
 #, c-format
 msgid "^K1Moron! You went against ^BG%s^K1, a team mate!"
-msgstr ""
+msgstr "^K1Vatipää! Kävit ^BG%s^K1, joukkuekaveria vastaan!"
 
 #: qcsrc/common/notifications/all.inc:670
 #, c-format
 msgid "^K1You were fragged by ^BG%s^K1, a team mate"
-msgstr ""
+msgstr "^K1Sinut frägättiin ^BG%s^K1, joukkuekaverin toimesta"
 
 #: qcsrc/common/notifications/all.inc:670
 #, c-format
 msgid "^K1You were scored against by ^BG%s^K1, a team mate"
-msgstr ""
+msgstr "^K1Sinua kohtaan tehtiin vääryyttä ^BG%s^K1, joukkuekaverin toimesta"
 
 #: qcsrc/common/notifications/all.inc:672
 msgid ""
 "^K1Stop idling!\n"
 "^BGDisconnecting in ^COUNT..."
 msgstr ""
+"^K1Lopeta se mitääntekemättömyys!\n"
+"^BGYhteys katkaistaan ^COUNT..."
 
 #: qcsrc/common/notifications/all.inc:674
 #, c-format
 msgid "^BGYou need %s^BG!"
-msgstr ""
+msgstr "^BGSinä tarvitset %s^BG!"
 
 #: qcsrc/common/notifications/all.inc:675
 #, c-format
 msgid "^BGYou also need %s^BG!"
-msgstr ""
+msgstr "^BGSen lisäksi tarvitset %s^BG!"
 
 #: qcsrc/common/notifications/all.inc:676
 msgid "^BGDoor unlocked!"
-msgstr ""
+msgstr "^BGOvi avattu!"
 
 #: qcsrc/common/notifications/all.inc:678
 msgid "^F2You picked up some extra lives"
-msgstr ""
+msgstr "^F2Poimit lisäelämiä"
 
 #: qcsrc/common/notifications/all.inc:680
 #, c-format
 msgid "^K3You revived ^BG%s"
-msgstr ""
+msgstr "^K3Sinä elvytit ^BG%s"
 
 #: qcsrc/common/notifications/all.inc:681
 msgid "^K3You revived yourself"
-msgstr ""
+msgstr "^K3Elvytit itsesi"
 
 #: qcsrc/common/notifications/all.inc:682
 #, c-format
 msgid "^K3You were revived by ^BG%s"
-msgstr ""
+msgstr "^K3Sinut elvytettiin ^BG%s :n toimesta"
 
 #: qcsrc/common/notifications/all.inc:683
 #, c-format
 msgid "^K3You were automatically revived after %s second(s)"
-msgstr ""
+msgstr "^K3Sinut elvytettiin automaattisesti %s sekunnissa()"
 
 #: qcsrc/common/notifications/all.inc:685
 msgid "^BGThe generator is under attack!"
-msgstr ""
+msgstr "^BGGeneraattori hyökkäyksen alaisena!"
 
 #: qcsrc/common/notifications/all.inc:687
 msgid "^TC^TT^BG team loses the round"
-msgstr ""
+msgstr "^TC^TT^BG joukkue häviää kierroksen"
 
 #: qcsrc/common/notifications/all.inc:691
 msgid "^K1You froze yourself"
-msgstr ""
+msgstr "^K1Jäädytit itsesi"
 
 #: qcsrc/common/notifications/all.inc:692
 msgid "^K1Round already started, you spawn as frozen"
-msgstr ""
+msgstr "^K1Kierros on jo alkanut, ilmestyt jäätyneenä"
 
 #: qcsrc/common/notifications/all.inc:694
 #, c-format
 msgid "^K1A %s has arrived!"
-msgstr ""
+msgstr "^K1A %s on saapunut!"
 
 #: qcsrc/common/notifications/all.inc:698
 msgid "^BGYou got the ^F1Fuel regenerator"
-msgstr ""
+msgstr "^BGSinulla on ^F1Polttoaineen uusiotuotin"
 
 #: qcsrc/common/notifications/all.inc:699
 msgid "^BGYou got the ^F1Jetpack"
-msgstr ""
+msgstr "^BGSinulla on ^F1Lentopakkaus"
 
 #: qcsrc/common/notifications/all.inc:707
 msgid ""
 "^K1No spawnpoints available!\n"
 "Hope your team can fix it..."
 msgstr ""
+"^K1Ei uudelleensyntypisteitä!\n"
+"Toivottavasti joukkueesi korjaa tämän asian..."
 
 #: qcsrc/common/notifications/all.inc:708
 msgid ""
 "^K1You may not join the game at this time.\n"
 "The player limit reached maximum capacity."
 msgstr ""
+"^K1Et voi liittyä peliin juuri nyt.\n"
+"Pelaajamäärä on saavuttanut lakipisteensä."
 
 #: qcsrc/common/notifications/all.inc:712
 msgid "^BGYou picked up the ball"
-msgstr ""
+msgstr "^BGPoimit pallon matkaan"
 
 #: qcsrc/common/notifications/all.inc:713
 msgid "^BGKilling people while you don't have the ball gives no points!"
-msgstr ""
+msgstr "^BGIhmisten tappaminen ilman palloa ei kerrytä pisteitä!"
 
 #: qcsrc/common/notifications/all.inc:715
 msgid ""
 "^BGAll keys are in your team's hands!\n"
 "Help the key carriers to meet!"
 msgstr ""
+"^BGKaikki avaimet ovat joukkueesi hallussa!\n"
+"Avusta avaintenkantajia tapaamaan toisensa!"
 
 #: qcsrc/common/notifications/all.inc:716
 msgid ""
 "^BGAll keys are in ^TC^TT team^BG's hands!\n"
 "Interfere ^F4NOW^BG!"
 msgstr ""
+"^BGKaikki avaimet ovat ^TC^TT joukkueen^BG hallussa!\n"
+"Puutu tilanteeseen ^F4NOW^BG!"
 
 #: qcsrc/common/notifications/all.inc:717
 msgid ""
 "^BGAll keys are in your team's hands!\n"
 "Meet the other key carriers ^F4NOW^BG!"
 msgstr ""
+"^BGKaikki avaimet ovat sinun joukkueesi hallussa!\n"
+"Järjestä tapaaminen muiden avaintenkantajien kanssa ^F4NOW^BG!"
 
 #: qcsrc/common/notifications/all.inc:718
 msgid "^F4Round will start in ^COUNT"
-msgstr ""
+msgstr "^F4Kierros alkaa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:719
 msgid "^BGScanning frequency range..."
-msgstr ""
+msgstr "^BGLäpikäydään taajuusaluetta..."
 
 #: qcsrc/common/notifications/all.inc:720
 msgid "^BGYou are starting with the ^TC^TT Key"
-msgstr ""
+msgstr "^BGAloitat ^TC^TT Avaimella"
 
 #: qcsrc/common/notifications/all.inc:722
 msgid "^BGYou have no lives left, you must wait until the next match"
 msgstr ""
+"^BGSinulla ei ole enää elämiä jäljellä, sinun täytyy odottaa seuraavaa "
+"ottelua"
 
 #: qcsrc/common/notifications/all.inc:724
 #, c-format
@@ -3989,32 +4118,34 @@ msgid ""
 "^BGWaiting for players to join...\n"
 "Need active players for: %s"
 msgstr ""
+"^BGPelaajia odotetaan liittyväksi...\n"
+"Aktiivisia tarvitaan: %s"
 
 #: qcsrc/common/notifications/all.inc:725
 #, c-format
 msgid "^BGWaiting for %s player(s) to join..."
-msgstr ""
+msgstr "^BGOdotetaan %s pelaajaa (pelaajia) liittymään..."
 
 #: qcsrc/common/notifications/all.inc:727
 msgid "^BGYour weapon has been downgraded until you find some ammo!"
-msgstr ""
+msgstr "^BGAseesi alasluokattiin kunnes löydät ammuksia!"
 
 #: qcsrc/common/notifications/all.inc:728
 msgid "^F4^COUNT^BG left to find some ammo!"
-msgstr ""
+msgstr "^F4^COUNT^BG jäljellä löytää ammuksia!"
 
 #: qcsrc/common/notifications/all.inc:729
 msgid "^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"
-msgstr ""
+msgstr "^BGHanki ammuksia tai olet kuollut tuotapikaa ^F4^COUNT^BG!"
 
 #: qcsrc/common/notifications/all.inc:729
 msgid "^BGGet some ammo! ^F4^COUNT^BG left!"
-msgstr ""
+msgstr "^BGHanki niitä ammuksia! ^F4^COUNT^BG jäljellä!"
 
 #: qcsrc/common/notifications/all.inc:730
 #, c-format
 msgid "^F2Extra lives remaining: ^K1%s"
-msgstr ""
+msgstr "^F2Lisäelämiä jäljellä: ^K1%s"
 
 #: qcsrc/common/notifications/all.inc:734
 #, c-format
@@ -4022,63 +4153,73 @@ msgid ""
 "^F2^COUNT^BG until weapon change...\n"
 "Next weapon: ^F1%s"
 msgstr ""
+"^F2^COUNT^BG jäljellä seuraavaan asevaihtoon...\n"
+"Seuraava ase: ^F1%s"
 
 #: qcsrc/common/notifications/all.inc:735
 #, c-format
 msgid "^F2Active weapon: ^F1%s"
-msgstr ""
+msgstr "^F2Aktiivinen ase: ^F1%s"
 
 #: qcsrc/common/notifications/all.inc:737
 #, c-format
 msgid "^BGYou captured %s^BG control point"
-msgstr ""
+msgstr "^BGKaappasit haltuusi %s^BG hallintapisteen"
 
 #: qcsrc/common/notifications/all.inc:738
 #, c-format
 msgid "^TC^TT^BG team captured %s^BG control point"
-msgstr ""
+msgstr "^TC^TT^BG joukkue kaappasi %s^BG hallintapisteen"
 
 #: qcsrc/common/notifications/all.inc:739
 msgid "^BGThis control point currently cannot be captured"
-msgstr ""
+msgstr "^BGTätä hallintapistettä ei nykyisellään voi kaapata haltuun"
 
 #: qcsrc/common/notifications/all.inc:740
 msgid ""
 "^BGThe enemy generator cannot be destroyed yet\n"
 "^F2Capture some control points to unshield it"
 msgstr ""
+"^BGVihollisgeneraattoria ei vielä voi tuhota\n"
+"^F2Kaappaa hallintapisteitä haltuusi riisuaksesi sen suojaukset"
 
 #: qcsrc/common/notifications/all.inc:741
 msgid "^BGThe ^TCenemy^BG generator is no longer shielded!"
-msgstr ""
+msgstr "^BGNyt ^TCvihollisten^BG generaattori on riisuttu suojauksistaan!"
 
 #: qcsrc/common/notifications/all.inc:742
 msgid ""
 "^K1Your generator is NOT shielded!\n"
 "^BGRe-capture control points to shield it!"
 msgstr ""
+"^K1Generaattorisi EI OLE suojattu!\n"
+"^BGKaappaa hallintapisteet takaisin suojataksesi sen!"
 
 #: qcsrc/common/notifications/all.inc:743
 #, c-format
 msgid "^BGPress ^F2%s^BG to teleport"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG etäsiirtyäksesi"
 
 #: qcsrc/common/notifications/all.inc:744
 #, c-format
 msgid "^BGTeleporting disabled for %s"
-msgstr ""
+msgstr "^BGEtäsiirto on kytketty pois %s :lle"
 
 #: qcsrc/common/notifications/all.inc:746
 msgid ""
 "^F2Now playing ^F4OVERTIME^F2!\n"
 "Keep fragging until we have a winner!"
 msgstr ""
+"^F2Nyt pelataan ^F4JATKOAIKAA^F2!\n"
+"Jatka frägäämistä kunnes voittaja selviää!"
 
 #: qcsrc/common/notifications/all.inc:746
 msgid ""
 "^F2Now playing ^F4OVERTIME^F2!\n"
 "Keep scoring until we have a winner!"
 msgstr ""
+"^F2Nyt pelataan ^F4JATKOAIKAA^F2!\n"
+"Jatka pisteiden takomista kunnes voittaja selviää!"
 
 #: qcsrc/common/notifications/all.inc:747
 msgid ""
@@ -4088,6 +4229,11 @@ msgid ""
 "The more control points your team holds,\n"
 "the faster the enemy generator decays"
 msgstr ""
+"^F2Nyt pelataan ^F4JATKOAIKAA^F2!\n"
+"\n"
+"Generaattorit hiipuvat.\n"
+"Mitä enemmän hallintapisteitä joukkueesi pitää hallussa,\n"
+"sitä nopeammin vastustajan generaattorit hiipuvat"
 
 #: qcsrc/common/notifications/all.inc:748
 #, c-format
@@ -4095,277 +4241,286 @@ msgid ""
 "^F2Now playing ^F4OVERTIME^F2!\n"
 "^BGAdded ^F4%s^BG to the game!"
 msgstr ""
+"^F2Nyt pelataan ^F4JATKOAIKAA^F2!\n"
+"^BGLisätty ^F4%s^BG peliin!"
 
 #: qcsrc/common/notifications/all.inc:750
 msgid "^K1In^BG-portal created"
-msgstr ""
+msgstr "^K1Sisäänkäynti^BG-portaali on luotu"
 
 #: qcsrc/common/notifications/all.inc:751
 msgid "^F3Out^BG-portal created"
-msgstr ""
+msgstr "^F3Uloskäynti^BG-portaali luotu"
 
 #: qcsrc/common/notifications/all.inc:752
 msgid "^F1Portal creation failed"
-msgstr ""
+msgstr "^F1Portaalin luominen epäonnistui"
 
 #: qcsrc/common/notifications/all.inc:754
 msgid "^F2Strength infuses your weapons with devastating power"
-msgstr ""
+msgstr "^F2Voima sytyttää aseesi tuhoisalla vahvuudella"
 
 #: qcsrc/common/notifications/all.inc:755
 msgid "^F2Strength has worn off"
-msgstr ""
+msgstr "^F2Voima ehtyi pois"
 
 #: qcsrc/common/notifications/all.inc:757
 msgid "^F2Shield surrounds you"
-msgstr ""
+msgstr "^F2Sinua ympäröi suojus"
 
 #: qcsrc/common/notifications/all.inc:758
 msgid "^F2Shield has worn off"
-msgstr ""
+msgstr "^F2Suoja ehtyi pois"
 
 #: qcsrc/common/notifications/all.inc:760
 msgid "^F2You are on speed"
-msgstr ""
+msgstr "^F2Olet vauhdissa"
 
 #: qcsrc/common/notifications/all.inc:761
 msgid "^F2Speed has worn off"
-msgstr ""
+msgstr "^F2Vauhti ehtyi pois"
 
 #: qcsrc/common/notifications/all.inc:763
 msgid "^F2You are invisible"
-msgstr ""
+msgstr "^F2Olet näkymätön"
 
 #: qcsrc/common/notifications/all.inc:764
 msgid "^F2Invisibility has worn off"
-msgstr ""
+msgstr "^F2Näkymättömyys ehtyi pois"
 
 #: qcsrc/common/notifications/all.inc:766
 msgid "^F2The race is over, finish your lap!"
-msgstr ""
+msgstr "^F2Kilpa on ohi, päätä kierroksesi päätökseen!"
 
 #: qcsrc/common/notifications/all.inc:768
 msgid "^BGSecondary fire inflicts no damage!"
-msgstr ""
+msgstr "^BGToissijainen tulitus ei aiheuta vahinkoa!"
 
 #: qcsrc/common/notifications/all.inc:770
 msgid "^BGSequence completed!"
-msgstr ""
+msgstr "^BGOsio saatettu päätökseen!"
 
 #: qcsrc/common/notifications/all.inc:771
 msgid "^BGThere are more to go..."
-msgstr ""
+msgstr "^BGEdessä on lisää..."
 
 #: qcsrc/common/notifications/all.inc:772
 #, c-format
 msgid "^BGOnly %s^BG more to go..."
-msgstr ""
+msgstr "^BGAinoastaan %s^BG jäljellä..."
 
 #: qcsrc/common/notifications/all.inc:774
 msgid "^F2Superweapons have broken down"
-msgstr ""
+msgstr "^F2Mahtiaseet ovat menneet rikki"
 
 #: qcsrc/common/notifications/all.inc:775
 msgid "^F2Superweapons have been lost"
-msgstr ""
+msgstr "^F2Mahtiaseet menetetty"
 
 #: qcsrc/common/notifications/all.inc:776
 msgid "^F2You now have a superweapon"
-msgstr ""
+msgstr "^F2Sinulla on nyt hallussasi mahtiase"
 
 #: qcsrc/common/notifications/all.inc:778
 msgid "^K1Changing to ^TC^TT^K1 in ^COUNT"
-msgstr ""
+msgstr "^K1Vaihdetaan ^TC^TT^K1 ajassa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:779
 msgid "^K1Changing team in ^COUNT"
-msgstr ""
+msgstr "^K1Vaihdetaan joukkuetta ajassa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:780
 msgid "^K1Spectating in ^COUNT"
-msgstr ""
+msgstr "^K1Katselu alkaa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:781
 msgid "^K1Suicide in ^COUNT"
-msgstr ""
+msgstr "^K1Itsemurha ajassa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:783
 msgid "^F4Timeout begins in ^COUNT"
-msgstr ""
+msgstr "^F4Aikalisä alkaa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:784
 msgid "^F4Timeout ends in ^COUNT"
-msgstr ""
+msgstr "^F4Aikalisä päättyy ajassa ^COUNT"
 
 #: qcsrc/common/notifications/all.inc:786
 msgid "^K1Cannot join given minigame session!"
-msgstr ""
+msgstr "^K1Annettuun pienpeli-istuntoon ei voitu liittyä!"
 
 #: qcsrc/common/notifications/all.inc:788
 #, c-format
 msgid "^BGPress ^F2%s^BG to enter/exit the vehicle"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG käydäksesi sisään/poistuaksesi ajoneuvosta"
 
 #: qcsrc/common/notifications/all.inc:789
 #, c-format
 msgid "^BGPress ^F2%s^BG to enter the vehicle gunner"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG käydäksesi sisälle ajoneuvon ampumisosaan"
 
 #: qcsrc/common/notifications/all.inc:790
 #, c-format
 msgid "^BGPress ^F2%s^BG to steal this vehicle"
-msgstr ""
+msgstr "^BGPaina ^F2%s^BG varastaaksesi ajoneuvon"
 
 #: qcsrc/common/notifications/all.inc:791
 msgid ""
 "^F2The enemy is stealing one of your vehicles!\n"
 "^F4Stop them!"
 msgstr ""
+"^F2Vihulainen varastaa yhtä ajoneuvoistasi!\n"
+"^F4Pysäytä heidät!"
 
 #: qcsrc/common/notifications/all.inc:792
 msgid "^F2Intruder detected, disabling shields!"
-msgstr ""
+msgstr "^F2Havaittu tunkeilija, kytketään suojat pois!"
 
 #: qcsrc/common/notifications/all.qh:194
 msgid "Notification dump command only works with cl_cmd and sv_cmd."
-msgstr ""
+msgstr "Ilmoitusten heivauskäsky toimii vain: cl_cmd ja sv_cmd."
 
 #: qcsrc/common/notifications/all.qh:404 qcsrc/common/notifications/all.qh:405
 #, c-format
 msgid " (near %s)"
-msgstr ""
+msgstr " (lähellä %s)"
 
 #: qcsrc/common/notifications/all.qh:412 qcsrc/common/notifications/all.qh:413
 msgid "primary"
-msgstr ""
+msgstr "ensisijainen"
 
 #: qcsrc/common/notifications/all.qh:412 qcsrc/common/notifications/all.qh:413
 msgid "secondary"
-msgstr ""
+msgstr "toissijainen"
 
 #: qcsrc/common/notifications/all.qh:415
 msgid "point"
-msgstr ""
+msgstr "piste"
 
 #: qcsrc/common/notifications/all.qh:415
 msgid "points"
-msgstr ""
+msgstr "pisteet"
 
 #: qcsrc/common/notifications/all.qh:424
 msgid "drop flag"
-msgstr ""
+msgstr "pudota lippu"
 
 #: qcsrc/common/notifications/all.qh:425
 msgid "throw nade"
-msgstr ""
+msgstr "heitä naatti"
 
 #: qcsrc/common/notifications/all.qh:450
 #, c-format
 msgid "%s^K1 made a TRIPLE FRAG! %s^BG"
-msgstr ""
+msgstr "%s^K1 toteutti KOLMOISFRÄGIN! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:450
 #, c-format
 msgid "%s^K1 made a TRIPLE SCORE! %s^BG"
-msgstr ""
+msgstr "%s^K1 teki KOLMOISPISTEET! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:450
 msgid "TRIPLE FRAG! "
-msgstr ""
+msgstr "KOLMOISFRÄGI!"
 
 #: qcsrc/common/notifications/all.qh:451
 #, c-format
 msgid "%s^K1 made FIVE SCORES IN A ROW! %s^BG"
-msgstr ""
+msgstr "%s^K1 toteutti VIISI PISTEISIIN OIKEUTTAVAA TEKOA PUTKEEN! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:451
 #, c-format
 msgid "%s^K1 unlocked RAGE! %s^BG"
-msgstr ""
+msgstr "%s^K1 avattu ominaisuus: RAIVO! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:451
 msgid "RAGE! "
-msgstr ""
+msgstr "RAIVO!"
 
 #: qcsrc/common/notifications/all.qh:452
 #, c-format
 msgid "%s^K1 made TEN SCORES IN A ROW! %s^BG"
-msgstr ""
+msgstr "%s^K1 toteutti KYMMENEN PISTEISIIN OIKEUTTAVAA TEKOA PUTKEEN!  %s^BG"
 
 #: qcsrc/common/notifications/all.qh:452
 #, c-format
 msgid "%s^K1 started a MASSACRE! %s^BG"
-msgstr ""
+msgstr "%s^K1 aloitti TEURASTUKSEN! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:452
 msgid "MASSACRE! "
-msgstr ""
+msgstr "TEURASTUS!"
 
 #: qcsrc/common/notifications/all.qh:453
 #, c-format
 msgid "%s^K1 executed MAYHEM! %s^BG"
-msgstr ""
+msgstr "%s^K1 laittoi alulle SEKASORRON! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:453
 #, c-format
 msgid "%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG"
 msgstr ""
+"%s^K1 toteutti VIISITOISTA PISTEISIIN OIKEUTTAVAA TEKOA PUTKEEN!  %s^BG"
 
 #: qcsrc/common/notifications/all.qh:453
 msgid "MAYHEM! "
-msgstr ""
+msgstr "SEKASORTO!"
 
 #: qcsrc/common/notifications/all.qh:454
 #, c-format
 msgid "%s^K1 is a BERSERKER! %s^BG"
-msgstr ""
+msgstr "%s^K1 on RAIVOHULLU! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:454
 #, c-format
 msgid "%s^K1 made TWENTY SCORES IN A ROW! %s^BG"
 msgstr ""
+"%s^K1 toteutti KAKSIKYMMENTÄ PISTEISIIN OIKEUTTAVAA TEKOA PUTKEEN!  %s^BG"
 
 #: qcsrc/common/notifications/all.qh:454
 msgid "BERSERKER! "
-msgstr ""
+msgstr "RAIVOHULLU!"
 
 #: qcsrc/common/notifications/all.qh:455
 #, c-format
 msgid "%s^K1 inflicts CARNAGE! %s^BG"
-msgstr ""
+msgstr "%s^K1 aloitti VERILÖYLYN! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:455
 #, c-format
 msgid "%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG"
 msgstr ""
+"%s^K1 toteutti KAKSIKYMMENTÄ JA VIISI PISTEISIIN OIKEUTTAVAA TEKOA "
+"PUTKEEN! ! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:455
 msgid "CARNAGE! "
-msgstr ""
+msgstr "VERILÖYLY!"
 
 #: qcsrc/common/notifications/all.qh:456
 #, c-format
 msgid "%s^K1 made THIRTY SCORES IN A ROW! %s^BG"
 msgstr ""
+"%s^K1 toteutti KOLMEKYMMENTÄ PISTEISIIN OIKEUTTAVAA TEKOA PUTKEEN!! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:456
 #, c-format
 msgid "%s^K1 unleashes ARMAGEDDON! %s^BG"
-msgstr ""
+msgstr "%s^K1 päästi valloilleen MAAILMANLOPUN MEININGIN! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:456
 msgid "ARMAGEDDON! "
-msgstr ""
+msgstr "MAAILMANLOPUN MEININKI!"
 
 #: qcsrc/common/notifications/all.qh:463
 #, c-format
 msgid "%s(^F1Bot^BG)"
-msgstr ""
+msgstr "%s(^F1Bot^BG)"
 
 #: qcsrc/common/notifications/all.qh:465
 #, c-format
 msgid "%s(Ping ^F1%d^BG)"
-msgstr ""
+msgstr "%s(Ping ^F1%d^BG)"
 
 #: qcsrc/common/notifications/all.qh:472
 #, c-format
@@ -4373,6 +4528,8 @@ msgid ""
 "\n"
 "(Health ^1%d^BG / Armor ^2%d^BG)%s"
 msgstr ""
+"\n"
+"(Terveys ^1%d^BG / Suojaus ^2%d^BG)%s"
 
 #: qcsrc/common/notifications/all.qh:474
 #, c-format
@@ -4380,410 +4537,412 @@ msgid ""
 "\n"
 "(^F4Dead^BG)%s"
 msgstr ""
+"\n"
+"(^F4Kuollut^BG)%s"
 
 #: qcsrc/common/notifications/all.qh:495 qcsrc/common/notifications/all.qh:508
 #, c-format
 msgid "%d score spree! "
-msgstr ""
+msgstr "%d pisteputki! "
 
 #: qcsrc/common/notifications/all.qh:507
 #, c-format
 msgid "%d frag spree! "
-msgstr ""
+msgstr "%d frägiputki! "
 
 #: qcsrc/common/notifications/all.qh:520
 msgid "First blood! "
-msgstr ""
+msgstr "Ensiveri vuodatettu!"
 
 #: qcsrc/common/notifications/all.qh:520
 msgid "First score! "
-msgstr ""
+msgstr "Ensipisteet!"
 
 #: qcsrc/common/notifications/all.qh:524
 msgid "First casualty! "
-msgstr ""
+msgstr "Ensikärsijä!"
 
 #: qcsrc/common/notifications/all.qh:524
 msgid "First victim! "
-msgstr ""
+msgstr "Ensiuhri!"
 
 #: qcsrc/common/notifications/all.qh:565
 #, c-format
 msgid "%s^K1 has %d frags in a row! %s^BG"
-msgstr ""
+msgstr "%s^K1 pisti %d frägiä putkeen! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:566
 #, c-format
 msgid "%s^K1 made %d scores in a row! %s^BG"
-msgstr ""
+msgstr "%s^K1 laittoi %d kirjausta putkeen! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:584
 #, c-format
 msgid "%s^K1 drew first blood! %s^BG"
-msgstr ""
+msgstr "%s^K1 vuodatutti ensiveret! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:585
 #, c-format
 msgid "%s^K1 got the first score! %s^BG"
-msgstr ""
+msgstr "%s^K1 saavutti ensipisteet! %s^BG"
 
 #: qcsrc/common/notifications/all.qh:601
 #, c-format
 msgid ", ending their %d frag spree"
-msgstr ""
+msgstr ", päättää %d frägiputkensa"
 
 #: qcsrc/common/notifications/all.qh:602
 #, c-format
 msgid ", ending their %d score spree"
-msgstr ""
+msgstr ", päättää %d pisteputkensa"
 
 #: qcsrc/common/notifications/all.qh:616
 #, c-format
 msgid ", losing their %d frag spree"
-msgstr ""
+msgstr ", menettää %d frägiputkensa"
 
 #: qcsrc/common/notifications/all.qh:617
 #, c-format
 msgid ", losing their %d score spree"
-msgstr ""
+msgstr ", menettää %d pisteputkensa"
 
 #: qcsrc/common/notifications/all.qh:642
 #, c-format
 msgid " with %d %s"
-msgstr ""
+msgstr "täten %d %s"
 
 #: qcsrc/common/teams.qh:31
 msgid "TEAM^Red"
-msgstr ""
+msgstr "JOUKKUE^Punainen"
 
 #: qcsrc/common/teams.qh:32
 msgid "TEAM^Blue"
-msgstr ""
+msgstr "JOUKKUE^Sininen"
 
 #: qcsrc/common/teams.qh:33
 msgid "TEAM^Yellow"
-msgstr ""
+msgstr "JOUKKUE^Keltainen"
 
 #: qcsrc/common/teams.qh:34
 msgid "TEAM^Pink"
-msgstr ""
+msgstr "JOUKKUE^Vaaleanpunainen"
 
 #: qcsrc/common/teams.qh:35
 msgid "Team"
-msgstr ""
+msgstr "Joukkue"
 
 #: qcsrc/common/teams.qh:36
 msgid "Neutral"
-msgstr ""
+msgstr "Puolueeton"
 
 #: qcsrc/common/teams.qh:39
 msgid "KEY^Red"
-msgstr ""
+msgstr "AVAIN^Punainen"
 
 #: qcsrc/common/teams.qh:40
 msgid "KEY^Blue"
-msgstr ""
+msgstr "AVAIN^Sininen"
 
 #: qcsrc/common/teams.qh:41
 msgid "KEY^Yellow"
-msgstr ""
+msgstr "AVAIN^Keltainen"
 
 #: qcsrc/common/teams.qh:42
 msgid "KEY^Pink"
-msgstr ""
+msgstr "AVAIN^Vaaleanpunainen"
 
 #: qcsrc/common/teams.qh:43
 msgid "FLAG^Red"
-msgstr ""
+msgstr "LIPPU^Punainen"
 
 #: qcsrc/common/teams.qh:44
 msgid "FLAG^Blue"
-msgstr ""
+msgstr "LIPPU^Sininen"
 
 #: qcsrc/common/teams.qh:45
 msgid "FLAG^Yellow"
-msgstr ""
+msgstr "LIPPU^Keltainen"
 
 #: qcsrc/common/teams.qh:46
 msgid "FLAG^Pink"
-msgstr ""
+msgstr "LIPPU^Vaaleanpunainen"
 
 #: qcsrc/common/teams.qh:47
 msgid "GENERATOR^Red"
-msgstr ""
+msgstr "GENERAATTORI^Punainen"
 
 #: qcsrc/common/teams.qh:48
 msgid "GENERATOR^Blue"
-msgstr ""
+msgstr "GENERAATTORI^Sininen"
 
 #: qcsrc/common/teams.qh:49
 msgid "GENERATOR^Yellow"
-msgstr ""
+msgstr "GENERAATTORI^Keltainen"
 
 #: qcsrc/common/teams.qh:50
 msgid "GENERATOR^Pink"
-msgstr ""
+msgstr "GENERAATTORI^Vaaleanpunainen"
 
 #: qcsrc/common/turrets/all.qh:96
 msgid "Turrets dump command only works with sv_cmd."
-msgstr ""
+msgstr "Tykkitornien heivaamiskäsky toimii vain tämän kautta: sv_cmd."
 
 #: qcsrc/common/turrets/cl_turrets.qc:125
 #, c-format
 msgid "%s under attack!"
-msgstr ""
+msgstr "%s hyökkäyksen alaisena!"
 
 #: qcsrc/common/turrets/turret.qh:11
 msgid "Turret"
-msgstr ""
+msgstr "Tykkitorni"
 
 #: qcsrc/common/turrets/turret/ewheel.qh:15
 msgid "eWheel Turret"
-msgstr ""
+msgstr "eWheel-tykkitorni"
 
 #: qcsrc/common/turrets/turret/ewheel_weapon.qh:7
 msgid "eWheel"
-msgstr ""
+msgstr "e-Wheel"
 
 #: qcsrc/common/turrets/turret/flac.qh:13
 msgid "FLAC Cannon"
-msgstr ""
+msgstr "FLAC-tykki"
 
 #: qcsrc/common/turrets/turret/flac_weapon.qh:9
 msgid "FLAC"
-msgstr ""
+msgstr "FLAC"
 
 #: qcsrc/common/turrets/turret/fusionreactor.qh:11
 msgid "Fusion Reactor"
-msgstr ""
+msgstr "Fuusioreaktori"
 
 #: qcsrc/common/turrets/turret/hellion.qh:13
 msgid "Hellion Missile Turret"
-msgstr ""
+msgstr "Hellion-ohjustykkitorni"
 
 #: qcsrc/common/turrets/turret/hellion_weapon.qh:7
 msgid "Hellion"
-msgstr ""
+msgstr "Hellion"
 
 #: qcsrc/common/turrets/turret/hk.qh:15
 msgid "Hunter-Killer Turret"
-msgstr ""
+msgstr "Hunter-Killer-tykkitorni"
 
 #: qcsrc/common/turrets/turret/hk_weapon.qh:7
 msgid "Hunter-Killer"
-msgstr ""
+msgstr "Hunter-Killer"
 
 #: qcsrc/common/turrets/turret/machinegun.qh:13
 msgid "Machinegun Turret"
-msgstr ""
+msgstr "Machinegun -koneaseellinen tykkitorni"
 
 #: qcsrc/common/turrets/turret/machinegun_weapon.qh:7
 msgid "Machinegun"
-msgstr ""
+msgstr "Machinegun-konease"
 
 #: qcsrc/common/turrets/turret/mlrs.qh:13
 msgid "MLRS Turret"
-msgstr ""
+msgstr "MLRS-tykkitorni"
 
 #: qcsrc/common/turrets/turret/mlrs_weapon.qh:7
 msgid "MLRS"
-msgstr ""
+msgstr "MLRS"
 
 #: qcsrc/common/turrets/turret/phaser.qh:13
 msgid "Phaser Cannon"
-msgstr ""
+msgstr "Vaiheistykki"
 
 #: qcsrc/common/turrets/turret/phaser_weapon.qh:7
 msgid "Phaser"
-msgstr ""
+msgstr "Vaiheistykki"
 
 #: qcsrc/common/turrets/turret/plasma.qh:13
 msgid "Plasma Cannon"
-msgstr ""
+msgstr "Plasmatykki"
 
 #: qcsrc/common/turrets/turret/plasma_dual.qh:8
 msgid "Dual plasma"
-msgstr ""
+msgstr "Kaksoisplasma"
 
 #: qcsrc/common/turrets/turret/plasma_dual.qh:20
 msgid "Dual Plasma Cannon"
-msgstr ""
+msgstr "Kaksoisplasmatykki"
 
 #: qcsrc/common/turrets/turret/plasma_weapon.qh:7
 msgid "Plasma"
-msgstr ""
+msgstr "Plasma"
 
 #: qcsrc/common/turrets/turret/tesla.qh:13
 #: qcsrc/common/turrets/turret/tesla_weapon.qh:7
 msgid "Tesla Coil"
-msgstr ""
+msgstr "Tesla-käämi"
 
 #: qcsrc/common/turrets/turret/walker.qh:15
 msgid "Walker Turret"
-msgstr ""
+msgstr "Walker-tykkitorni"
 
 #: qcsrc/common/turrets/turret/walker_weapon.qh:7
 msgid "Walker"
-msgstr ""
+msgstr "Walker"
 
 #: qcsrc/common/util.qc:1403
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:173
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:183
 msgid "Male"
-msgstr ""
+msgstr "Miespuolinen"
 
 #: qcsrc/common/util.qc:1404
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:182
 msgid "Female"
-msgstr ""
+msgstr "Naispuolinen"
 
 #: qcsrc/common/util.qc:1405
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:171
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:184
 msgid "Undisclosed"
-msgstr ""
+msgstr "Epäselvä"
 
 #: qcsrc/common/util.qc:1452
 msgid "<KEY NOT FOUND>"
-msgstr ""
+msgstr "<KEY NOT FOUND>"
 
 #: qcsrc/common/util.qc:1453
 msgid "<UNKNOWN KEYNUM>"
-msgstr ""
+msgstr "<UNKNOWN KEYNUM>"
 
 #: qcsrc/common/util.qc:1458
 msgid "TAB"
-msgstr ""
+msgstr "TAB"
 
 #: qcsrc/common/util.qc:1459 qcsrc/common/util.qc:1530
 #, c-format
 msgid "ENTER"
-msgstr ""
+msgstr "ENTER"
 
 #: qcsrc/common/util.qc:1460
 msgid "ESCAPE"
-msgstr ""
+msgstr "ESCAPE"
 
 #: qcsrc/common/util.qc:1461
 msgid "SPACE"
-msgstr ""
+msgstr "VÄLILYÖNTI"
 
 #: qcsrc/common/util.qc:1463
 msgid "BACKSPACE"
-msgstr ""
+msgstr "BACKSPACE-taakseaskellusnäppäin"
 
 #: qcsrc/common/util.qc:1464 qcsrc/common/util.qc:1521
 #, c-format
 msgid "UPARROW"
-msgstr ""
+msgstr "NUOLI YLÖSPÄIN"
 
 #: qcsrc/common/util.qc:1465 qcsrc/common/util.qc:1516
 #, c-format
 msgid "DOWNARROW"
-msgstr ""
+msgstr "NUOLI ALASPÄIN"
 
 #: qcsrc/common/util.qc:1466 qcsrc/common/util.qc:1518
 #, c-format
 msgid "LEFTARROW"
-msgstr ""
+msgstr "NUOLI VASEMMALLE"
 
 #: qcsrc/common/util.qc:1467 qcsrc/common/util.qc:1519
 #, c-format
 msgid "RIGHTARROW"
-msgstr ""
+msgstr "NUOLI OIKEALLE"
 
 #: qcsrc/common/util.qc:1469
 msgid "ALT"
-msgstr ""
+msgstr "ALT"
 
 #: qcsrc/common/util.qc:1470
 msgid "CTRL"
-msgstr ""
+msgstr "CTRL"
 
 #: qcsrc/common/util.qc:1471
 msgid "SHIFT"
-msgstr ""
+msgstr "SHIFT-vaihtonäppäin"
 
 #: qcsrc/common/util.qc:1473 qcsrc/common/util.qc:1514
 #, c-format
 msgid "INS"
-msgstr ""
+msgstr "INS"
 
 #: qcsrc/common/util.qc:1474 qcsrc/common/util.qc:1524
 #, c-format
 msgid "DEL"
-msgstr ""
+msgstr "DEL"
 
 #: qcsrc/common/util.qc:1475 qcsrc/common/util.qc:1517
 #, c-format
 msgid "PGDN"
-msgstr ""
+msgstr "PGDN"
 
 #: qcsrc/common/util.qc:1476 qcsrc/common/util.qc:1522
 #, c-format
 msgid "PGUP"
-msgstr ""
+msgstr "PGUP"
 
 #: qcsrc/common/util.qc:1477 qcsrc/common/util.qc:1520
 #, c-format
 msgid "HOME"
-msgstr ""
+msgstr "HOME"
 
 #: qcsrc/common/util.qc:1478 qcsrc/common/util.qc:1515
 #, c-format
 msgid "END"
-msgstr ""
+msgstr "END"
 
 #: qcsrc/common/util.qc:1480
 msgid "PAUSE"
-msgstr ""
+msgstr "PAUSE"
 
 #: qcsrc/common/util.qc:1482
 msgid "NUMLOCK"
-msgstr ""
+msgstr "NUMLOCK"
 
 #: qcsrc/common/util.qc:1483
 msgid "CAPSLOCK"
-msgstr ""
+msgstr "CAPSLOCK"
 
 #: qcsrc/common/util.qc:1484
 msgid "SCROLLOCK"
-msgstr ""
+msgstr "SCROLLOCK"
 
 #: qcsrc/common/util.qc:1486
 msgid "SEMICOLON"
-msgstr ""
+msgstr "PUOLIPISTE"
 
 #: qcsrc/common/util.qc:1487
 msgid "TILDE"
-msgstr ""
+msgstr "TILDE-aaltoviiva"
 
 #: qcsrc/common/util.qc:1488
 msgid "BACKQUOTE"
-msgstr ""
+msgstr "BACKQUOTE-taaksepäinlainaus"
 
 #: qcsrc/common/util.qc:1489
 msgid "QUOTE"
-msgstr ""
+msgstr "QUOTE-lainausmerkki"
 
 #: qcsrc/common/util.qc:1490
 msgid "APOSTROPHE"
-msgstr ""
+msgstr "HEITTOMERKKI"
 
 #: qcsrc/common/util.qc:1491
 msgid "BACKSLASH"
-msgstr ""
+msgstr "KENOVIIVA"
 
 #: qcsrc/common/util.qc:1499
 #, c-format
 msgid "F%d"
-msgstr ""
+msgstr "F%d"
 
 #: qcsrc/common/util.qc:1509
 #, c-format
 msgid "KP_%d"
-msgstr ""
+msgstr "KP_%d"
 
 #: qcsrc/common/util.qc:1514 qcsrc/common/util.qc:1515
 #: qcsrc/common/util.qc:1516 qcsrc/common/util.qc:1517
@@ -4796,74 +4955,74 @@ msgstr ""
 #: qcsrc/common/util.qc:1530 qcsrc/common/util.qc:1531
 #, c-format
 msgid "KP_%s"
-msgstr ""
+msgstr "KP_%s"
 
 #: qcsrc/common/util.qc:1523
 #, c-format
 msgid "PERIOD"
-msgstr ""
+msgstr "PISTE"
 
 #: qcsrc/common/util.qc:1525
 #, c-format
 msgid "DIVIDE"
-msgstr ""
+msgstr "JAKOMERKKI"
 
 #: qcsrc/common/util.qc:1526
 #, c-format
 msgid "SLASH"
-msgstr ""
+msgstr "KENOVIIVA ETEEN"
 
 #: qcsrc/common/util.qc:1527
 #, c-format
 msgid "MULTIPLY"
-msgstr ""
+msgstr "KERTOMERKKI"
 
 #: qcsrc/common/util.qc:1528
 #, c-format
 msgid "MINUS"
-msgstr ""
+msgstr "MIINUS"
 
 #: qcsrc/common/util.qc:1529
 #, c-format
 msgid "PLUS"
-msgstr ""
+msgstr "PLUS"
 
 #: qcsrc/common/util.qc:1531
 #, c-format
 msgid "EQUALS"
-msgstr ""
+msgstr "YHTÄKUIN"
 
 #: qcsrc/common/util.qc:1536
 msgid "PRINTSCREEN"
-msgstr ""
+msgstr "PRINTSCREEN-näppäin"
 
 #: qcsrc/common/util.qc:1539
 #, c-format
 msgid "MOUSE%d"
-msgstr ""
+msgstr "HIIRI%d"
 
 #: qcsrc/common/util.qc:1541
 msgid "MWHEELUP"
-msgstr ""
+msgstr "HIIRIRULLA YLÖS"
 
 #: qcsrc/common/util.qc:1542
 msgid "MWHEELDOWN"
-msgstr ""
+msgstr "HIIRIRULLA ALAS"
 
 #: qcsrc/common/util.qc:1545
 #, c-format
 msgid "JOY%d"
-msgstr ""
+msgstr "SAUVA%d"
 
 #: qcsrc/common/util.qc:1548
 #, c-format
 msgid "AUX%d"
-msgstr ""
+msgstr "AUX%d"
 
 #: qcsrc/common/util.qc:1555
 #, c-format
 msgid "DPAD_UP"
-msgstr ""
+msgstr "D-PADI_YLÖS"
 
 #: qcsrc/common/util.qc:1555 qcsrc/common/util.qc:1556
 #: qcsrc/common/util.qc:1557 qcsrc/common/util.qc:1558
@@ -4877,190 +5036,190 @@ msgstr ""
 #: qcsrc/common/util.qc:1573 qcsrc/common/util.qc:1574
 #, c-format
 msgid "X360_%s"
-msgstr ""
+msgstr "X360_%s"
 
 #: qcsrc/common/util.qc:1556
 #, c-format
 msgid "DPAD_DOWN"
-msgstr ""
+msgstr "D-PADI_ALAS"
 
 #: qcsrc/common/util.qc:1557
 #, c-format
 msgid "DPAD_LEFT"
-msgstr ""
+msgstr "D-PADI_VASEN"
 
 #: qcsrc/common/util.qc:1558
 #, c-format
 msgid "DPAD_RIGHT"
-msgstr ""
+msgstr "D-PADI_OIKEA"
 
 #: qcsrc/common/util.qc:1559
 #, c-format
 msgid "START"
-msgstr ""
+msgstr "START-nappi"
 
 #: qcsrc/common/util.qc:1560
 #, c-format
 msgid "BACK"
-msgstr ""
+msgstr "BACK-takaisinnappi"
 
 #: qcsrc/common/util.qc:1561
 #, c-format
 msgid "LEFT_THUMB"
-msgstr ""
+msgstr "VASEN_PEUKALO"
 
 #: qcsrc/common/util.qc:1562
 #, c-format
 msgid "RIGHT_THUMB"
-msgstr ""
+msgstr "OIKEA_PEUKALO"
 
 #: qcsrc/common/util.qc:1563
 #, c-format
 msgid "LEFT_SHOULDER"
-msgstr ""
+msgstr "VASEN_OLKAPÄÄ"
 
 #: qcsrc/common/util.qc:1564
 #, c-format
 msgid "RIGHT_SHOULDER"
-msgstr ""
+msgstr "OIKEA_OLKAPÄÄ"
 
 #: qcsrc/common/util.qc:1565
 #, c-format
 msgid "LEFT_TRIGGER"
-msgstr ""
+msgstr "VASEN_LIIPAISIN"
 
 #: qcsrc/common/util.qc:1566
 #, c-format
 msgid "RIGHT_TRIGGER"
-msgstr ""
+msgstr "OIKEA_LIIPAISIN"
 
 #: qcsrc/common/util.qc:1567
 #, c-format
 msgid "LEFT_THUMB_UP"
-msgstr ""
+msgstr "VASEN_PEUKALO_YLÖS"
 
 #: qcsrc/common/util.qc:1568
 #, c-format
 msgid "LEFT_THUMB_DOWN"
-msgstr ""
+msgstr "VASEN_PEUKALO_ALAS"
 
 #: qcsrc/common/util.qc:1569
 #, c-format
 msgid "LEFT_THUMB_LEFT"
-msgstr ""
+msgstr "VASEN_PEUKALO_VASEN"
 
 #: qcsrc/common/util.qc:1570
 #, c-format
 msgid "LEFT_THUMB_RIGHT"
-msgstr ""
+msgstr "VASEN_PEUKALO_OIKEA"
 
 #: qcsrc/common/util.qc:1571
 #, c-format
 msgid "RIGHT_THUMB_UP"
-msgstr ""
+msgstr "OIKEA_PEUKALO_YLÖS"
 
 #: qcsrc/common/util.qc:1572
 #, c-format
 msgid "RIGHT_THUMB_DOWN"
-msgstr ""
+msgstr "OIKEA_PEUKALO_ALAS"
 
 #: qcsrc/common/util.qc:1573
 #, c-format
 msgid "RIGHT_THUMB_LEFT"
-msgstr ""
+msgstr "OIKEA_PEUKALO_VASEN"
 
 #: qcsrc/common/util.qc:1574
 #, c-format
 msgid "RIGHT_THUMB_RIGHT"
-msgstr ""
+msgstr "OIKEA_PEUKALO_OIKEA"
 
 #: qcsrc/common/util.qc:1584 qcsrc/common/util.qc:1585
 #: qcsrc/common/util.qc:1586 qcsrc/common/util.qc:1587
 #, c-format
 msgid "JOY_%s"
-msgstr ""
+msgstr "Sauvaohjain_%s"
 
 #: qcsrc/common/util.qc:1584
 #, c-format
 msgid "UP"
-msgstr ""
+msgstr "YLÖS"
 
 #: qcsrc/common/util.qc:1585
 #, c-format
 msgid "DOWN"
-msgstr ""
+msgstr "ALAS"
 
 #: qcsrc/common/util.qc:1586
 #, c-format
 msgid "LEFT"
-msgstr ""
+msgstr "VASEN"
 
 #: qcsrc/common/util.qc:1587
 #, c-format
 msgid "RIGHT"
-msgstr ""
+msgstr "OIKEA"
 
 #: qcsrc/common/util.qc:1593
 #, c-format
 msgid "MIDINOTE%d"
-msgstr ""
+msgstr "MIDIHUOMAUTUS%d"
 
 #: qcsrc/common/vehicles/cl_vehicles.qc:190
 #, c-format
 msgid "Press %s"
-msgstr ""
+msgstr "Paina %s"
 
 #: qcsrc/common/vehicles/vehicle/bumblebee.qc:947
 msgid "No right gunner!"
-msgstr ""
+msgstr "Ei oikean ammuntaa!"
 
 #: qcsrc/common/vehicles/vehicle/bumblebee.qc:953
 msgid "No left gunner!"
-msgstr ""
+msgstr "Ei vasemman ammuntaa!"
 
 #: qcsrc/common/vehicles/vehicle/bumblebee.qh:19
 msgid "Bumblebee"
-msgstr ""
+msgstr "Bumblebee"
 
 #: qcsrc/common/vehicles/vehicle/racer.qh:19
 msgid "Racer"
-msgstr ""
+msgstr "Kilpuri"
 
 #: qcsrc/common/vehicles/vehicle/racer_weapon.qh:9
 msgid "Racer cannon"
-msgstr ""
+msgstr "Kilpuritykki"
 
 #: qcsrc/common/vehicles/vehicle/raptor.qh:19
 msgid "Raptor"
-msgstr ""
+msgstr "Raptor"
 
 #: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:9
 msgid "Raptor cannon"
-msgstr ""
+msgstr "Raptor-tykki"
 
 #: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:17
 msgid "Raptor bomb"
-msgstr ""
+msgstr "Raptor-pommi"
 
 #: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:25
 msgid "Raptor flare"
-msgstr ""
+msgstr "Raptor-soihtu"
 
 #: qcsrc/common/vehicles/vehicle/spiderbot.qh:19
 msgid "Spiderbot"
-msgstr ""
+msgstr "Hämisbotti"
 
 #: qcsrc/common/weapons/all.qh:77
 msgid "Weapons dump command only works with sv_cmd."
-msgstr ""
+msgstr "Aseiden heivauskäsky toimii vain täten: sv_cmd."
 
 #: qcsrc/common/weapons/weapon/arc.qh:18
 msgid "Arc"
-msgstr ""
+msgstr "Arc"
 
 #: qcsrc/common/weapons/weapon/blaster.qh:18
 msgid "Blaster"
-msgstr ""
+msgstr "Läjäytin"
 
 #: qcsrc/common/weapons/weapon/crylink.qh:18
 msgid "Crylink"
@@ -5068,7 +5227,7 @@ msgstr "Crylink"
 
 #: qcsrc/common/weapons/weapon/devastator.qh:18
 msgid "Devastator"
-msgstr ""
+msgstr "Hävittäjä"
 
 #: qcsrc/common/weapons/weapon/electro.qh:18
 msgid "Electro"
@@ -5092,7 +5251,7 @@ msgstr "Grabbling Hook"
 
 #: qcsrc/common/weapons/weapon/machinegun.qh:18
 msgid "MachineGun"
-msgstr ""
+msgstr "MachineGun-konease"
 
 #: qcsrc/common/weapons/weapon/minelayer.qh:18
 msgid "Mine Layer"
@@ -5116,7 +5275,7 @@ msgstr "T.A.G. Seeker"
 
 #: qcsrc/common/weapons/weapon/shockwave.qh:18
 msgid "Shockwave"
-msgstr ""
+msgstr "Shockwave-paineaalto"
 
 #: qcsrc/common/weapons/weapon/shotgun.qh:18
 msgid "Shotgun"
@@ -5129,196 +5288,196 @@ msgstr "@!#%'n tuuba"
 
 #: qcsrc/common/weapons/weapon/vaporizer.qh:19
 msgid "Vaporizer"
-msgstr ""
+msgstr "Höyrystäjä"
 
 #: qcsrc/common/weapons/weapon/vortex.qh:19
 msgid "Vortex"
-msgstr ""
+msgstr "Pyörremyrsky"
 
 #: qcsrc/lib/counting.qh:9
 #, c-format
 msgid "CI_DEC^%s years"
-msgstr ""
+msgstr "CI_DEC^%s vuotta"
 
 #: qcsrc/lib/counting.qh:12
 #, c-format
 msgid "CI_ZER^%d years"
-msgstr ""
+msgstr "CI_ZER^%d vuotta"
 
 #: qcsrc/lib/counting.qh:13
 #, c-format
 msgid "CI_FIR^%d year"
-msgstr ""
+msgstr "CI_FIR^%d vuosi"
 
 #: qcsrc/lib/counting.qh:14
 #, c-format
 msgid "CI_SEC^%d years"
-msgstr ""
+msgstr "CI_SEC^%d vuotta"
 
 #: qcsrc/lib/counting.qh:15
 #, c-format
 msgid "CI_THI^%d years"
-msgstr ""
+msgstr "CI_THI^%d vuotta"
 
 #: qcsrc/lib/counting.qh:16
 #, c-format
 msgid "CI_MUL^%d years"
-msgstr ""
+msgstr "CI_MUL^%d vuotta"
 
 #: qcsrc/lib/counting.qh:18
 #, c-format
 msgid "CI_DEC^%s weeks"
-msgstr ""
+msgstr "CI_DEC^%s viikkoa"
 
 #: qcsrc/lib/counting.qh:21
 #, c-format
 msgid "CI_ZER^%d weeks"
-msgstr ""
+msgstr "CI_ZER^%d viikkoa"
 
 #: qcsrc/lib/counting.qh:22
 #, c-format
 msgid "CI_FIR^%d week"
-msgstr ""
+msgstr "CI_FIR^%d viikko"
 
 #: qcsrc/lib/counting.qh:23
 #, c-format
 msgid "CI_SEC^%d weeks"
-msgstr ""
+msgstr "CI_SEC^%d viikkoa"
 
 #: qcsrc/lib/counting.qh:24
 #, c-format
 msgid "CI_THI^%d weeks"
-msgstr ""
+msgstr "CI_THI^%d viikkoa"
 
 #: qcsrc/lib/counting.qh:25
 #, c-format
 msgid "CI_MUL^%d weeks"
-msgstr ""
+msgstr "CI_MUL^%d viikkoa"
 
 #: qcsrc/lib/counting.qh:27
 #, c-format
 msgid "CI_DEC^%s days"
-msgstr ""
+msgstr "CI_DEC^%s päivää"
 
 #: qcsrc/lib/counting.qh:30
 #, c-format
 msgid "CI_ZER^%d days"
-msgstr ""
+msgstr "CI_ZER^%d päivää"
 
 #: qcsrc/lib/counting.qh:31
 #, c-format
 msgid "CI_FIR^%d day"
-msgstr ""
+msgstr "CI_FIR^%d päivä"
 
 #: qcsrc/lib/counting.qh:32
 #, c-format
 msgid "CI_SEC^%d days"
-msgstr ""
+msgstr "CI_SEC^%d päivää"
 
 #: qcsrc/lib/counting.qh:33
 #, c-format
 msgid "CI_THI^%d days"
-msgstr ""
+msgstr "CI_THI^%d päivää"
 
 #: qcsrc/lib/counting.qh:34
 #, c-format
 msgid "CI_MUL^%d days"
-msgstr ""
+msgstr "CI_MUL^%d päivää"
 
 #: qcsrc/lib/counting.qh:36
 #, c-format
 msgid "CI_DEC^%s hours"
-msgstr ""
+msgstr "CI_DEC^%s tuntia"
 
 #: qcsrc/lib/counting.qh:39
 #, c-format
 msgid "CI_ZER^%d hours"
-msgstr ""
+msgstr "CI_ZER^%d tuntia"
 
 #: qcsrc/lib/counting.qh:40
 #, c-format
 msgid "CI_FIR^%d hour"
-msgstr ""
+msgstr "CI_FIR^%d tunti"
 
 #: qcsrc/lib/counting.qh:41
 #, c-format
 msgid "CI_SEC^%d hours"
-msgstr ""
+msgstr "CI_SEC^%d tuntia"
 
 #: qcsrc/lib/counting.qh:42
 #, c-format
 msgid "CI_THI^%d hours"
-msgstr ""
+msgstr "CI_THI^%d tuntia"
 
 #: qcsrc/lib/counting.qh:43
 #, c-format
 msgid "CI_MUL^%d hours"
-msgstr ""
+msgstr "CI_MUL^%d tuntia"
 
 #: qcsrc/lib/counting.qh:46
 #, c-format
 msgid "CI_DEC^%s minutes"
-msgstr ""
+msgstr "CI_DEC^%s minuuttia"
 
 #: qcsrc/lib/counting.qh:49
 #, c-format
 msgid "CI_ZER^%d minutes"
-msgstr ""
+msgstr "CI_ZER^%d minuuttia"
 
 #: qcsrc/lib/counting.qh:50
 #, c-format
 msgid "CI_FIR^%d minute"
-msgstr ""
+msgstr "CI_FIR^%d minuutti"
 
 #: qcsrc/lib/counting.qh:51
 #, c-format
 msgid "CI_SEC^%d minutes"
-msgstr ""
+msgstr "CI_SEC^%d minuuttia"
 
 #: qcsrc/lib/counting.qh:52
 #, c-format
 msgid "CI_THI^%d minutes"
-msgstr ""
+msgstr "CI_THI^%d minuuttia"
 
 #: qcsrc/lib/counting.qh:53
 #, c-format
 msgid "CI_MUL^%d minutes"
-msgstr ""
+msgstr "CI_MUL^%d minuuttia"
 
 #: qcsrc/lib/counting.qh:55
 #, c-format
 msgid "CI_DEC^%s seconds"
-msgstr ""
+msgstr "CI_DEC^%s sekuntia"
 
 #: qcsrc/lib/counting.qh:58
 #, c-format
 msgid "CI_ZER^%d seconds"
-msgstr ""
+msgstr "CI_ZER^%d sekuntia"
 
 #: qcsrc/lib/counting.qh:59
 #, c-format
 msgid "CI_FIR^%d second"
-msgstr ""
+msgstr "CI_FIR^%d sekunti"
 
 #: qcsrc/lib/counting.qh:60
 #, c-format
 msgid "CI_SEC^%d seconds"
-msgstr ""
+msgstr "CI_SEC^%d seconds"
 
 #: qcsrc/lib/counting.qh:61
 #, c-format
 msgid "CI_THI^%d seconds"
-msgstr ""
+msgstr "CI_THI^%d sekuntia"
 
 #: qcsrc/lib/counting.qh:62
 #, c-format
 msgid "CI_MUL^%d seconds"
-msgstr ""
+msgstr "CI_MUL^%d sekuntia"
 
 #: qcsrc/lib/counting.qh:79
 #, c-format
 msgid "%dst"
-msgstr ""
+msgstr "%dst"
 
 #: qcsrc/lib/counting.qh:80
 #, c-format
@@ -5337,7 +5496,7 @@ msgstr "%dth"
 
 #: qcsrc/lib/oo.qh:330
 msgid "No description"
-msgstr ""
+msgstr "Ei kuvausta"
 
 #: qcsrc/lib/spawnfunc.qh:240
 #, c-format
@@ -5345,40 +5504,43 @@ msgid ""
 "Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, "
 "please file an issue."
 msgstr ""
+"Oliokenttä %s.%s (%s) ei ole valkoluetteloitu. Mikäli uskot tämän olevan "
+"virhe, ole hyvä ja ilmoita siitä."
 
 #: qcsrc/lib/string.qh:81
 #, c-format
 msgid "%d days, %02d:%02d:%02d"
-msgstr ""
+msgstr "%d päivää, %02d:%02d:%02d"
 
 #: qcsrc/lib/string.qh:82
 #, c-format
 msgid "%02d:%02d:%02d"
-msgstr ""
+msgstr "%02d:%02d:%02d"
 
 #: qcsrc/menu/command/menu_cmd.qc:48
 msgid "Usage: menu_cmd command..., where possible commands are:"
-msgstr ""
+msgstr "Käyttö: menu_cmd command..., johon mahdollisest käskyt ovat:"
 
 #: qcsrc/menu/command/menu_cmd.qc:49
 msgid "  sync - reloads all cvars on the current menu page"
-msgstr ""
+msgstr "  sync - uudelleenlataa kaiken nykyisellä valikkosivulla"
 
 #: qcsrc/menu/command/menu_cmd.qc:50
 msgid "  directmenu ITEM - select a menu item as main item"
-msgstr ""
+msgstr "  directmenu ITEM - valitse valikkokohde pääkohteeksi"
 
 #: qcsrc/menu/command/menu_cmd.qc:51
 msgid "  dumptree - dump the state of the menu as a tree to the console"
-msgstr ""
+msgstr "  dumptree - heivaa valikon tila päätteeseen puu-oksarakenteisena"
 
 #: qcsrc/menu/command/menu_cmd.qc:81
 msgid "Available options:"
-msgstr ""
+msgstr "Mahdolliset vaihtoehdot:"
 
 #: qcsrc/menu/command/menu_cmd.qc:130
 msgid "Invalid command. For a list of supported commands, try menu_cmd help."
 msgstr ""
+"Epäkelpo käsky. Tuettuja käskyjä katsellaksesi, kokeile: menu_cmd help."
 
 #: qcsrc/menu/item/listbox.qc:413
 #, c-format
@@ -5399,183 +5561,183 @@ msgstr "Taso %d: %s"
 
 #: qcsrc/menu/xonotic/credits.qc:4
 msgid "Core Team"
-msgstr ""
+msgstr "Ydinjoukkue"
 
 #: qcsrc/menu/xonotic/credits.qc:16
 msgid "Extended Team"
-msgstr ""
+msgstr "Laajennettu joukkue"
 
 #: qcsrc/menu/xonotic/credits.qc:48
 msgid "Website"
-msgstr ""
+msgstr "Verkkosivu"
 
 #: qcsrc/menu/xonotic/credits.qc:53
 msgid "Stats"
-msgstr ""
+msgstr "Tilastot"
 
 #: qcsrc/menu/xonotic/credits.qc:57
 msgid "Art"
-msgstr ""
+msgstr "Taide"
 
 #: qcsrc/menu/xonotic/credits.qc:65
 msgid "Animation"
-msgstr ""
+msgstr "Animaatio"
 
 #: qcsrc/menu/xonotic/credits.qc:69
 msgid "Level Design"
-msgstr ""
+msgstr "Kenttäsuunnittelu"
 
 #: qcsrc/menu/xonotic/credits.qc:92
 msgid "Music / Sound FX"
-msgstr ""
+msgstr "Musiikki / ääniefektit"
 
 #: qcsrc/menu/xonotic/credits.qc:108
 msgid "Game Code"
-msgstr ""
+msgstr "Pelin ohjelmakoodi"
 
 #: qcsrc/menu/xonotic/credits.qc:116
 msgid "Marketing / PR"
-msgstr ""
+msgstr "Markkinointi / PR"
 
 #: qcsrc/menu/xonotic/credits.qc:122
 msgid "Legal"
-msgstr ""
+msgstr "Lakisääteiset asiat"
 
 #: qcsrc/menu/xonotic/credits.qc:127
 msgid "Game Engine"
-msgstr ""
+msgstr "Pelimoottori"
 
 #: qcsrc/menu/xonotic/credits.qc:131
 msgid "Engine Additions"
-msgstr ""
+msgstr "Moottorin lisät"
 
 #: qcsrc/menu/xonotic/credits.qc:136
 msgid "Compiler"
-msgstr ""
+msgstr "Koonti"
 
 #: qcsrc/menu/xonotic/credits.qc:142
 msgid "Other Active Contributors"
-msgstr ""
+msgstr "Muita aktiivisia panoksensa antajia"
 
 #: qcsrc/menu/xonotic/credits.qc:149
 msgid "Translators"
-msgstr ""
+msgstr "Kääntäjät"
 
 #: qcsrc/menu/xonotic/credits.qc:151
 msgid "Asturian"
-msgstr ""
+msgstr "Asturian-kieli"
 
 #: qcsrc/menu/xonotic/credits.qc:156
 msgid "Belarusian"
-msgstr ""
+msgstr "Valko-venäjä"
 
 #: qcsrc/menu/xonotic/credits.qc:159
 msgid "Bulgarian"
-msgstr ""
+msgstr "Bulgaria"
 
 #: qcsrc/menu/xonotic/credits.qc:166
 msgid "Chinese (China)"
-msgstr ""
+msgstr "Kiina (Kiinassa)"
 
 #: qcsrc/menu/xonotic/credits.qc:172
 msgid "Chinese (Taiwan)"
-msgstr ""
+msgstr "Kiina (Taiwan)"
 
 #: qcsrc/menu/xonotic/credits.qc:177
 msgid "Cornish"
-msgstr ""
+msgstr "Korni"
 
 #: qcsrc/menu/xonotic/credits.qc:180
 msgid "Czech"
-msgstr ""
+msgstr "Tsekki"
 
 #: qcsrc/menu/xonotic/credits.qc:185
 msgid "Dutch"
-msgstr ""
+msgstr "Hollanti"
 
 #: qcsrc/menu/xonotic/credits.qc:192
 msgid "English (Australia)"
-msgstr ""
+msgstr "Englanti (Australiassa)"
 
 #: qcsrc/menu/xonotic/credits.qc:197
 msgid "Finnish"
-msgstr ""
+msgstr "Suomi"
 
 #: qcsrc/menu/xonotic/credits.qc:202
 msgid "French"
-msgstr ""
+msgstr "Ranska"
 
 #: qcsrc/menu/xonotic/credits.qc:210
 msgid "German"
-msgstr ""
+msgstr "Saksa"
 
 #: qcsrc/menu/xonotic/credits.qc:221
 msgid "Greek"
-msgstr ""
+msgstr "Kreikka"
 
 #: qcsrc/menu/xonotic/credits.qc:227
 msgid "Hungarian"
-msgstr ""
+msgstr "Unkari"
 
 #: qcsrc/menu/xonotic/credits.qc:231
 msgid "Irish"
-msgstr ""
+msgstr "Iiri"
 
 #: qcsrc/menu/xonotic/credits.qc:234
 msgid "Italian"
-msgstr ""
+msgstr "Italia"
 
 #: qcsrc/menu/xonotic/credits.qc:240
 msgid "Kazakh"
-msgstr ""
+msgstr "Kasakki"
 
 #: qcsrc/menu/xonotic/credits.qc:243
 msgid "Korean"
-msgstr ""
+msgstr "Korea"
 
 #: qcsrc/menu/xonotic/credits.qc:247
 msgid "Polish"
-msgstr ""
+msgstr "Puola"
 
 #: qcsrc/menu/xonotic/credits.qc:255
 msgid "Portuguese"
-msgstr ""
+msgstr "Portugali"
 
 #: qcsrc/menu/xonotic/credits.qc:261
 msgid "Romanian"
-msgstr ""
+msgstr "Romania"
 
 #: qcsrc/menu/xonotic/credits.qc:268
 msgid "Russian"
-msgstr ""
+msgstr "Venäjä"
 
 #: qcsrc/menu/xonotic/credits.qc:279
 msgid "Scottish Gaelic"
-msgstr ""
+msgstr "Skottilainen keltti"
 
 #: qcsrc/menu/xonotic/credits.qc:282
 msgid "Serbian"
-msgstr ""
+msgstr "Serbia"
 
 #: qcsrc/menu/xonotic/credits.qc:288
 msgid "Spanish"
-msgstr ""
+msgstr "Espanja"
 
 #: qcsrc/menu/xonotic/credits.qc:299
 msgid "Swedish"
-msgstr ""
+msgstr "Ruotsi"
 
 #: qcsrc/menu/xonotic/credits.qc:303
 msgid "Ukrainian"
-msgstr ""
+msgstr "Ukraina"
 
 #: qcsrc/menu/xonotic/credits.qc:310
 msgid "Past Contributors"
-msgstr ""
+msgstr "Aikaisemmat panoksensa antajat"
 
 #: qcsrc/menu/xonotic/cvarlist.qc:73
 msgid "forced to be saved to config.cfg"
-msgstr ""
+msgstr "pakoitettu tallennettavaksi tiedostoon config.cfg"
 
 #: qcsrc/menu/xonotic/cvarlist.qc:79 qcsrc/menu/xonotic/cvarlist.qc:89
 msgid "will not be saved"
@@ -5612,7 +5774,7 @@ msgstr "Tekijät"
 
 #: qcsrc/menu/xonotic/dialog_credits.qh:8
 msgid "The Xonotic credits"
-msgstr ""
+msgstr "Xonotic:in tunnustusmaininnat"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:39
 msgid ""
@@ -5632,7 +5794,7 @@ msgstr "Nimi:"
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:53
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:64
 msgid "Name under which you will appear in the game"
-msgstr ""
+msgstr "Näkyvä nimi jota tulet käyttämään pelissä"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:69
 msgid "Text language:"
@@ -5644,7 +5806,7 @@ msgstr "Salli pelinimesi käyttö pelaajatilastosivulla stats.xonotic.org?"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:84
 msgid "Undecided"
-msgstr ""
+msgstr "Ei päätetty"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:88
 msgid "Save settings"
@@ -5665,12 +5827,12 @@ msgstr "Näytä vain nykyinen ammustyyppi"
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:24
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:46
 msgid "Noncurrent alpha:"
-msgstr ""
+msgstr "Ei-ajanmukainen alpha-versio:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:28
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:50
 msgid "Noncurrent scale:"
-msgstr ""
+msgstr "Ei-ajanmukaisuuden skaala:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:32
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:24
@@ -5734,7 +5896,7 @@ msgstr "Fontin skaalaus:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6
 msgid "Centerprint Panel"
-msgstr ""
+msgstr "Keskeiskirjoituksen palkki"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:17
 msgid "Chat entries:"
@@ -5770,7 +5932,7 @@ msgstr "Pelimoottorin tietopaneeli"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:17
 msgid "Combine health and armor"
-msgstr ""
+msgstr "Yhdistä terveys ja suojapanssari"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:19
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:28
@@ -5838,35 +6000,35 @@ msgstr "Pois päältä"
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:17
 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:15
 msgid "Enable spectating"
-msgstr ""
+msgstr "Kytke päälle sivustakatselu"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18
 msgid "Enable even playing in warmup"
-msgstr ""
+msgstr "Salli jopa lämmittelykierrosta pelatessa"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29
 msgid "Reduced"
-msgstr ""
+msgstr "Alennettu"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32
 msgid "Text/icon ratio:"
-msgstr ""
+msgstr "Teksti/kuvake-suhde:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35
 msgid "Hide spawned items"
-msgstr ""
+msgstr "Piilota ilmestyneet esineet"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:37
 msgid "Hide big armor and health"
-msgstr ""
+msgstr "Piilota suuri suojapanssari ja terveysmääre"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:39
 msgid "Dynamic size"
-msgstr ""
+msgstr "Dynaaminen koko"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qh:6
 msgid "Items Time Panel"
-msgstr ""
+msgstr "Esineiden aikapalkki"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_modicons.qh:6
 msgid "Mod Icons Panel"
@@ -5899,15 +6061,15 @@ msgstr "Ilmoituspaneeli"
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:16
 #: qcsrc/menu/xonotic/util.qc:766
 msgid "Enable"
-msgstr ""
+msgstr "Ota käyttöön"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17
 msgid "Enable even observing"
-msgstr ""
+msgstr "Salli jopa katselijana"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18
 msgid "Enable only in Race/CTS"
-msgstr ""
+msgstr "Otakäyttöön vain Kilvassa/CTS:ssä"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24
 msgid "Status bar"
@@ -5994,7 +6156,7 @@ msgstr "Tehonlisäyspaneeli"
 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:16
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:17
 msgid "Always enable"
-msgstr ""
+msgstr "Aina päällä"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:23
 msgid "Forced aspect:"
@@ -6006,7 +6168,7 @@ msgstr "Painettujen näppäinten paneeli"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qh:6
 msgid "Quick Menu Panel"
-msgstr ""
+msgstr "Pikavalikkopalkki"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.qh:6
 msgid "Race Timer Panel"
@@ -6014,7 +6176,7 @@ msgstr "Kilpajuoksun ajanoton paneeli"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16
 msgid "Enable in team games"
-msgstr ""
+msgstr "Salli joukkuepeleissä"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23
 msgid "Radar:"
@@ -6192,7 +6354,7 @@ msgstr "Näppäin"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:60
 msgid "Weapon ID scale:"
-msgstr ""
+msgstr "Aseen ID-tunnisteen skaalaus:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:66
 msgid "Show Accuracy"
@@ -6216,7 +6378,7 @@ msgstr "Asepaneeli"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:19
 msgid "HUD skins"
-msgstr ""
+msgstr "HUD-päällysteskinit"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:22
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:173
@@ -6232,7 +6394,7 @@ msgstr "Suodatin:"
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:49
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:42
 msgid "Refresh"
-msgstr ""
+msgstr "Virkistys"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:33
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:30
@@ -6241,7 +6403,7 @@ msgstr "Aseta ulkoasu:"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:37
 msgid "Save current skin"
-msgstr ""
+msgstr "Tallenna nykyinen päällysteskini"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:46
 msgid "Panel background defaults:"
@@ -6322,7 +6484,7 @@ msgstr "Paneelin näkymän asetukset"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:13
 msgid "Monster:"
-msgstr ""
+msgstr "Hirviö:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:22
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:20
@@ -6336,27 +6498,27 @@ msgstr "Poista"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:25
 msgid "Move target:"
-msgstr ""
+msgstr "Siirrä kohde:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:26
 msgid "Follow"
-msgstr ""
+msgstr "Seuraa"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:27
 msgid "Wander"
-msgstr ""
+msgstr "Vaella"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:28
 msgid "Spawnpoint"
-msgstr ""
+msgstr "Syntymispiste"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:29
 msgid "No moving"
-msgstr ""
+msgstr "Ei liikkettä"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:31
 msgid "Colors:"
-msgstr ""
+msgstr "Värit:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:33
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:39
@@ -6365,7 +6527,7 @@ msgstr "Aseta iho:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qh:6
 msgid "Monster Tools"
-msgstr ""
+msgstr "Hirviötyökalut"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:14
 msgid "Servers"
@@ -6373,19 +6535,19 @@ msgstr "Palvelimet"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:15
 msgid "Find servers to play on"
-msgstr ""
+msgstr "Etsi palvelimia joissa pelata"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:17
 msgid "Host your own game"
-msgstr ""
+msgstr "Isännöi oma pelisi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:18
 msgid "Media"
-msgstr ""
+msgstr "Media"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:19
 msgid "Profile"
-msgstr ""
+msgstr "Henkilökuva"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qh:6
 msgid "Multiplayer"
@@ -6396,6 +6558,8 @@ msgid ""
 "Play online, against your friends in LAN, view demos or change player "
 "settings"
 msgstr ""
+"Pelaa internet-verkossa, ystäviäsi vastaan LAN-lähiverkossa, katsele demoja "
+"tai muuta pelaaja-asetuksia"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:38
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:111
@@ -6408,11 +6572,11 @@ msgstr "Perusasetus"
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:40
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:64
 msgid "Unlimited"
-msgstr ""
+msgstr "Rajoittamaton"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:74
 msgid "Gametype"
-msgstr ""
+msgstr "Pelimuoto"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:79
 msgid "Time limit:"
@@ -6420,16 +6584,16 @@ msgstr "Aikaraja"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:81
 msgid "Timelimit in minutes that when hit, will end the match"
-msgstr ""
+msgstr "Aikaraja minuuteissa jonka täytyttyä, päättää ottelun"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:82
 #, c-format
 msgid "%d minutes"
-msgstr ""
+msgstr "%d minuuttia"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:83
 msgid "TIMLIM^Default"
-msgstr ""
+msgstr "TIMLIM^Vakio"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:84
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:159
@@ -6438,7 +6602,7 @@ msgstr "1 minuutti"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:101
 msgid "TIMLIM^Infinite"
-msgstr ""
+msgstr "TIMLIM^Rajaton"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:109
 msgid "Teams:"
@@ -6446,15 +6610,15 @@ msgstr "Joukkueet:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:112
 msgid "2 teams"
-msgstr ""
+msgstr "2 joukkuetta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:113
 msgid "3 teams"
-msgstr ""
+msgstr "3 joukkuetta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:114
 msgid "4 teams"
-msgstr ""
+msgstr "4 joukkuetta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:117
 msgid "Player slots:"
@@ -6465,6 +6629,8 @@ msgid ""
 "The maximum amount of players or bots that can be connected to your server "
 "at once"
 msgstr ""
+"Pelaajien tai bottien enimmäismäärä jotka voivat yhdistää palvelimeesi "
+"kerralla"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:121
 msgid "Number of bots:"
@@ -6472,7 +6638,7 @@ msgstr "Bottien lukumäärä:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:123
 msgid "Amount of bots on your server"
-msgstr ""
+msgstr "Bottien lukumäärä palvelimellasi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:125
 msgid "Bot skill:"
@@ -6480,7 +6646,7 @@ msgstr "Bottien taitotaso:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:128
 msgid "Specify how experienced the bots will be"
-msgstr ""
+msgstr "Määritä kuinka kokeneita haluat bottien olevan"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:129
 msgid "Botlike"
@@ -6532,49 +6698,51 @@ msgstr "Muokkaukset..."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:156
 msgid "Mutators and weapon arenas"
-msgstr ""
+msgstr "Mutaattorit ja ase-areenat"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:165
 msgid "Maplist"
-msgstr ""
+msgstr "Karttaluettelo"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:175
 msgid ""
 "Click here or Ctrl-F to provide a keyword to narrow down the map list. Ctrl-"
 "Delete to clear; Enter when done."
 msgstr ""
+"Napsauta tässä tai Ctrl-F toimittaaksesi avainsanan kaventaaksesi "
+"karttaluetteloa. Ctrl-Delete tyhjentää; paina Enter kun kaikki valmista."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:184
 msgid "Add shown"
-msgstr ""
+msgstr "Lisää näkyvät"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:185
 msgid "Add the maps shown in the list to your selection"
-msgstr ""
+msgstr "Lisää kartat jotka näkyvät "
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:188
 msgid "Remove shown"
-msgstr ""
+msgstr "Poista näkyvistä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:189
 msgid "Remove the maps shown in the list from your selection"
-msgstr ""
+msgstr "Poista karttoja jotka näkyvät "
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:194
 msgid "Add all"
-msgstr ""
+msgstr "Lisää kaikki"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:195
 msgid "Add every available map to your selection"
-msgstr ""
+msgstr "Lisää kaikki tarjollaolevat kartat valintaasi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:198
 msgid "Remove all"
-msgstr ""
+msgstr "Poista kaikki"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:199
 msgid "Remove all the maps from your selection"
-msgstr ""
+msgstr "Poista kaikki kartat valinnastasi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:206
 msgid "Start Multiplayer!"
@@ -6626,7 +6794,7 @@ msgstr "Väistely"
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:59
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:278
 msgid "InstaGib"
-msgstr ""
+msgstr "InstaGib-hetitappo"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:61
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:221
@@ -6674,7 +6842,7 @@ msgstr "Jalat irti maasta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:81
 msgid "Melee only"
-msgstr ""
+msgstr "Vain lähiaseet"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:85
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:229
@@ -6694,11 +6862,11 @@ msgstr "Verenvuodatus"
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:93
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:174
 msgid "Buffs"
-msgstr ""
+msgstr "Puhvit"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:95
 msgid "Overkill"
-msgstr ""
+msgstr "Ylimalkaalliset"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:97
 msgid "No powerups"
@@ -6715,7 +6883,7 @@ msgstr "Räjähtävä kosketus"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:103
 msgid "Wall jumping"
-msgstr ""
+msgstr "Seinähyppely"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:105
 msgid "MUT^None"
@@ -6727,28 +6895,33 @@ msgstr "Pelityylin muokkaukset:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:164
 msgid "Enable dodging"
-msgstr ""
+msgstr "Ota käyttöön väistäminen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:171
 msgid "All players are almost invisible"
-msgstr ""
+msgstr "Kaikki pelaajat ovat lähes näkymättömiä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:179
 msgid "Only possible to inflict damage on your enemy while they're airborne"
 msgstr ""
+"Ainoa mahdollisuus aiheuttaa vahinkoa vihollisillesi on silloin kun he ovat "
+"ilmassa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183
 msgid "Damage done to your enemy gets added to your own health"
-msgstr ""
+msgstr "Vihollisellesi aiheutettu vahinko siirtyy lisänä omaan terveyteesi "
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:188
 msgid ""
 "Amount of health below which your player gets stunned because of blood loss"
 msgstr ""
+"Terveysmääre missä kohtaa pelaajasi menee taintumatilaan verenhukan takia"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:197
 msgid "Make things fall to the ground slower, lower value means lower gravity"
 msgstr ""
+"Laita esineet putoamaan maahan hitaammin, matalampi arvo tarkoittaa "
+"vähäisempää vetovoimaa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:206
 msgid "Weapon & item mutators:"
@@ -6760,19 +6933,19 @@ msgstr "Köysi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:210
 msgid "Players spawn with the grappling hook"
-msgstr ""
+msgstr "Pelaajat syntyvät heittokoukun kera"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:214
 msgid "Players spawn with the jetpack"
-msgstr ""
+msgstr "Pelaajat syntyvät lentopakkauksen kera"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:230
 msgid "Players will drop all weapons they possessed when they are killed"
-msgstr ""
+msgstr "Pelaajat pudottavat kaikki omaamansa aseet tapetuksi tullessaan "
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:235
 msgid "Weapons stay after they are picked up"
-msgstr ""
+msgstr "Aseet säilyvät poimimisen jälkeen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:240
 msgid "Regular (no arena)"
@@ -6783,6 +6956,8 @@ msgid ""
 "Players will be given a set of weapons at spawn as well as unlimited ammo, "
 "without weapon pickups"
 msgstr ""
+"Pelaajille annetaan asevalikoima syntyessä kuten myös rajattomat ammukset, "
+"ilman asepoimintaa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:243
 msgid "Weapon arenas:"
@@ -6790,7 +6965,7 @@ msgstr "Tietyn aseen taistelukenttä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:246
 msgid "Custom weapons"
-msgstr ""
+msgstr "Mukautetut aseet"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:268
 msgid "Most weapons"
@@ -6811,6 +6986,11 @@ msgid ""
 "to find some or if he fails to do so, face death. The secondary fire mode "
 "does not inflict any damage but is good for doing trickjumps."
 msgstr ""
+"Pelaajille annetaan vain yksi ase, joka voi tappaa vastustajan välittömästi "
+"yhdellä laukauksella. Mikäli pelaajalta loppuvat ammukset, saa hän 10 "
+"sekuntia aikaa löytääkseen niitä tai jos hän siinä epäonnistuu, kuolo "
+"korjaa. Toissijainen tulitus ei aiheuta ollenkaan vahinkoa mutta on kätevä "
+"temppuhyppyjen toteuttamiseen."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:284
 msgid ""
@@ -6818,14 +6998,17 @@ msgid ""
 "weapon. After some time, a countdown will start, after which everyone will "
 "switch to another weapon."
 msgstr ""
+"Xonotic ilman esineitä - poiminnallisten esineiden sijasta, kaikki pelaavat "
+"samalla aseella. Kotvan kuluttua, lähtölaskenta alkaa, ja jonka päätyttyä "
+"jokainen vaihtaa toiseen aseeseen."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:288
 msgid "with blaster"
-msgstr ""
+msgstr "läjäyttimellä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:289
 msgid "Always carry the blaster as an additional weapon in Nix"
-msgstr ""
+msgstr "Läjäytin aina kannossa lisäaseen ominaisuudessa Nix:issä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qh:9
 msgid "Mutators"
@@ -6833,7 +7016,7 @@ msgstr "Muokatut pelitilat"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:39
 msgid "SRVS^Categories"
-msgstr ""
+msgstr "SRVS^Osa-alueet"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:42
 msgid "SRVS^Empty"
@@ -6841,7 +7024,7 @@ msgstr "SRVS^Tyhjä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:43
 msgid "Show empty servers"
-msgstr ""
+msgstr "Näytä tyhjät palvelimet"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:47
 msgid "SRVS^Full"
@@ -6849,7 +7032,7 @@ msgstr "SRVS^Täynnä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:48
 msgid "Show full servers that have no slots available"
-msgstr ""
+msgstr "Näytä täydet palvelimet joissa ei ole pelaajapaikkoja jäljellä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:52
 msgid "Pause"
@@ -6859,10 +7042,12 @@ msgstr "Keskeytä"
 msgid ""
 "Pause updating the server list to prevent servers from \"jumping around\""
 msgstr ""
+"Tauota palvelinluettelon päivittäminen estääksesi palvelimien \"sinne-tänne "
+"hyppelyn\""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:54
 msgid "Reload the server list"
-msgstr ""
+msgstr "Lataa palvelinluettelo uudestaan"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:68
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:184
@@ -6875,17 +7060,17 @@ msgstr "Tietoa..."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:80
 msgid "Show more information about the currently highlighted server"
-msgstr ""
+msgstr "Näytä lisätietoja tämänhetkisestä korostetusta palvelimesta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:85
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh:6
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh:6
 msgid "Disconnect"
-msgstr ""
+msgstr "Katkaise yhteys"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:86
 msgid "Disconnect from the server"
-msgstr ""
+msgstr "Katkaise yhteys palvelimeen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:88
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:264
@@ -6895,7 +7080,7 @@ msgstr "Liity!"
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:114
 #: qcsrc/menu/xonotic/serverlist.qc:1044
 msgid "MOD^Default"
-msgstr ""
+msgstr "MOD^Vakio"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
 #, c-format
@@ -6948,7 +7133,7 @@ msgstr "Vaadittu (salaus onnistuu)"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:161
 msgid "Use the `crypto_aeslevel` cvar to change your preferences"
-msgstr ""
+msgstr "Käytä `crypto_aeslevel` cvar muuttaaksesi asetuksia"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:178
 msgid "Hostname:"
@@ -7009,15 +7194,15 @@ msgstr "Demot"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:26
 msgid "Screenshots"
-msgstr ""
+msgstr "Kuvakaappaukset"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:27
 msgid "Music Player"
-msgstr ""
+msgstr "Musiikkisoitin"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48
 msgid "Auto record demos"
-msgstr ""
+msgstr "Demojen automaattitallennus"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57
 msgid "Timedemo"
@@ -7026,6 +7211,8 @@ msgstr "Aikademo"
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:58
 msgid "Benchmark how fast your computer can run the highlighted demo"
 msgstr ""
+"Toteuta mittapuu joka ilmentää kuinka nopeasti tietokoneesi pystyy ajamaan "
+"kyseistä demoa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:62
 msgid "DEMO^Play"
@@ -7033,92 +7220,92 @@ msgstr "Pelaa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:13
 msgid "Playing a demo will disconnect you from the current match."
-msgstr ""
+msgstr "Demon pelaaminen katkaisee yhteytesi nykyiseen otteluun."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:15
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:15
 msgid "Do you really wish to disconnect now?"
-msgstr ""
+msgstr "Haluatko todella katkaista yhteyden nyt?"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:13
 msgid "Timing a demo will disconnect you from the current match."
-msgstr ""
+msgstr "Demon ajastus katkaisee yhteyden tämänhetkiseen otteluun."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:37
 msgid "MUSICPL^Add"
-msgstr ""
+msgstr "MUSICPL^Lisää"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:40
 msgid "MUSICPL^Add all"
-msgstr ""
+msgstr "MUSICPL^Lisää kaikki"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:44
 msgid "Set as menu track"
-msgstr ""
+msgstr "Aseta valikon musiikkiraidaksi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:48
 msgid "Reset default menu track"
-msgstr ""
+msgstr "Nollaa vakiollinen valikon musiikkiraita"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:54
 msgid "Playlist:"
-msgstr ""
+msgstr "Soittolista:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:55
 msgid "Random order"
-msgstr ""
+msgstr "Satunnainen järjestys"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:60
 msgid "MUSICPL^Stop"
-msgstr ""
+msgstr "MUSICPL^Pysäytä"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:63
 msgid "MUSICPL^Play"
-msgstr ""
+msgstr "MUSICPL^Soita"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:66
 msgid "MUSICPL^Pause"
-msgstr ""
+msgstr "MUSICPL^Tauko"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:69
 msgid "MUSICPL^Prev"
-msgstr ""
+msgstr "MUSICPL^Edell"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:72
 msgid "MUSICPL^Next"
-msgstr ""
+msgstr "MUSICPL^Seur"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:76
 msgid "MUSICPL^Remove"
-msgstr ""
+msgstr "MUSICPL^Poista"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:79
 msgid "MUSICPL^Remove all"
-msgstr ""
+msgstr "MUSICPL^Poista kaikki"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:41
 msgid "Auto screenshot scoreboard"
-msgstr ""
+msgstr "Automaattinen kuvakaappaus tulostaulusta"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:61
 msgid "Open in the viewer"
-msgstr ""
+msgstr "Avaa kuvankatseluohjelmassa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:137
 msgid "Reset"
-msgstr ""
+msgstr "Nollaa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:142
 msgid "Previous"
-msgstr ""
+msgstr "Edellinen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:145
 msgid "Next"
-msgstr ""
+msgstr "Seuraava"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:150
 msgid "Slide show"
-msgstr ""
+msgstr "Kuvasarja"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:38
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:21
@@ -7131,23 +7318,23 @@ msgstr "Ota heti käyttöön"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:52
 msgid "Name"
-msgstr ""
+msgstr "Nimi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:81
 msgid "Model"
-msgstr ""
+msgstr "Malli"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:100
 msgid "Glowing color"
-msgstr ""
+msgstr "Hehkuva väri"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:110
 msgid "Detail color"
-msgstr ""
+msgstr "Yksityiskohtaväri"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:125
 msgid "Statistics"
-msgstr ""
+msgstr "Tilastot"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:129
 msgid "Allow player statistics to track your client"
@@ -7159,19 +7346,19 @@ msgstr "Salli pelaajatilastojen käyttävän pelinimeäsi"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:149
 msgid "Country"
-msgstr ""
+msgstr "Maa"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:153
 msgid "Select language..."
-msgstr ""
+msgstr "Valitse kieli..."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:169
 msgid "Gender:"
-msgstr ""
+msgstr "Sukupuoli:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:176
 msgid "Gender"
-msgstr ""
+msgstr "Sukupuoli"
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:11
 msgid "Are you sure you want to quit?"
@@ -7179,15 +7366,15 @@ msgstr "Haluatko aivan varmasti lopettaa pelin?"
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:15
 msgid "Back to work..."
-msgstr ""
+msgstr "Takaisin sorvin ääreen..."
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:17
 msgid "I got some more fragging to do!"
-msgstr ""
+msgstr "Minulla on vielä hiukan lisää frägättävää!"
 
 #: qcsrc/menu/xonotic/dialog_quit.qh:7
 msgid "Quit the game"
-msgstr ""
+msgstr "Lopeta peli"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15
 msgid "Model:"
@@ -7327,7 +7514,7 @@ msgstr "Ääni"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:22
 msgid "Game"
-msgstr ""
+msgstr "Peli"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:23
 msgid "Input"
@@ -7348,7 +7535,7 @@ msgstr "Asetukset"
 
 #: qcsrc/menu/xonotic/dialog_settings.qh:7
 msgid "Change the game settings"
-msgstr ""
+msgstr "Muuta peliasetuksia"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:29
 msgid "Master:"
@@ -7404,7 +7591,7 @@ msgstr "Taajuus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:107
 msgid "Sound output frequency"
-msgstr ""
+msgstr "Äänen ulostulotaajuus"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:108
 msgid "8 kHz"
@@ -7444,7 +7631,7 @@ msgstr "Kanavat:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:121
 msgid "Number of channels for the sound output"
-msgstr ""
+msgstr "Ääniulostulon kanavien määrä"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:122
 msgid "Mono"
@@ -7480,11 +7667,11 @@ msgstr "7.1"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:134
 msgid "Swap stereo output channels"
-msgstr ""
+msgstr "Vaihda stereo-ulostulokanavat keskenään"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:135
 msgid "Swap left/right channels"
-msgstr ""
+msgstr "Vaihda kanavat vasen/oikea"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:138
 msgid "Headphone friendly mode"
@@ -7495,6 +7682,8 @@ msgid ""
 "Enable spatialization (blend the right and left channel slightly to decrease "
 "stereo separation a bit for headphones)"
 msgstr ""
+"Kytke spatialisaatio (sekoittaa inansa oikeaa ja vasempaa kanavaa "
+"vähentääkseen stereo erottelua hiukan kuulokkeita ajatellen) "
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:143
 msgid "Hit indication sound"
@@ -7502,7 +7691,7 @@ msgstr "Osumailmaisimen ääni"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:144
 msgid "Play a hit indicator sound when your shot hits an enemy"
-msgstr ""
+msgstr "Toista osumaa merkitsevä ääni laukauksesi osuessa viholliseen"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:147
 msgid "Chat message sound"
@@ -7514,15 +7703,15 @@ msgstr "Valikon äänet"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:150
 msgid "Play sounds when clicking menu items"
-msgstr ""
+msgstr "Toista ääniä kun napsauttelet valikon kohteita"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:151
 msgid "Focus sounds"
-msgstr ""
+msgstr "Kohdista äänet"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:152
 msgid "Play sounds when hovering over menu items too"
-msgstr ""
+msgstr "Toista äänet myöskin vain leijaillessa valikon kohteiden yllä"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:156
 msgid "Time announcer:"
@@ -7542,25 +7731,25 @@ msgstr "WRN^Molemmat"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:164
 msgid "Automatic taunts:"
-msgstr ""
+msgstr "Automaattiset herjaukset:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:166
 msgid "Automatically taunt enemies after fragging them"
-msgstr ""
+msgstr "Herjaa vihulaisia automaattisesti sinun heidät frägättyäsi "
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:168
 msgid "Sometimes"
-msgstr ""
+msgstr "Aika-ajoin"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:169
 msgid "Often"
-msgstr ""
+msgstr "Usein"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:170
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:147
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:57
 msgid "Always"
-msgstr ""
+msgstr "Aina"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:176
 msgid "Debug info about sounds"
@@ -7568,11 +7757,11 @@ msgstr "Äänten debug info"
 
 #: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:11
 msgid "Are you sure you want to reset all key bindings?"
-msgstr ""
+msgstr "Oletko varma että haluat nollata kaikki näppäinsidonnat?"
 
 #: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qh:6
 msgid "Reset key bindings"
-msgstr ""
+msgstr "Nollaa näppäinsidonnat"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:41
 msgid "Quality preset:"
@@ -7612,7 +7801,7 @@ msgstr "Geometriset yksityiskohdat:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:67
 msgid "Change the smoothness of the curves on the map"
-msgstr ""
+msgstr "Muuta mutkien sileyttä kartassa"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:68
 msgid "DET^Lowest"
@@ -7644,23 +7833,23 @@ msgstr "Pelaajahahmon yksityiskohtaisuus"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:79
 msgid "PDET^Low"
-msgstr ""
+msgstr "PDET^Matala"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:80
 msgid "PDET^Medium"
-msgstr ""
+msgstr "PDET^Keskisuhteinen"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:81
 msgid "PDET^Normal"
-msgstr ""
+msgstr "PDET^Tavanomainen"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:82
 msgid "PDET^Good"
-msgstr ""
+msgstr "PDET^Hyvä"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:83
 msgid "PDET^Best"
-msgstr ""
+msgstr "PDET^Paras"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:87
 msgid "Texture resolution:"
@@ -7709,6 +7898,9 @@ msgid ""
 "Disable textures completely for very slow hardware. This gives a huge "
 "performance boost, but looks very ugly."
 msgstr ""
+"Ota tekstuurit kokonaan päältä pois erittäin hitaan laitteiston ollessa "
+"käytössä. Tämä tuottaa valtavan parannuksen suorituskykyyn, mutta kaikki "
+"näyttää erittäin rumalta."
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:135
 msgid "Use lightmaps"
@@ -7719,6 +7911,8 @@ msgid ""
 "Use high resolution lightmaps, which will look pretty but use up some extra "
 "video memory"
 msgstr ""
+"Käytä korkean erottelutarkkuuden valokarttoja; näyttää sievältä mutta syöden "
+"hiukan lisää videomuistia."
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:138
 msgid "Deluxe mapping"
@@ -7726,7 +7920,7 @@ msgstr "Pikselikohtainen valaistus"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:139
 msgid "Use per-pixel lighting effects"
-msgstr ""
+msgstr "Käytä pikselikohtaisia valoefektejä"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:141
 msgid "Gloss"
@@ -7734,7 +7928,7 @@ msgstr "Kiilto"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:142
 msgid "Enable the use of glossmaps on textures supporting it"
-msgstr ""
+msgstr "Ota käyttöön tuetut hohtokartat tekstuureissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:145
 msgid "Offset mapping"
@@ -7745,6 +7939,9 @@ msgid ""
 "Offset mapping effect that will make textures with bumpmaps appear like they "
 "\"pop out\" of the flat 2D surface"
 msgstr ""
+"Poikkeamatyyppinen kartoitusefekti joka laittaa tekstuurit bumpmappausten "
+"kanssa näyttämään siltä kuin ne \"pompsahtaisivat ulos\" lättänästä 2D "
+"pinnasta"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:148
 msgid "Relief mapping"
@@ -7754,6 +7951,8 @@ msgstr "Tehokas tekstuurien kuhmujen korostus"
 msgid ""
 "Higher quality offset mapping, which also has a huge impact on performance"
 msgstr ""
+"Korkeampilaatuinen poikkeamatyyppinen kartoitus jolla on myös suuri vaikutus "
+"suorituskykyyn"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:152
 msgid "Reflections:"
@@ -7764,10 +7963,12 @@ msgid ""
 "Reflection and refraction quality, has a huge impact on performance on maps "
 "with reflecting surfaces"
 msgstr ""
+"Heijastusten- ja taittumien laatu; omaa suuren vaikutuksen suorituskykyn "
+"kartoissa joissa on heijastavia pintoja"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:156
 msgid "Resolution of reflections/refractions"
-msgstr ""
+msgstr "Heijastusten/taittumien erottelumääre"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:157
 msgid "Blurred"
@@ -7787,7 +7988,7 @@ msgstr "Siirtokuvat"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:164
 msgid "Enable decals (bullet holes and blood)"
-msgstr ""
+msgstr "Ota käyttöön tapahtumajäljet (luodinreijät ja verijäljet)"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:165
 msgid "Decals on models"
@@ -7800,7 +8001,7 @@ msgstr "Etäisyys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:172
 msgid "Decals further away than this will not be drawn"
-msgstr ""
+msgstr "Tapahtumajälkiä tätä kauempana ei piirretä "
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:176
 msgid "Time:"
@@ -7808,7 +8009,7 @@ msgstr "Kesto:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:179
 msgid "Time in seconds before decals fade away"
-msgstr ""
+msgstr "Aika sekunneissa milloin tapahtumajäljet haihtuvat"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:183
 msgid "Damage effects:"
@@ -7816,15 +8017,15 @@ msgstr "Vahinkoefektit:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:185
 msgid "DMGFX^Disabled"
-msgstr ""
+msgstr "DMGFX^Poispäältä"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:186
 msgid "Skeletal"
-msgstr ""
+msgstr "Luurankomainen"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:187
 msgid "DMGFX^All"
-msgstr ""
+msgstr "DMGFX^Kaikki"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:191
 msgid "No dynamic lighting"
@@ -7832,7 +8033,7 @@ msgstr "Ei dynaamista valaistusta"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:192
 msgid "Enable corona flares around certain lights"
-msgstr ""
+msgstr "Ota käyttöön pyöröheijastukset tiettyjen valojen ympärille"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:194
 msgid "Fake corona lighting"
@@ -7843,6 +8044,8 @@ msgid ""
 "Enable faster but uglier dynamic lights by rendering bright coronas instead "
 "of real dynamic lights"
 msgstr ""
+"Ota käyttöön nopeammat mutta karummat dynaamiset valot renderöimällä "
+"kirkkaat pyörövalotukset oikeiden dynaamisten valojen sijaan"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:198
 msgid "Realtime dynamic lighting"
@@ -7851,6 +8054,8 @@ msgstr "Reaaliaikainen dynaaminen valaitus"
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:199
 msgid "Enable rendering of dynamic lights such as explosions and rocket lights"
 msgstr ""
+"Ota käyttöön dynaamisten valojen renderöinti kuten räjähdykset ja rakettien "
+"valot"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:201
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:207
@@ -7859,7 +8064,7 @@ msgstr "Varjot"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:202
 msgid "Enable rendering of shadows from dynamic lights"
-msgstr ""
+msgstr "Ota käyttöön varjojen renderöinti dynaamisista valoista"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:205
 msgid "Realtime world lighting"
@@ -7870,10 +8075,13 @@ msgid ""
 "Enable rendering of full realtime world lighting on maps that support it. "
 "Note that this might have a big impact on performance."
 msgstr ""
+"Ota käyttöön kaikenkattava oikea-aikainen maailmavalaistus kartoissa jotka "
+"sitä tukevat. Huomaa että tämä vaikuttaa huomattavasti suorituskykyyn."
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:208
 msgid "Enable rendering of shadows from realtime world lights"
 msgstr ""
+"Ota käyttöön varjojen renderöinti oikea-aikaisista maailmavalotuksista "
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:212
 msgid "Use normal maps"
@@ -7881,7 +8089,7 @@ msgstr "Käytä tekstuurien suunnattua varjostamista"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:213
 msgid "Enable use of directional shading on textures"
-msgstr ""
+msgstr "Ota käyttöön suunnittainen tekstuurien vivahteikkuus"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:215
 msgid "Soft shadows"
@@ -7889,11 +8097,11 @@ msgstr "Pehmeät varjot"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:219
 msgid "Fade corona according to visibility"
-msgstr ""
+msgstr "Himmennä pyörövaloheijastusta näkyvyyteen nähden"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:220
 msgid "Fade coronas according to visibility"
-msgstr ""
+msgstr "Himmennä pyörövaloheijastuksia näkyvyyteen nähden"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:224
 msgid "Bloom"
@@ -7904,6 +8112,8 @@ msgid ""
 "Enable bloom effect, which brightens the neighboring pixels of very bright "
 "pixels. Has a big impact on performance."
 msgstr ""
+"Ota käyttöön bloom-tehoste, joka kirkastaa myös vierekkäiset pikselit hyvin "
+"kirkkaista pikseleistä. Suuri vaikutus suorituskykyyn."
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:226
 msgid "Extra postprocessing effects"
@@ -7914,10 +8124,12 @@ msgid ""
 "Enables special postprocessing effects for when damaged or under water or "
 "using a powerup"
 msgstr ""
+"Ottaa käyttöön erityiset jälkikäsittelyefektit kun otetaan vastaan vahinkoa, "
+"ollaan veden alla tai kun käytetään pikavoimistuksia"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:232
 msgid "Motion blur strength - 0.4 recommended"
-msgstr ""
+msgstr "Liikkeen utuisuuden voimakkuus - 0.4 on suositeltava"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:233
 msgid "Motion blur:"
@@ -7925,19 +8137,20 @@ msgstr "Liikesumeus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:239
 msgid "Particles"
-msgstr ""
+msgstr "Hiukkaset"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:240
 msgid "Spawnpoint effects"
-msgstr ""
+msgstr "Syntypiste-efektit"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:241
 msgid "Particles effects at all spawn points and whenever a player spawns"
 msgstr ""
+"Hiukkasefektit kaikilla syntymispisteillä ja aina kun pelaaja ilmestyy/syntyy"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:246
 msgid "Quality:"
-msgstr ""
+msgstr "Laatu:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:249
 #: qcsrc/menu/xonotic/slider_particles.qc:13
@@ -7945,10 +8158,12 @@ msgid ""
 "Multiplier for amount of particles. Less means less particles, which in turn "
 "gives for better performance"
 msgstr ""
+"Hiukkasten määrän kerroin. Vähemmän tietää lukumääräisesti vähempää määrää "
+"hiukkasia, joka puolestaan johtaa parempaan suorituskykyyn"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:256
 msgid "Particles further away than this will not be drawn"
-msgstr ""
+msgstr "Tätä kauempana siintäviä hiukkasia ei piirretä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:31
 msgid "No crosshair"
@@ -7964,12 +8179,13 @@ msgid ""
 "Set a different crosshair for each weapon, good if you play without weapon "
 "models"
 msgstr ""
+"Aseta eri tähtäin jokaiselle aseelle; on hyväksi jos pelaat ilman asemalleja"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:48
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:81
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:97
 msgid "Size:"
-msgstr ""
+msgstr "Koko:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:64
 msgid "By health"
@@ -8001,6 +8217,9 @@ msgid ""
 "when there's an obstacle between your gun and the target; Enemies: also "
 "enlarge the crosshair when you would hit an enemy"
 msgstr ""
+"Ei mitään: älä tee muutoksia tähtäimeen. TosiTähtäys: sumenna tähtäintä kun "
+"aseen ja kohteen välissä on este. Viholliset: isonna tähtäintä silloin kun "
+"voisit ampua osuman"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:129
 msgid "HTTST^Disabled"
@@ -8020,45 +8239,47 @@ msgstr "Sumenna tähtäin jos aseen ja kohteen välissä on este"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:140
 msgid "Enlarge crosshair if targeting an enemy"
-msgstr ""
+msgstr "Suurenna tähtäintä mikäli tähtäät vihollista kohti"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:143
 msgid "Animate crosshair when hitting an enemy"
-msgstr ""
+msgstr "Elollista tähtäin kun ammut osuman viholliseen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:146
 msgid "Animate crosshair when picking up an item"
-msgstr ""
+msgstr "Elollista tähtäin poimiessasi esineen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qh:7
 msgid "Crosshair"
-msgstr ""
+msgstr "Tähtäin"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43
 msgid "Scoreboard"
-msgstr ""
+msgstr "Tulostaulu"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:48
 msgid "Fading speed:"
-msgstr ""
+msgstr "Haihtumisen nopeus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:51
 msgid "Enable rows / columns highlighting"
-msgstr ""
+msgstr "Ota käyttöön rivien / pystysarakkaiden korostus"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:53
 msgid "Show accuracy underneath scoreboard"
-msgstr ""
+msgstr "Näytä tulostaulun alaosassa osumatarkkuus"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:55
 msgid "Show team sizes:"
-msgstr ""
+msgstr "Näytä joukkueiden koot:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:56
 msgid ""
 "Team size position: Off=do not show; Left=on the left side of the scoreboard "
 "and move team scores to the right; Right=on the right of the scoreboard"
 msgstr ""
+"Joukkuekoon sijainti: Pois= älä näytä. Vasen= tulostaulun vasemmassa "
+"laidassa sekä siirrä joukkuepisteet oikealle. Oikea= tulostaulun oikea laita "
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:64
 msgid "Waypoints"
@@ -8066,20 +8287,20 @@ msgstr "Välietapit"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:66
 msgid "Display waypoint markers for objectives on the map"
-msgstr ""
+msgstr "Näytä välietappien maamerkit kartan kohteille "
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:67
 msgid "Show various gametype specific waypoints"
-msgstr ""
+msgstr "Näytä useita pelimuoto-ominaisia välietappeja"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:73
 msgid "Control transparency of the waypoints"
-msgstr ""
+msgstr "Hallinnoi välietappien läpinäkyvyyttä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:77
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:130
 msgid "Fontsize:"
-msgstr ""
+msgstr "Kirjasinkoko:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:83
 msgid "Edge offset:"
@@ -8087,15 +8308,15 @@ msgstr "Tönäisy reunasta:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:91
 msgid "Fade when near the crosshair"
-msgstr ""
+msgstr "Hämärrä kun lähellä tähtäintä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:95
 msgid "Display names instead of icons"
-msgstr ""
+msgstr "Näytä nimet kuvakkeiden sijasta"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:100
 msgid "Damage"
-msgstr ""
+msgstr "Vahinko"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:102
 msgid "Overlay:"
@@ -8111,7 +8332,7 @@ msgstr "Sisääntulon häivennyksen kesto"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:118
 msgid "Player Names"
-msgstr ""
+msgstr "Pelaajanimet"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:120
 msgid "Show names above players"
@@ -8119,16 +8340,16 @@ msgstr "Näytä pelaajanimet hahmojen yläpuolella"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:136
 msgid "Max distance:"
-msgstr ""
+msgstr "Enimmäisetäisyys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:142
 msgid "Decolorize:"
-msgstr ""
+msgstr "Väripoisto:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:146
 #: qcsrc/menu/xonotic/keybinder.qc:114
 msgid "Teamplay"
-msgstr ""
+msgstr "Joukkuepeli"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:154
 msgid "Only when near crosshair"
@@ -8140,19 +8361,19 @@ msgstr "Näytä elämän ja panssarin arvot"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:163
 msgid "Damage overlay:"
-msgstr ""
+msgstr "Päällys joka osoittaa vahingot:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:166
 msgid "Dynamic HUD"
-msgstr ""
+msgstr "Dynaaminen HUD"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:167
 msgid "HUD moves around following player's movement"
-msgstr ""
+msgstr "HUD liikkuu ympärillä seuraten pelaajan liikkeitä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:169
 msgid "Shake the HUD when hurt"
-msgstr ""
+msgstr "Väristä HUD:ia kun sattuu"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:173
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qh:6
@@ -8161,7 +8382,7 @@ msgstr "Muokkaa näkymää"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qh:7
 msgid "HUD"
-msgstr ""
+msgstr "HUD"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:21
 msgid "In order for the HUD editor to show, you must first be in game."
@@ -8174,153 +8395,153 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
 msgid "Frag Information"
-msgstr ""
+msgstr "Frägitieto"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:26
 msgid "Display information about killing sprees"
-msgstr ""
+msgstr "Näytä tiedot tappoputkista"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:29
 msgid "Only display sprees if they are achievements"
-msgstr ""
+msgstr "Näytä putket vain jos niitä saavutetaan"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34
 msgid "Show spree information in centerprints"
-msgstr ""
+msgstr "Näytä putkitiedot keskeiskirjoituksessa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38
 msgid "Show spree information in death messages"
-msgstr ""
+msgstr "Näytä putkitiedot kuoloviesteissä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:43
 msgid "Sprees in info messages:"
-msgstr ""
+msgstr "Putkitiedot tiedotusviesteissä:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:46
 msgid "SPREES^Disabled"
-msgstr ""
+msgstr "SPREES^Pois"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:47
 msgid "Target"
-msgstr ""
+msgstr "Kohde"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:48
 msgid "Attacker"
-msgstr ""
+msgstr "Hyökkääjä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:49
 msgid "SPREES^Both"
-msgstr ""
+msgstr "SPREES^Molemmat"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:55
 msgid "Print on a seperate line"
-msgstr ""
+msgstr "Tulosta eri riveille"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58
 msgid "Add extra frag information to centerprint when available"
-msgstr ""
+msgstr "Laita lisäfrägitiedot keskikirjoitukseen kun niitä on saatavilla"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62
 msgid "Add frag location to death messages when available"
-msgstr ""
+msgstr "Lisää frägin sijaintitieto kuoloviesteihin kun niitä on saatavilla"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:65
 msgid "Gamemode Settings"
-msgstr ""
+msgstr "Pelimuotoasetukset"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:67
 msgid "Display capture times in Capture The Flag"
-msgstr ""
+msgstr "Näytä kaappausajat Lipunryöstössä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:71
 msgid "Display name of flag stealer in Capture The Flag"
-msgstr ""
+msgstr "Näytä lipunvarastajan nimi Lipunryöstössä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:76
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:92
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:133
 msgid "Other"
-msgstr ""
+msgstr "Muuta"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:78
 msgid "Display console messages in the top left corner"
-msgstr ""
+msgstr "Näytä pääteviestejä vasemmassa yläkulmassa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:80
 msgid "Display all info messages in the chatbox"
-msgstr ""
+msgstr "Näytä kaikki tiedotusviestit keskustelulaatikossa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:82
 msgid "Display player statuses in the chatbox"
-msgstr ""
+msgstr "Näytä pelaajatilat keskustelulaatikossa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:86
 msgid "Powerup notifications"
-msgstr ""
+msgstr "Pikavoimistusten ilmoitukset"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89
 msgid "Weapon centerprint notifications"
-msgstr ""
+msgstr "Aseiden ilmoitukset keskikirjoituksessa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92
 msgid "Weapon info message notifications"
-msgstr ""
+msgstr "Asetietoviestien ilmoitukset"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:96
 msgid "Announcers"
-msgstr ""
+msgstr "Julkistajat"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:98
 msgid "Respawn countdown sounds"
-msgstr ""
+msgstr "Uudelleensyntymislaskennan äänet"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:101
 msgid "Killstreak sounds"
-msgstr ""
+msgstr "Tapposarjan äänet"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:104
 msgid "Achievement sounds"
-msgstr ""
+msgstr "Saavutusäänet"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7
 msgid "Messages"
-msgstr ""
+msgstr "Viestit"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30
 msgid "Items"
-msgstr ""
+msgstr "Esineet"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:32
 msgid "Use simple 2D images instead of item models"
-msgstr ""
+msgstr "Käytä yksinkertaisia 2D-kuvia esinemallien sijasta"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:34
 msgid "Unavailable alpha:"
-msgstr ""
+msgstr "Ei saatavissa alpha:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:37
 msgid "Unavailable color:"
-msgstr ""
+msgstr "Ei paikalla -väri:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:39
 msgid "GHOITEMS^Black"
-msgstr ""
+msgstr "GHOITEMS^Musta"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:40
 msgid "GHOITEMS^Dark"
-msgstr ""
+msgstr "GHOITEMS^Tumma"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:41
 msgid "GHOITEMS^Tinted"
-msgstr ""
+msgstr "GHOITEMS^Sävytetty"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:42
 msgid "GHOITEMS^Normal"
-msgstr ""
+msgstr "GHOITEMS^Tavanomainen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:43
 msgid "GHOITEMS^Blue"
-msgstr ""
+msgstr "GHOITEMS^Sininen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:49
 #: qcsrc/menu/xonotic/serverlist.qc:751
@@ -8337,7 +8558,7 @@ msgstr "Pakota pelaajat samanvärisiksi"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:56
 msgid "In non teamplay modes only"
-msgstr ""
+msgstr "Vain ei-joukkuepelimuodoissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60
 msgid "Body fading:"
@@ -8365,11 +8586,11 @@ msgstr "GIBS^Runsaasti"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qh:7
 msgid "Models"
-msgstr ""
+msgstr "Mallit"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qh:8
 msgid "Customize how players and items are displayed in game"
-msgstr ""
+msgstr "Mukauta miten pelaajat ja esineet näytetään pelissä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:26
 msgid "1st person perspective"
@@ -8377,7 +8598,7 @@ msgstr "Ensimmäisen persoonan näkymä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:30
 msgid "Slide to third person upon death"
-msgstr ""
+msgstr "Liu'uta kolmanteen persoonaan kuollessa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:34
 msgid "Smooth the view when landing from a jump"
@@ -8417,23 +8638,25 @@ msgstr "Näkökenttä:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:72
 msgid "Field of vision in degrees"
-msgstr ""
+msgstr "Näkökenttä asteissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:76
 msgid "ZOOM^Zoom factor:"
-msgstr ""
+msgstr "ZOOM^Zoomauksen kerroin:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:78
 msgid "How big the zoom factor is when the zoom button is pressed"
-msgstr ""
+msgstr "Kuinka iso zoomauksen kerroin on zoomaus-nappia painettaessa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:81
 msgid "ZOOM^Zoom speed:"
-msgstr ""
+msgstr "ZOOM^Zoom-nopeus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:83
 msgid "How fast the view will be zoomed, disable to zoom instantly"
 msgstr ""
+"Kuinka nopeasti näkymä zoomataan, ota pois käytöstä jotta zoom tapahtuu "
+"välittömästi"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:92
 msgid "ZOOM^Instant"
@@ -8441,46 +8664,48 @@ msgstr "ZOOM^Heti"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:96
 msgid "ZOOM^Zoom sensitivity:"
-msgstr ""
+msgstr "ZOOM^Zoom-herkkyys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:98
 msgid ""
 "How zoom changes sensitivity, from 0 (lower sensitivity) to 1 (no "
 "sensitivity change)"
 msgstr ""
+"Kuinka zoom kohdistaa herkkyyden kannalta, alkaen 0:sta (matalampi "
+"herkkyystaso) määreeseen 1 (ei muutosta herkkyydensäätöön)"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:101
 msgid "Velocity zoom"
-msgstr ""
+msgstr "Kiertonopeus-zoom"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:102
 msgid "Forward movement only"
-msgstr ""
+msgstr "Vain eteenpäinliike"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:106
 msgid "VZOOM^Factor"
-msgstr ""
+msgstr "VZOOM^Kerroin"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:113
 msgid "Display reticle 2D overlay while zooming"
-msgstr ""
+msgstr "Näytä 2D-päällisristikko zoomatessa"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:116
 msgid "Release zoom when you die or respawn"
-msgstr ""
+msgstr "Vapauta zoom kuollessa tai uudelleensynnyt"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:120
 msgid "Release zoom when you switch weapons"
-msgstr ""
+msgstr "Vapauta zoom vaihtaessasi aseita"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qh:7
 #: qcsrc/menu/xonotic/keybinder.qc:85
 msgid "View"
-msgstr ""
+msgstr "Näkymä"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:34
 msgid "Weapon Priority List (* = mutator weapon)"
-msgstr ""
+msgstr "Aseiden ensisijaisuusluettelo (* = mutaattori-ase)"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:40
 msgid "Up"
@@ -8498,10 +8723,12 @@ msgstr "Käytä prioriteettiä aseiden vaihdossa"
 msgid ""
 "Make use of the list above when cycling through weapons with the mouse wheel"
 msgstr ""
+"Käytä hyväksi ylläolevaa luetteloa kun kierrät läpi asevalikoimaasi hiiren "
+"rullalla"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:53
 msgid "Cycle through only usable weapon selections"
-msgstr ""
+msgstr "Läpikäy vain käytettäviä aseita"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:57
 msgid "Auto switch weapons on pickup"
@@ -8512,10 +8739,12 @@ msgid ""
 "Automatically switch to newly picked up weapons if they are better than what "
 "you are carrying"
 msgstr ""
+"Vaihda automaattisesti tuoreeltaan poimittu ase jos se on parempi kuin mitä "
+"sillä hetkellä kannat"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:61
 msgid "Release attack buttons when you switch weapons"
-msgstr ""
+msgstr "Vapauta hyökkäysnappi vaihtaessasi aseita"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:64
 msgid "Draw 1st person weapon model"
@@ -8523,13 +8752,13 @@ msgstr "Piirrä ensimmäisen persoonan asemalli"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:65
 msgid "Draw the weapon model"
-msgstr ""
+msgstr "Piirrä asemalli"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:69
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:72
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:75
 msgid "Position of the weapon model; requires reconnect"
-msgstr ""
+msgstr "Asemallin sijainti; vaatii yhteyden uudelleenmuodostamisen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:80
 msgid "Gun model swaying"
@@ -8542,11 +8771,11 @@ msgstr "Aseen heilunta"
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qh:7
 #: qcsrc/menu/xonotic/keybinder.qc:51
 msgid "Weapons"
-msgstr ""
+msgstr "Aseet"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:34
 msgid "Key Bindings"
-msgstr ""
+msgstr "Näppäinsidonnat"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:38
 msgid "Change key..."
@@ -8562,11 +8791,11 @@ msgstr "Tyhjennä"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:53
 msgid "Reset all"
-msgstr ""
+msgstr "Nollaa kaikki"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:58
 msgid "Mouse"
-msgstr ""
+msgstr "Hiiri"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:60
 msgid "Sensitivity:"
@@ -8574,7 +8803,7 @@ msgstr "Herkkyys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:62
 msgid "Mouse speed multiplier"
-msgstr ""
+msgstr "Hiiren nopeuden moninkertaistaja"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:64
 msgid "Smooth aiming"
@@ -8583,6 +8812,7 @@ msgstr "Tähtäyksen pehmennys"
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:65
 msgid "Smoothes the mouse movement, but makes aiming slightly less responsive"
 msgstr ""
+"Pehmentää hiiriliikkeitä, mutta tekee tähtäämisen hiukan vähemmän herkäksi"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:67
 msgid "Invert aiming"
@@ -8590,11 +8820,11 @@ msgstr "Käännä hiiren suunta"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:68
 msgid "Invert mouse movement on the Y-axis"
-msgstr ""
+msgstr "Käännä hiiriliikkeet Y-akselilla"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:70
 msgid "Use system mouse positioning"
-msgstr ""
+msgstr "Käytä järjestelmän hiirenkohdistusta"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:75
 msgid "Enable built in mouse acceleration"
@@ -8608,7 +8838,7 @@ msgstr "Laita käyttöjärjestelmän hiiren kiihtyvyys pois päältä"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:80
 msgid "Make use of DGA mouse input"
-msgstr ""
+msgstr "Käytä DGA-sisääntuloa hiirelle"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:94
 msgid "Pressing \"enter console\" key also closes it"
@@ -8616,7 +8846,7 @@ msgstr "\"avaa komentorivi\" myös sulkee komentorivin"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:95
 msgid "Allow the console toggling bind to also close the console"
-msgstr ""
+msgstr "Salli päätteen esiintulon nappisidontaa myöskin päätteen sulkemiseen"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:97
 msgid "Automatically repeat jumping if holding jump"
@@ -8624,19 +8854,19 @@ msgstr "Hyppää automaattisesti uudestaan pitämällä hyppynappi painettuna"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:100
 msgid "Jetpack on jump:"
-msgstr ""
+msgstr "Lentopakkaus hypätessä:"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:102
 msgid "JPJUMP^Disabled"
-msgstr ""
+msgstr "JPJUMP^Pois"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:103
 msgid "Air only"
-msgstr ""
+msgstr "Vain ilmassa"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:104
 msgid "JPJUMP^All"
-msgstr ""
+msgstr "JPJUMP^Kaikki"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:110
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:115
@@ -8663,21 +8893,21 @@ msgstr "Käyttäjän määrittelemä näppäinasetus"
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:11
 #, c-format
 msgid "%d fps"
-msgstr ""
+msgstr "%d fps-ruudunpäivitys"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:12
 #, c-format
 msgid "%d KB/s"
-msgstr ""
+msgstr "%d Kt/s"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:13
 #, c-format
 msgid "%d MB/s"
-msgstr ""
+msgstr "%d Mt/s"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:27
 msgid "Network"
-msgstr ""
+msgstr "Verkko"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
 msgid "Client UDP port:"
@@ -8686,14 +8916,16 @@ msgstr "Asiakkaan UDP portti"
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:31
 msgid "Force client to use chosen port unless it is set to 0"
 msgstr ""
+"Pakota asiakasohjelma käyttämään valittua porttia ellei se ole asetettu "
+"muotoon 0"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:34
 msgid "Bandwidth:"
-msgstr ""
+msgstr "Kaistanleveys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:36
 msgid "Specify your network speed"
-msgstr ""
+msgstr "Määritä verkkoyhteytesi nopeus"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:37
 msgid "56k"
@@ -8721,11 +8953,11 @@ msgstr "Vastaanottopaketit /s:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:46
 msgid "How many input packets to send to the server each second"
-msgstr ""
+msgstr "Montako sisääntulopakettia lähettää palvelimelle jokainen sekunti"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
 msgid "Server queries/s:"
-msgstr ""
+msgstr "Palvelinkyselyt/s:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
 msgid "Downloads:"
@@ -8733,11 +8965,11 @@ msgstr "Lataukset:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:54
 msgid "Maximum number of concurrent HTTP/FTP downloads"
-msgstr ""
+msgstr "Rinnakkaisten HTTP/FTP latausten enimmäismäärä"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:56
 msgid "Download speed:"
-msgstr ""
+msgstr "Latausnopeus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:69
 msgid "Local latency:"
@@ -8749,7 +8981,7 @@ msgstr "Näytä verkkograafi"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:74
 msgid "Show a graph of packet sizes and other information"
-msgstr ""
+msgstr "Näytä pakettikokojen- ja muiden tietojen kuvaus"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:76
 msgid "Client-side movement prediction"
@@ -8761,11 +8993,11 @@ msgstr "Liikkeen virhekompensaatio"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:82
 msgid "Use encryption (AES) when available"
-msgstr ""
+msgstr "Käytä salausta (AES) kun se on saatavissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:85
 msgid "Framerate"
-msgstr ""
+msgstr "Ruudunpäivitysnopeus"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:87
 msgid "Maximum:"
@@ -8801,7 +9033,7 @@ msgstr "Näytä ruudunpäivitysnopeus (FPS)"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:130
 msgid "Show your rendered frames per second"
-msgstr ""
+msgstr "Näytä renderöityjen ruutujen nopeus /sekunnissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:135
 msgid "Menu tooltips:"
@@ -8812,6 +9044,8 @@ msgid ""
 "Menu tooltips: disabled, standard or advanced (also shows cvar or console "
 "command bound to the menu item)"
 msgstr ""
+"Valikon vihjeet: pois, vakiollinen tai edistynyt (näyttää myös cvar:in tai "
+"päätekäskyn joka on sidonnainen valikon kohteeseen)"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:138
 msgid "TLTIP^Disabled"
@@ -8827,11 +9061,13 @@ msgstr "TLTIP^Kehittynyt"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:143
 msgid "Show current date and time"
-msgstr ""
+msgstr "Näytä tämänhetkinen päivämäärä ja kellonaika"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:144
 msgid "Show current date and time of day, useful on screenshots"
 msgstr ""
+"Näytä tämänhetkinen päivämäärä ja kellonaika, käytännöllinen "
+"kuvakaappauksissa"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:147
 msgid "Enable developer mode"
@@ -8844,11 +9080,13 @@ msgstr "Edistyneet asetukset..."
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:152
 msgid "Advanced settings where you can tweak every single variable of the game"
 msgstr ""
+"Edistyneet -valikko on paikka jonka kautta voit säätää pelien jokaista osa-"
+"aluetta ja muuttujaa"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:157
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qh:6
 msgid "Factory reset"
-msgstr ""
+msgstr "Nollaus tehdasasetuksiin"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:31
 msgid "Cvar filter:"
@@ -8856,7 +9094,7 @@ msgstr "Cvar suodatin"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:38
 msgid "Modified cvars only"
-msgstr ""
+msgstr "Vain mukautetut cvar:it"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:45
 msgid "Setting:"
@@ -8880,19 +9118,19 @@ msgstr "Edistyneet asetukset"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:11
 msgid "Are you sure you want to reset all settings?"
-msgstr ""
+msgstr "Oletko varma että haluat nollata kaikki asetukset?"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:13
 msgid "This will create a backup config in your data directory"
-msgstr ""
+msgstr "Tämä luo varmuuskopion asetuksista data-kansioosi"
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:25
 msgid "Menu Skins"
-msgstr ""
+msgstr "Valikon päällysteet"
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:64
 msgid "Text Language"
-msgstr ""
+msgstr "Tekstin kieli"
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:69
 msgid "Set language"
@@ -8905,26 +9143,30 @@ msgstr "Ota ylimitoitettu raakuus ja karski kieli pois käytöstä"
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:75
 msgid "Replace blood and gibs with content that does not have any gore effects"
 msgstr ""
+"Korvaa veri ja viillokit sisällöllä joka ei sisällä mitään hurmeosastoa"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10
 msgid "While connected language changes will be applied only to the menu,"
 msgstr ""
+"Kun kieli jolla yhteys on muodostettu muutetaan, se vaikuttaa vain valikkoon"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12
 msgid "full language changes will take effect starting from the next game"
 msgstr ""
+"kielimuutos astuu voimaan kokonaisuudessaan vasta kun käynnistät seuraavan "
+"pelin"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
 msgid "Disconnect now"
-msgstr ""
+msgstr "Katkaise yhteys nyt"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:17
 msgid "Switch language"
-msgstr ""
+msgstr "Vaihda kieli"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh:6
 msgid "Warning"
-msgstr ""
+msgstr "Varoitus"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:33
 msgid "Resolution:"
@@ -8977,6 +9219,7 @@ msgstr "Värisävy:"
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:53
 msgid "How many bits per pixel (BPP) to render at, 32 is recommended"
 msgstr ""
+"Montako tavua pikseliä kohden (BPP) renderöitäväksi; 32 on suositeltava määrä"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:54
 msgid "16bit"
@@ -8999,6 +9242,8 @@ msgid ""
 "Enable vertical synchronization to prevent tearing, will cap your fps to the "
 "screen refresh rate"
 msgstr ""
+"Ota käyttöön pystysuuntainen yhdenmukaistus välttääksesi ruuturevintää, "
+"rajaa ruudunpäivitystä virkistystaajuuteen nähden"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:67
 msgid "Flip view horizontally"
@@ -9006,7 +9251,7 @@ msgstr "Käännä näkymä horisontaalisesti"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:68
 msgid "Poor man's left handed mode"
-msgstr ""
+msgstr "Köyhänmiehen vasenkäsi -tila"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:71
 msgid "Anisotropy:"
@@ -9014,7 +9259,7 @@ msgstr "Anisotropia:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:73
 msgid "Anisotropic filtering quality"
-msgstr ""
+msgstr "Anisotrooppisen suodatuksen laatu"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:74
 msgid "ANISO^Disabled"
@@ -9047,6 +9292,8 @@ msgid ""
 "Enable antialiasing, which smooths the edges of 3D geometry. Note that it "
 "might decrease performance by quite a lot"
 msgstr ""
+"Kytke päälle anti-aliasing, joka pehmentää 3D-geometrisiä reunoja. Huomaa, "
+"että tämä saattaa alentaa suorituskykyä melkoisesti"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:85
 msgid "AA^Disabled"
@@ -9065,6 +9312,8 @@ msgid ""
 "Eliminate overdraw by rendering a depth-only version of the scene before the "
 "normal rendering starts"
 msgstr ""
+"Poista ylipiirräntä renderöimällä vain-syvyys version kohtauksesta ennen "
+"kuin tavanomainen renderöinti alkaa"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:100
 msgid "DF^Disabled"
@@ -9097,6 +9346,8 @@ msgid ""
 "Make use of Vertex Buffer Objects to store static geometry in video memory "
 "for faster rendering"
 msgstr ""
+"Ota käyttöön Vertex Buffer Objects varastoidaksesi staattista geometriaa "
+"videomuistiin nopeampaa renderöintiä varten"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:113
 msgid "Vertices"
@@ -9112,7 +9363,7 @@ msgstr "Kirkkaus:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:121
 msgid "Brightness of black"
-msgstr ""
+msgstr "Mustan kirkkaus"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:123
 msgid "Contrast:"
@@ -9120,7 +9371,7 @@ msgstr "Kontrasti:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:125
 msgid "Brightness of white"
-msgstr ""
+msgstr "Valkoisen kirkkaus"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:127
 msgid "Gamma:"
@@ -9131,6 +9382,8 @@ msgid ""
 "Inverse gamma correction value, a brightness effect that does not affect "
 "white or black"
 msgstr ""
+"Käännä gamma-kirkkauden korjausmääre, kirkkausefekti joka ei vaikuta "
+"valkoiseen tai mustaan"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:133
 msgid "Contrast boost:"
@@ -9138,7 +9391,7 @@ msgstr "Kontrastin lisäys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:136
 msgid "By how much to multiply the contrast in dark areas"
-msgstr ""
+msgstr "Monellako kontrasti kerrotaan tummilla alueilla"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:139
 msgid "Saturation:"
@@ -9149,6 +9402,8 @@ msgid ""
 "Saturation adjustment (0 = grayscale, 1 = normal, 2 = oversaturated), "
 "requires GLSL color control"
 msgstr ""
+"Kylläisyyden säätö (0 = harmaasävy, 1 = tavallinen, 2 = ylikylläinen), "
+"vaatii GLSL-värihallinnan"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:146
 msgid "LIT^Ambient:"
@@ -9159,6 +9414,8 @@ msgid ""
 "Ambient lighting, if set too high it tends to make light on maps look dull "
 "and flat"
 msgstr ""
+"Ympäröivä valaistus; mikäli asetettu liian korkeaksi, se tapaa tehdä kartan "
+"valot tylsiksi ja tasapaksuiksi"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:150
 msgid "Intensity:"
@@ -9166,7 +9423,7 @@ msgstr "Intensiivisyys:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:152
 msgid "Global rendering brightness"
-msgstr ""
+msgstr "Yleismaailmallisen renderöinnin kirkkaus"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:155
 msgid "Wait for GPU to finish each frame"
@@ -9177,6 +9434,9 @@ msgid ""
 "Make the CPU wait for the GPU to finish each frame, can help with some "
 "strange input or video lag on some machines"
 msgstr ""
+"Laita suoritin odottamaan näytönohjainta viimeistelläkseen jokaisen "
+"kehyksen; voi auttaa joissakin oudoissa sisääntulo tai videon "
+"laahaamisongelmissa joillakin kokoonpanoilla"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:158
 msgid "Use OpenGL 2.0 shaders (GLSL)"
@@ -9191,6 +9451,8 @@ msgid ""
 "Enable use of GLSL to apply gamma correction, note that it might decrease "
 "performance by a lot"
 msgstr ""
+"Ota käyttöön GLSL toteuttaaksesi gamma-kirkkauskorjauksen, huomaa että tämä "
+"saattaa alentaa suorituskykyä huomattavasti"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:168
 msgid "Psycho coloring (easter egg)"
@@ -9235,6 +9497,8 @@ msgstr "Yksinpeli"
 #: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
 msgid "Play the singleplayer campaign or instant action matches against bots"
 msgstr ""
+"Pelaa yksinpeli-kampanja tai välitön toiminnantäyteinen ottelu botteja "
+"vastaan"
 
 #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
 msgid "Winner"
@@ -9246,7 +9510,7 @@ msgstr "liity 'parhaimpaan' joukkueeseen"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:33
 msgid "Autoselect team (recommended)"
-msgstr ""
+msgstr "Joukkueen automaattivalinta (suositeltava)"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:37
 msgid "red"
@@ -9274,179 +9538,179 @@ msgstr "Joukkueen valinta"
 
 #: qcsrc/menu/xonotic/dialog_uid2name.qc:10
 msgid "Allow player statistics to use your nickname?"
-msgstr ""
+msgstr "Salli pelaajatilastojen käyttää lempinimeäsi?"
 
 #: qcsrc/menu/xonotic/dialog_uid2name.qc:12
 msgid "Answering \"No\" you will appear as \"Anonymous player\""
-msgstr ""
+msgstr "Vastaamalla \"Ei\" näyt muodossa \"Nimetön pelaaja\""
 
 #: qcsrc/menu/xonotic/gametypelist.qc:87
 msgid "teamplay"
-msgstr ""
+msgstr "joukkuepeli"
 
 #: qcsrc/menu/xonotic/gametypelist.qc:89
 msgid "free for all"
-msgstr ""
+msgstr "kaikille vapaa"
 
 #: qcsrc/menu/xonotic/keybinder.qc:35
 msgid "Moving"
-msgstr ""
+msgstr "Liikkeet"
 
 #: qcsrc/menu/xonotic/keybinder.qc:36
 msgid "forward"
-msgstr ""
+msgstr "eteenpäin"
 
 #: qcsrc/menu/xonotic/keybinder.qc:37
 msgid "backpedal"
-msgstr ""
+msgstr "taakse"
 
 #: qcsrc/menu/xonotic/keybinder.qc:38
 msgid "strafe left"
-msgstr ""
+msgstr "askella vasemmalle"
 
 #: qcsrc/menu/xonotic/keybinder.qc:39
 msgid "strafe right"
-msgstr ""
+msgstr "askella oikealle"
 
 #: qcsrc/menu/xonotic/keybinder.qc:40
 msgid "jump / swim"
-msgstr ""
+msgstr "hyppää / ui"
 
 #: qcsrc/menu/xonotic/keybinder.qc:41
 msgid "crouch / sink"
-msgstr ""
+msgstr "kyykisty / uppoa"
 
 #: qcsrc/menu/xonotic/keybinder.qc:42
 msgid "off-hand hook"
-msgstr ""
+msgstr "toisenkäden koukku"
 
 #: qcsrc/menu/xonotic/keybinder.qc:43
 msgid "jetpack"
-msgstr ""
+msgstr "lentopakkaus"
 
 #: qcsrc/menu/xonotic/keybinder.qc:46
 msgid "Attacking"
-msgstr ""
+msgstr "Hyökkääminen"
 
 #: qcsrc/menu/xonotic/keybinder.qc:52
 msgid "WEAPON^previous"
-msgstr ""
+msgstr "ASE^edellinen"
 
 #: qcsrc/menu/xonotic/keybinder.qc:53
 msgid "WEAPON^next"
-msgstr ""
+msgstr "ASE^seuraava"
 
 #: qcsrc/menu/xonotic/keybinder.qc:54
 msgid "WEAPON^previously used"
-msgstr ""
+msgstr "ASE^aiemmin käytetty"
 
 #: qcsrc/menu/xonotic/keybinder.qc:55
 msgid "WEAPON^best"
-msgstr ""
+msgstr "ASE^paras"
 
 #: qcsrc/menu/xonotic/keybinder.qc:56
 msgid "reload"
-msgstr ""
+msgstr "lataa uudelleen"
 
 #: qcsrc/menu/xonotic/keybinder.qc:57
 msgid "drop weapon / throw nade"
-msgstr ""
+msgstr "pudota ase / heitä naatti"
 
 #: qcsrc/menu/xonotic/keybinder.qc:86
 msgid "hold zoom"
-msgstr ""
+msgstr "pidä zoom paikallaan"
 
 #: qcsrc/menu/xonotic/keybinder.qc:87
 msgid "toggle zoom"
-msgstr ""
+msgstr "zoom-kytkin"
 
 #: qcsrc/menu/xonotic/keybinder.qc:88
 msgid "show scores"
-msgstr ""
+msgstr "näytä pisteet"
 
 #: qcsrc/menu/xonotic/keybinder.qc:89
 msgid "screen shot"
-msgstr ""
+msgstr "kuvakaappaus"
 
 #: qcsrc/menu/xonotic/keybinder.qc:90
 msgid "maximize radar"
-msgstr ""
+msgstr "suurenna tutka"
 
 #: qcsrc/menu/xonotic/keybinder.qc:91
 msgid "3rd person view"
-msgstr ""
+msgstr "näkymä 3:ssa persoonassa"
 
 #: qcsrc/menu/xonotic/keybinder.qc:92
 msgid "enter spectator mode"
-msgstr ""
+msgstr "käynnistä katsojatila"
 
 #: qcsrc/menu/xonotic/keybinder.qc:95
 msgid "Communicate"
-msgstr ""
+msgstr "Keskustele"
 
 #: qcsrc/menu/xonotic/keybinder.qc:96
 msgid "public chat"
-msgstr ""
+msgstr "julkinen chat-keskustelu"
 
 #: qcsrc/menu/xonotic/keybinder.qc:97 qcsrc/menu/xonotic/keybinder.qc:115
 msgid "team chat"
-msgstr ""
+msgstr "joukkue-chat-keskustelu"
 
 #: qcsrc/menu/xonotic/keybinder.qc:98
 msgid "show chat history"
-msgstr ""
+msgstr "näytä keskusteluhistoria"
 
 #: qcsrc/menu/xonotic/keybinder.qc:99
 msgid "vote YES"
-msgstr ""
+msgstr "äänestä KYLLÄ"
 
 #: qcsrc/menu/xonotic/keybinder.qc:100
 msgid "vote NO"
-msgstr ""
+msgstr "äänestä EI"
 
 #: qcsrc/menu/xonotic/keybinder.qc:104
 msgid "Client"
-msgstr ""
+msgstr "Asiakasohjelma"
 
 #: qcsrc/menu/xonotic/keybinder.qc:108
 msgid "enter console"
-msgstr ""
+msgstr "käynnistä pääte"
 
 #: qcsrc/menu/xonotic/keybinder.qc:110
 msgid "disconnect"
-msgstr ""
+msgstr "katkaise yhteys"
 
 #: qcsrc/menu/xonotic/keybinder.qc:111
 msgid "quit"
-msgstr ""
+msgstr "lopeta"
 
 #: qcsrc/menu/xonotic/keybinder.qc:116
 msgid "auto-join team"
-msgstr ""
+msgstr "liity joukkueeseen automaattisesti"
 
 #: qcsrc/menu/xonotic/keybinder.qc:118
 msgid "drop key / drop flag"
-msgstr ""
+msgstr "pudota avain / puodta lippu"
 
 #: qcsrc/menu/xonotic/keybinder.qc:122
 msgid "respawn"
-msgstr ""
+msgstr "uudelleensynty"
 
 #: qcsrc/menu/xonotic/keybinder.qc:123
 msgid "quick menu"
-msgstr ""
+msgstr "pikavalikko"
 
 #: qcsrc/menu/xonotic/keybinder.qc:124
 msgid "sandbox menu"
-msgstr ""
+msgstr "rajattu hiekkalaatikkovalikko"
 
 #: qcsrc/menu/xonotic/keybinder.qc:125
 msgid "drag object"
-msgstr ""
+msgstr "raahaa kohde"
 
 #: qcsrc/menu/xonotic/keybinder.qc:128
 msgid "User defined"
-msgstr ""
+msgstr "Käyttäjän määrittämä"
 
 #: qcsrc/menu/xonotic/mainwindow.qc:65 qcsrc/menu/xonotic/mainwindow.qc:68
 msgid "Do not press this button again!"
@@ -9456,6 +9720,8 @@ msgstr "Älä paina enää näppäintä!"
 msgid ""
 "Huh? Can't play this (m is NULL). Refiltering so this won't happen again."
 msgstr ""
+"Täh? Tätä ei voi pelata (m on NULL-tyhjiö). Uudelleensuodatetaan jotta näin "
+"ei tapahtuisi enää."
 
 #: qcsrc/menu/xonotic/maplist.qc:296
 #, c-format
@@ -9467,6 +9733,8 @@ msgid ""
 "Huh? Can't play this (invalid game type). Refiltering so this won't happen "
 "again."
 msgstr ""
+"Täh? Tätä ei voi pelata (epäkelpo pelityyppi). Uudelleensuodatetaan jotta "
+"näin ei tapahtuisi enää."
 
 #: qcsrc/menu/xonotic/playerlist.qc:102 qcsrc/menu/xonotic/playerlist.qc:112
 msgid "spectator"
@@ -9478,13 +9746,15 @@ msgstr "<mallia ei löytynyt>"
 
 #: qcsrc/menu/xonotic/serverlist.qc:267
 msgid "Favorite"
-msgstr ""
+msgstr "Lemppari"
 
 #: qcsrc/menu/xonotic/serverlist.qc:268
 msgid ""
 "Bookmark the currently highlighted server so that it's faster to find in the "
 "future"
 msgstr ""
+"Laita kirjanmerkiksi tämänhetkinen korostettu palvelin jotta se on nopeampi "
+"löytää tulevassa"
 
 #: qcsrc/menu/xonotic/serverlist.qc:747
 msgid "Ping"
@@ -9492,7 +9762,7 @@ msgstr "Viive"
 
 #: qcsrc/menu/xonotic/serverlist.qc:748
 msgid "Hostname"
-msgstr ""
+msgstr "Palvelinnimi"
 
 #: qcsrc/menu/xonotic/serverlist.qc:749
 msgid "Map"
@@ -9505,74 +9775,74 @@ msgstr "Tyyppi"
 #: qcsrc/menu/xonotic/serverlist.qc:1043
 #, c-format
 msgid "AES level %d"
-msgstr ""
+msgstr "AES taso %d"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1043
 msgid "ENC^none"
-msgstr ""
+msgstr "ENC^ei mikään"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1043
 msgid "encryption:"
-msgstr ""
+msgstr "salaus:"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1044
 #, c-format
 msgid "mod: %s"
-msgstr ""
+msgstr "modi: %s"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1046
 #, c-format
 msgid "modified settings"
-msgstr ""
+msgstr "mukautetut asetukset"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1046
 #, c-format
 msgid "official settings"
-msgstr ""
+msgstr "viralliset asetukset"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1048
 msgid "stats disabled"
-msgstr ""
+msgstr "tilastot pois päältä"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1048
 msgid "stats enabled"
-msgstr ""
+msgstr "tilastot päällä"
 
 #: qcsrc/menu/xonotic/serverlist.qh:152
 msgid "SLCAT^Favorites"
-msgstr ""
+msgstr "SLCAT^Lempparit"
 
 #: qcsrc/menu/xonotic/serverlist.qh:153
 msgid "SLCAT^Recommended"
-msgstr ""
+msgstr "SLCAT^Suositellut"
 
 #: qcsrc/menu/xonotic/serverlist.qh:154
 msgid "SLCAT^Normal Servers"
-msgstr ""
+msgstr "SLCAT^Tavalliset palvelimet"
 
 #: qcsrc/menu/xonotic/serverlist.qh:155
 msgid "SLCAT^Servers"
-msgstr ""
+msgstr "SLCAT^Palvelimet"
 
 #: qcsrc/menu/xonotic/serverlist.qh:156
 msgid "SLCAT^Competitive Mode"
-msgstr ""
+msgstr "SLCAT^Kilpailullinen tila"
 
 #: qcsrc/menu/xonotic/serverlist.qh:157
 msgid "SLCAT^Modified Servers"
-msgstr ""
+msgstr "SLCAT^Mukautetut palvelimet"
 
 #: qcsrc/menu/xonotic/serverlist.qh:158
 msgid "SLCAT^Overkill"
-msgstr ""
+msgstr "SLCAT^Ylimalkaalliset"
 
 #: qcsrc/menu/xonotic/serverlist.qh:159
 msgid "SLCAT^InstaGib"
-msgstr ""
+msgstr "SLCAT^InstaGib-hetitappo"
 
 #: qcsrc/menu/xonotic/serverlist.qh:160
 msgid "SLCAT^Defrag Mode"
-msgstr ""
+msgstr "SLCAT^Epäfrägitila"
 
 #: qcsrc/menu/xonotic/skinlist.qc:70
 msgid "<TITLE>"
@@ -9597,165 +9867,167 @@ msgstr "%s dB"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:14
 msgid "PART^OMG"
-msgstr ""
+msgstr "PART^OMG"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:15
 msgid "PART^Low"
-msgstr ""
+msgstr "PART^Matala"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:16
 msgid "PART^Medium"
-msgstr ""
+msgstr "PART^Keskisuhta"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:17
 #: qcsrc/menu/xonotic/slider_sbfadetime.qc:14
 msgid "PART^Normal"
-msgstr ""
+msgstr "PART^Tavallinen"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:18
 msgid "PART^High"
-msgstr ""
+msgstr "PART^Korkea"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:19
 msgid "PART^Ultra"
-msgstr ""
+msgstr "PART^Mahtava"
 
 #: qcsrc/menu/xonotic/slider_particles.qc:20
 msgid "PART^Ultimate"
-msgstr ""
+msgstr "PART^Jumalainen"
 
 #: qcsrc/menu/xonotic/slider_picmip.qc:13
 msgid ""
 "Change the sharpness of the textures. Lowering it will effectively reduce "
 "texture memory usage, but make the textures appear very blurry."
 msgstr ""
+"Muuta päällysteiden terävyyttä. Alennus vähentää tehokkaasti muistikäyttöä, "
+"mutta saa päällysteet näyttämään hyvin sumuisilta."
 
 #: qcsrc/menu/xonotic/slider_resolution.qc:115
 msgid "Screen resolution"
-msgstr ""
+msgstr "Näytön tarkkuus"
 
 #: qcsrc/menu/xonotic/slider_sbfadetime.qc:13
 msgid "PART^Slow"
-msgstr ""
+msgstr "PART^Hidas"
 
 #: qcsrc/menu/xonotic/slider_sbfadetime.qc:15
 msgid "PART^Fast"
-msgstr ""
+msgstr "PART^Nopea"
 
 #: qcsrc/menu/xonotic/slider_sbfadetime.qc:16
 msgid "PART^Instant"
-msgstr ""
+msgstr "PART^Välitön"
 
 #: qcsrc/menu/xonotic/statslist.qc:29
 msgid "January"
-msgstr ""
+msgstr "Tammikuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:30
 msgid "February"
-msgstr ""
+msgstr "Helmikuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:31
 msgid "March"
-msgstr ""
+msgstr "Maaliskuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:32
 msgid "April"
-msgstr ""
+msgstr "Huhtikuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:33
 msgid "May"
-msgstr ""
+msgstr "Toukokuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:34
 msgid "June"
-msgstr ""
+msgstr "Kesäkuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:35
 msgid "July"
-msgstr ""
+msgstr "Heinäkuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:36
 msgid "August"
-msgstr ""
+msgstr "Elokuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:37
 msgid "September"
-msgstr ""
+msgstr "Syyskuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:38
 msgid "October"
-msgstr ""
+msgstr "Lokakuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:39
 msgid "November"
-msgstr ""
+msgstr "Marraskuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:40
 msgid "December"
-msgstr ""
+msgstr "Joulukuu"
 
 #: qcsrc/menu/xonotic/statslist.qc:96
 msgid "Joined:"
-msgstr ""
+msgstr "Liittyi:"
 
 #: qcsrc/menu/xonotic/statslist.qc:103
 msgid "Last match:"
-msgstr ""
+msgstr "Viimeisin ottelu:"
 
 #: qcsrc/menu/xonotic/statslist.qc:110
 msgid "Time played:"
-msgstr ""
+msgstr "Peliaika:"
 
 #: qcsrc/menu/xonotic/statslist.qc:117 qcsrc/menu/xonotic/statslist.qc:230
 msgid "Favorite map:"
-msgstr ""
+msgstr "Lempikartta:"
 
 #: qcsrc/menu/xonotic/statslist.qc:149 qcsrc/menu/xonotic/statslist.qc:201
 #: qcsrc/menu/xonotic/statslist.qc:244
 #, c-format
 msgid "Matches:"
-msgstr ""
+msgstr "Ottelut:"
 
 #: qcsrc/menu/xonotic/statslist.qc:154
 #, c-format
 msgid "Wins/Losses:"
-msgstr ""
+msgstr "Voitot/Tappiot"
 
 #: qcsrc/menu/xonotic/statslist.qc:155
 #, c-format
 msgid "Win percentage:"
-msgstr ""
+msgstr "Voittoprosentti:"
 
 #: qcsrc/menu/xonotic/statslist.qc:166
 #, c-format
 msgid "Kills/Deaths:"
-msgstr ""
+msgstr "Tapot/Kuolemat"
 
 #: qcsrc/menu/xonotic/statslist.qc:172
 #, c-format
 msgid "Kill ratio:"
-msgstr ""
+msgstr "Tapposuhde:"
 
 #: qcsrc/menu/xonotic/statslist.qc:207
 msgid "ELO:"
-msgstr ""
+msgstr "ELO:"
 
 #: qcsrc/menu/xonotic/statslist.qc:214
 msgid "Rank:"
-msgstr ""
+msgstr "Rankkaustaso:"
 
 #: qcsrc/menu/xonotic/statslist.qc:221
 msgid "Percentile:"
-msgstr ""
+msgstr "Prosenttipiste:"
 
 #: qcsrc/menu/xonotic/statslist.qc:246
 #, c-format
 msgid "%d (unranked)"
-msgstr ""
+msgstr "%d (ei rankattu)"
 
 #: qcsrc/menu/xonotic/util.qc:417
 msgid "Update can be downloaded at:"
-msgstr ""
+msgstr "Päivitys ladattavissa osoitteessa:"
 
 #: qcsrc/menu/xonotic/util.qc:525
 msgid "Autogenerating mapinfo for newly added maps..."
@@ -9777,6 +10049,8 @@ msgid ""
 "^1ERROR: Texture compression is required but not supported.\n"
 "^1Expect visual problems."
 msgstr ""
+"^1VIRHE: Tekstuuripakkaus vaaditaan mutta se ei ole tuettuna.\n"
+"^1Odotettavissa graafisia virheitä."
 
 #: qcsrc/menu/xonotic/util.qc:788
 msgid "Use default"
index 9d2e0105cb4b83c0bf2991ba598782a7334b9a0a..f7f4fd952cd63e8ad64db6964d95864c2aef6cc1 100644 (file)
 # Jakub P. <pedziszewski@gmail.com>, 2015
 # Jakub P. <pedziszewski@gmail.com>, 2015
 # John Smith <myrangd@gmail.com>, 2016
-# karol kosek <transifex@krkk.ct8.pl>, 2020
-# karol kosek <transifex@krkk.ct8.pl>, 2020
-# karol kosek <transifex@krkk.ct8.pl>, 2020
-# karol kosek <transifex@krkk.ct8.pl>, 2020
+# Karol Kosek, 2020
+# Karol Kosek, 2020
+# Karol Kosek, 2020
+# Karol Kosek, 2020
+# Karol Kosek, 2020
 # Kriss Chr <kriss7475@gmail.com>, 2017
 # Piotr Kozica <koza91@gmail.com>, 2016
 # Rafał Szymański <okavasly@gmail.com>, 2017
@@ -25,7 +26,7 @@ msgstr ""
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2019-05-19 07:23+0200\n"
 "PO-Revision-Date: 2020-02-08 12:09+0000\n"
-"Last-Translator: karol kosek <transifex@krkk.ct8.pl>\n"
+"Last-Translator: Karol Kosek\n"
 "Language-Team: Polish (http://www.transifex.com/team-xonotic/xonotic/"
 "language/pl/)\n"
 "Language: pl\n"
index 129dba36e2c6a09ec35974649391ee051a7a9853..8c6a51feaa9fa55bc4ff0c15f2acc28a3a487944 100644 (file)
@@ -8355,3 +8355,27 @@ effect tr_bullet_weak
        trailspacing 32
        underwater
        velocityjitter 16 16 16
+effect TE_TEI_G3_HIT
+       type beam
+       alpha 128 128 256
+       color 0xFFFFFF 0xFFFFFF
+       countabsolute 1
+       size 8 8
+       tex 200 200
+effect TE_TEI_G3_HIT
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
+effect TE_TEI_G3_HIT
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
index 84e73404d078d1daef56af39b2bbb46661081975..7b83618169ce12dc6176bf97f9ecfdc14ea177e7 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index 2b0d14a2735052c1d61a690b9a72963dc460a947..a7e95f56f32ea1909493a71f5416c8b262e5ed36 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index be4a87ae29967cb03d7ed11664abb48f161617a4..646b149d6ca8773132503d938b87323917eb983d 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index db0fc51c6e18bbd47eb8d8ccab963150668b1cdd..f8716369d3b9541d295f4d2051743d1aa6d2891e 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index 4baea48523d4579afcd2cd94f39afb06f14ceefe..16b498a75a059d31b6720e803e5441dfa8b9014e 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index 726620501f0635cca1e0384257bac0bf274069dd..0e0f079e8e25d214aa6553a8b7589dc3b3eb1854 100644 (file)
@@ -276,6 +276,7 @@ seta hud_panel_centerprint_bg_padding ""
 seta hud_panel_centerprint_align "0.5"
 seta hud_panel_centerprint_flip "0"
 seta hud_panel_centerprint_fontscale "1"
+seta hud_panel_centerprint_fontscale_bold "1.8"
 seta hud_panel_centerprint_time "3"
 seta hud_panel_centerprint_fade_in "0.2"
 seta hud_panel_centerprint_fade_out "0.5"
index 27c977d43dd6e84489a6eeb7c33fd5a53223156e..de3fc8a13c701fc583c2e4234599eceb702bc894 100644 (file)
@@ -13,7 +13,7 @@ pl    "Polish" "Polski" 74%
 pt    "Portuguese" "Português" 86%
 pt_BR "Portuguese (Brazil)" "Português (Brasil)" 100%
 ro    "Romanian" "Romana" 75%
-fi    "Finnish" "Suomi" 30%
+fi    "Finnish" "Suomi" 100%
 el    "Greek" "Ελληνική" 47%
 be    "Belarusian" "Беларуская" 55%
 bg    "Bulgarian" "Български" 60%
index f3ed5e07690c3bd5599d767159e290b23b0c16bc..2d52893786d5d7d02c9e4969f4bc300fb8ddcaa8 100644 (file)
@@ -9,6 +9,7 @@
 set g_dodging 0 "set to 1 to enable dodging (quick acceleration in a given direction)"
 
 seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable"
+seta cl_dodging 0 "enable dodging, requires sv_dodging_clientselect to be enabled on the server"
 
 set sv_dodging_air_dodging 0
 set sv_dodging_wall_dodging 0 "allow dodging off walls"
@@ -27,6 +28,7 @@ set sv_dodging_frozen 0 "allow dodging while frozen"
 set sv_dodging_frozen_doubletap 0
 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 sv_dodging_clientselect 0 "allow clients to opt-in to dodging movement with the cl_dodging cvar, dodging will be off for clients by default with this enabled"
 
 
 // ===========
@@ -444,8 +446,9 @@ set g_breakablehook_owner 0 "allow owner to break their own hook"
 // ===========
 //  multijump
 // ===========
-seta cl_multijump 1 "allow multijump mutator"
+seta cl_multijump -1 "allow multijump mutator, set to -1 for the server to decide whether it's enabled"
 set g_multijump 0      "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
+set g_multijump_client 1 "If the client sets cl_multijump to -1, this setting is used for them as a default"
 set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
 set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
 set g_multijump_maxspeed 0
index 823e85bce3c237bae128e9840a882762f4a6ab88..b74f68b3db4d1c3c341c70216e80765f7c28f8cc 100644 (file)
@@ -7,7 +7,7 @@
 //  Main options
 // ==============
 set g_physics_clientselect 0 "allow clients to select their physics set"
-set g_physics_clientselect_options "xonotic nexuiz quake warsow defrag quake3 vecxis quake2 bones overkill"
+set g_physics_clientselect_options "xonotic nexuiz quake warsow defrag quake3 vecxis quake2 bones"
 set g_physics_clientselect_default "" "override default physics"
 
 // =========
index 234f9b0a9a4d9c2883fc8ec124955a9104a6d364..90bf6fb91ffa0cccbb9ef81320af6047ed59e7ba 100644 (file)
@@ -243,6 +243,7 @@ float autocvar_hud_panel_centerprint_fade_subsequent_minfontsize = 0.75;
 float autocvar_hud_panel_centerprint_fade_minfontsize = 0;
 bool autocvar_hud_panel_centerprint_flip;
 float autocvar_hud_panel_centerprint_fontscale;
+float autocvar_hud_panel_centerprint_fontscale_bold = 1.8;
 float autocvar_hud_panel_centerprint_time;
 bool autocvar_hud_panel_chat;
 bool autocvar_hud_panel_engineinfo;
@@ -445,6 +446,7 @@ int autocvar__cl_color;
 int autocvar__cl_playerskin;
 string autocvar__cl_playermodel;
 float autocvar_cl_deathglow;
+float autocvar_cl_deathglow_min = 0.5;
 bool autocvar_developer_csqcentities;
 float autocvar_cl_jetpack_attenuation = 2;
 bool autocvar_cl_showspectators;
index 1272758f76cee3de642322d9ce6ffb2419660e7a..624d997fecd7cc5bb5b51cc83fb106c72755a079 100644 (file)
@@ -1,6 +1,5 @@
 #include "csqcmodel_hooks.qh"
 #include "autocvars.qh"
-#include "csqcmodel_hooks.qh"
 #include "miscfunctions.qh"
 #include <client/mutators/_mod.qh>
 #include "player_skeleton.qh"
@@ -109,7 +108,6 @@ string forceplayermodels_goodmodel;
 int forceplayermodels_goodmodelindex;
 
 .vector glowmod;
-.vector old_glowmod;
 
 void CSQCPlayer_ModelAppearance_PreUpdate(entity this)
 {
@@ -294,16 +292,14 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer)
        {
                if(this.csqcmodel_isdead)
                {
-                       // Fade out to black now...
-                       if(this.old_glowmod == '0 0 0') { this.old_glowmod = this.glowmod; }
-                       this.colormap = 0;
-
-                       this.glowmod = this.old_glowmod * bound(0, 1 - (time - this.death_time) / autocvar_cl_deathglow, 1);
-                       this.glowmod_x = max(this.glowmod.x, 0.0001);
-                       this.glowmod_y = max(this.glowmod.y, 0.0001);
-                       this.glowmod_z = max(this.glowmod.z, 0.0001);
+                       float min_factor = bound(0, autocvar_cl_deathglow_min, 1);
+                       if(this.colormap > 0)
+                               min_factor /= 2;
+                       float glow_fade = bound(0, 1 - (time - this.death_time) / autocvar_cl_deathglow, 1);
+                       this.glowmod *= (min_factor + glow_fade * (1 - min_factor));
+                       if (this.glowmod == '0 0 0')
+                               this.glowmod.x = 0.000001;
                }
-               else if(this.old_glowmod != '0 0 0') { this.old_glowmod = '0 0 0'; }
        }
 
        //printf("CSQCPlayer_ModelAppearance_Apply(): state = %s, colormap = %f, glowmod = %s\n", (this.csqcmodel_isdead ? "DEAD" : "ALIVE"), this.colormap, vtos(this.glowmod));
index 27a33c408b50de484b40dbbd9722b47972756e4e..e23647fb3fb6dd919047b77e9695d386f7d98f6b 100644 (file)
@@ -98,7 +98,6 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        HUD_Write_Cvar("hud_panel_weapons_timeout_speed_in");
                                        HUD_Write_Cvar("hud_panel_weapons_timeout_speed_out");
                                        HUD_Write_Cvar("hud_panel_weapons_onlyowned");
-                                       HUD_Write_Cvar("hud_panel_weapons_orderbyimpulse");
                                        HUD_Write_Cvar("hud_panel_weapons_noncurrent_alpha");
                                        HUD_Write_Cvar("hud_panel_weapons_noncurrent_scale");
                                        HUD_Write_Cvar("hud_panel_weapons_selection_radius");
@@ -194,6 +193,7 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        HUD_Write_Cvar("hud_panel_centerprint_align");
                                        HUD_Write_Cvar("hud_panel_centerprint_flip");
                                        HUD_Write_Cvar("hud_panel_centerprint_fontscale");
+                                       HUD_Write_Cvar("hud_panel_centerprint_fontscale_bold");
                                        HUD_Write_Cvar("hud_panel_centerprint_time");
                                        HUD_Write_Cvar("hud_panel_centerprint_fade_in");
                                        HUD_Write_Cvar("hud_panel_centerprint_fade_out");
index d5601e5a34f86387a532baef847a42e52f903793..446a64ec65649c7266c890f56fdc803f366dec72 100644 (file)
@@ -6,6 +6,9 @@
 #include <client/miscfunctions.qh>
 
 // CenterPrint (#16)
+// These are the functions that draw the text at the center of the screen (e.g. frag messages and server MOTDs).
+// Usually local_notification_centerprint_generic() is called, which in turn calls centerprint_generic(), which
+// uses some kind of macro magic to call HUD_CenterPrint, which draws them on screen using drawcolorcodedstring().
 
 const int CENTERPRINT_MAX_MSGS = 10;
 const int CENTERPRINT_MAX_ENTRIES = 50;
@@ -113,6 +116,7 @@ void reset_centerprint_messages()
                strfree(centerprint_messages[i]);
        }
 }
+
 float hud_configure_cp_generation_time;
 void HUD_CenterPrint ()
 {
@@ -191,15 +195,11 @@ void HUD_CenterPrint ()
                panel_size -= '2 2 0' * panel_bg_padding;
        }
 
+       bool is_bold;
+       string centerprint_message = strzone("");
        int entries;
        float height;
        vector fontsize;
-       // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES);
-       // height = panel_size_y/entries;
-       // fontsize = '1 1 0' * height;
-       height = vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale;
-       fontsize = '1 1 0' * height;
-       entries = bound(1, floor(panel_size.y/height), CENTERPRINT_MAX_ENTRIES);
 
        int i, j, k, n, g;
        float a, sz, align, current_msg_posY = 0, msg_size;
@@ -213,6 +213,21 @@ void HUD_CenterPrint ()
        align = bound(0, autocvar_hud_panel_centerprint_align, 1);
        for (g=0, i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
        {
+               // if the notification starts with ^BOLD make it bold (e.g. frag messages);
+               is_bold = (substring(centerprint_messages[j], 0, 5) == BOLD_OPERATOR);
+               // remove ^BOLD so it doesn't get printed onscreen
+               if (is_bold)
+                       strcpy(centerprint_message, substring(centerprint_messages[j], 5, -1));
+               else
+                       strcpy(centerprint_message, centerprint_messages[j]);
+
+               // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES);
+               // height = panel_size_y/entries;
+               // fontsize = '1 1 0' * height;
+               height = (is_bold) ? vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale_bold : vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale;
+               fontsize = '1 1 0' * height;
+               entries = bound(1, floor(panel_size.y/height), CENTERPRINT_MAX_ENTRIES);
+
                if (j == CENTERPRINT_MAX_MSGS)
                        j = 0;
                if (centerprint_expire_time[j] == -1)
@@ -272,9 +287,9 @@ void HUD_CenterPrint ()
                drawfontscale = hud_scale * sz;
 
                if (centerprint_countdown_num[j])
-                       n = tokenizebyseparator(strreplace("^COUNT", count_seconds(centerprint_countdown_num[j]), centerprint_messages[j]), "\n");
+                       n = tokenizebyseparator(strreplace("^COUNT", count_seconds(centerprint_countdown_num[j]), centerprint_message), "\n");
                else
-                       n = tokenizebyseparator(centerprint_messages[j], "\n");
+                       n = tokenizebyseparator(centerprint_message, "\n");
 
                if (autocvar_hud_panel_centerprint_flip)
                {
@@ -306,7 +321,9 @@ void HUD_CenterPrint ()
                                        if (align)
                                                pos.x = panel_pos.x + (panel_size.x - stringwidth(ts, true, fontsize) * sz) * align;
                                        if (a > 0.5/255.0)  // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
+                                               if (is_bold) draw_beginBoldFont();
                                                drawcolorcodedstring(pos + eY * 0.5 * (1 - sz * hud_scale.x) * fontsize.y, ts, fontsize, a, DRAWFLAG_NORMAL);
+                                               if (is_bold) draw_endBoldFont();
                                        pos.y += fontsize.y;
                                }
                                else
@@ -326,6 +343,7 @@ void HUD_CenterPrint ()
                        if (pos.y < panel_pos.y) // check if the next message can be shown
                        {
                                drawfontscale = hud_scale;
+                               strfree(centerprint_message);
                                return;
                        }
                }
@@ -338,10 +356,13 @@ void HUD_CenterPrint ()
                        if(pos.y > panel_pos.y + panel_size.y - fontsize.y) // check if the next message can be shown
                        {
                                drawfontscale = hud_scale;
+                               strfree(centerprint_message);
                                return;
                        }
                }
        }
+       strfree(centerprint_message);
+
        drawfontscale = hud_scale;
        if (all_messages_expired)
        {
index c58fb2a675f5d191a5ba55d1ee385a0753321a37..a0bd8727a99d271004951553a1d1653f0213cd91 100644 (file)
@@ -863,7 +863,7 @@ void QuickMenu_Default(string target_submenu)
        {
                LOG_INFOF("Couldn't find submenu \"%s\"", target_submenu);
                if(prvm_language != "en")
-                       LOG_INFOF("^3Warning: submenu title must be in English", target_submenu);
+                       LOG_INFO("^3Warning: submenu title must be in English");
                QuickMenu_Buffer_Size = 0;
        }
 }
index 281b2377ff10e839439cd83f002a5ef6ebf93130..ecf8f9f33851ecb3fa8659c76448b134e0f90f8d 100644 (file)
@@ -5,7 +5,7 @@
 #include <client/miscfunctions.qh>
 #include <common/mapinfo.qh>
 
-// Race timer (#6)
+// Race timer (#8)
 
 // return the string of the onscreen race timer
 string MakeRaceString(int cp, float mytime, float theirtime, float othertime, float lapdelta, string theirname)
index a6d1cc941708193c6696c3a2479a3641d26f0eda..08a1a73bb0977148aa8174f48ef67d836aad4ded 100644 (file)
@@ -1604,11 +1604,11 @@ void Scoreboard_Draw()
        draw_endBoldFont();
 
        // Game Info: Game Detail
-       float tl, fl, ll;
-       str = ""; // optionally "^7Limits: "
-       tl = STAT(TIMELIMIT);
-       fl = STAT(FRAGLIMIT);
-       ll = STAT(LEADLIMIT);
+       float tl = STAT(TIMELIMIT);
+       float fl = STAT(FRAGLIMIT);
+       float ll = STAT(LEADLIMIT);
+       float ll_and_fl = STAT(LEADLIMIT_AND_FRAGLIMIT);
+       str = "";
        if(tl > 0)
                str = strcat(str, sprintf(_("^3%1.0f minutes"), tl));
        if(!ISGAMETYPE(LMS))
@@ -1635,7 +1635,14 @@ void Scoreboard_Draw()
                if(ll > 0)
                {
                        if(tl > 0 || fl > 0)
-                               str = strcat(str, "^7 / "); // delimiter
+                       {
+                               // delimiter
+                               if (ll_and_fl && fl > 0)
+                                       str = strcat(str, "^7 & ");
+                               else
+                                       str = strcat(str, "^7 / ");
+                       }
+
                        if(teamplay)
                        {
                                str = strcat(str, sprintf(_("^2+%s %s"), ScoreString(teamscores_flags(ts_primary), ll),
index b7b7e530371b9430a90621262fd34c7ba453f6c2..d6a073a5de91d4798917c424c2f37cc8b3fd70eb 100644 (file)
@@ -136,7 +136,9 @@ void CSQC_Init()
 
        registercvar("cl_shootfromfixedorigin", "");
 
-       registercvar("cl_multijump", "1");
+       registercvar("cl_multijump", "-1");
+
+       registercvar("cl_dodging", "0");
 
        registercvar("cl_spawn_near_teammate", "1");
 
index d801ceabd7d7ccde6edf099e3aacd4b6f67b1a44..1af1b971ffe91272af6cfcb915c1de041cbf49a8 100644 (file)
@@ -422,18 +422,11 @@ void PolyDrawModel(entity e)
 
 void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag)
 {
-       float d;
        vector ringsize, v, t;
        ringsize = radi * '1 1 0';
        centre = HUD_Shift(centre);
        ringsize = HUD_Scale(ringsize);
 
-       float co = cos(f * 2 * M_PI);
-       float si = sin(f * 2 * M_PI);
-       float q = fabs(co) + fabs(si);
-       co /= q;
-       si /= q;
-
        if(f >= 1)
        {
                // draw full rectangle
@@ -454,22 +447,18 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.y -= 0.5 * ringsize.y;        t -= '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               return;  // Complete rectangle, nothing more needed.
+       }
 
-               d = q - 1;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
+       float co = cos(f * 2 * M_PI);
+       float si = sin(f * 2 * M_PI);
+       float q = fabs(co) + fabs(si);
+       co /= q;
+       si /= q;
 
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
-       }
-       else if(f > 0.75)
+       if(f > 0.75)
        {
-               // draw upper and first triangle
+               // draw upper half in full
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
@@ -483,6 +472,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               // draw clipped lower half as a quad
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -494,14 +484,10 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v = centre;                     t = '0.5 0.5 0';
                        v.y -= 0.5 * ringsize.y;        t -= '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-
-               d = q - 0.75;
-               if(d <= 0)
-                       R_EndPolygon();
        }
        else if(f > 0.5)
        {
-               // draw upper triangle
+               // draw upper half in full
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
@@ -515,22 +501,18 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               // draw clipped lower half as a triangle
+               R_BeginPolygon(pic, drawflag, true);
+                       v = centre;                     t = '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
 
-               d = q - 0.5;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
+                       v = centre;                     t = '0.5 0.5 0';
+                       v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
        }
        else if(f > 0.25)
        {
-               // draw first triangle
+               // draw clipped lower half as a quad
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -542,34 +524,30 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v = centre;                     t = '0.5 0.5 0';
                        v.y += 0.5 * ringsize.y;        t += '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-
-               d = q - 0.25;
-               if(d <= 0)
-                       R_EndPolygon();
        }
-       else
+       else if (f > 0)
        {
-               d = q;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
-       }
+               // draw clipped lower half as a triangle
+               R_BeginPolygon(pic, drawflag, true);
+                       v = centre;                     t = '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
 
-       if(d > 0)
-       {
                        v = centre;                     t = '0.5 0.5 0';
-                       v.x += co * 0.5 * ringsize.x;   t += co * '0.5 0.5 0';
-                       v.y += si * 0.5 * ringsize.y;   t += si * '0.5 -0.5 0';
+                       v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-               R_EndPolygon();
        }
+       else
+       {
+               // Nothing to draw.
+               return;
+       }
+
+       // The last, moving vertex.
+               v = centre;                     t = '0.5 0.5 0';
+               v.x += co * 0.5 * ringsize.x;   t += co * '0.5 0.5 0';
+               v.y += si * 0.5 * ringsize.y;   t += si * '0.5 -0.5 0';
+               R_PolygonVertex(v, t, rgb, a);
+       R_EndPolygon();
 }
 
 /** engine callback */
index 74136906e4c6a955c1bace120df660ea08dcdc68..87633056de69b7dbb52e5916b6447352fb3acda7 100644 (file)
@@ -88,7 +88,7 @@ void Draw_ShowNames(entity this)
                        if (eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight) continue;
                        eo.z = 0;
                        if (vdist((vec2(o) - eo), <, autocvar_hud_shownames_antioverlap_distance)
-                           && vlen2(it.origin - view_origin) < vlen2(this.origin - view_origin))
+                               && vlen2(it.origin - view_origin) < vlen2(this.origin - view_origin))
                        {
                                overlap = 1;
                                break;
@@ -97,14 +97,14 @@ void Draw_ShowNames(entity this)
        }
        bool onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
        if (!this.fadedelay) this.fadedelay = time + SHOWNAMES_FADEDELAY;
-       if (this.csqcmodel_isdead)                                                                   // dead player, fade out slowly
+       if (this.csqcmodel_isdead) // dead player, fade out slowly
        {
                this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
        }
        else if (!onscreen || (!this.sameteam && !hit)) // out of view, fade out
        {
                this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
-               this.fadedelay = 0;                         // reset fade in delay, enemy has left the view
+               this.fadedelay = 0; // reset fade in delay, enemy has left the view
        }
        else if (overlap > 0) // tag overlap detected, fade out
        {
@@ -119,14 +119,12 @@ void Draw_ShowNames(entity this)
                this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
        }
        float a = autocvar_hud_shownames_alpha * this.alpha;
-       // multiply by player alpha
        if (!this.sameteam || (this.sv_entnum == player_localentnum))
        {
                float f = entcs_GetAlpha(this.sv_entnum - 1);
                if (f == 0) f = 1;
                if (f < 0) f = 0;
-               // FIXME: alpha is negative when dead, breaking death fade
-               if (!this.csqcmodel_isdead) a *= f;
+               a *= f;
        }
        if (a < ALPHA_MIN_VISIBLE && ISGAMETYPE(CTS)) return;
        if (vdist(this.origin - view_origin, >=, max_shot_distance)) return;
@@ -156,11 +154,10 @@ void Draw_ShowNames(entity this)
                myPos.x += 0.5 * (mySize.x / resize - mySize.x);
                myPos.y += (mySize.y / resize - mySize.y);
                // this is where the origin of the string
-               vector namepos = myPos;
                float namewidth = mySize.x;
                if (autocvar_hud_shownames_status && this.sameteam)
                {
-                       vector pos = namepos + eY * autocvar_hud_shownames_fontsize * resize;
+                       vector pos = myPos + eY * autocvar_hud_shownames_fontsize * resize;
                        vector sz = vec2(0.5 * mySize.x, resize * autocvar_hud_shownames_statusbar_height);
                        if (autocvar_hud_shownames_statusbar_highlight)
                                drawfill(pos + eX * 0.25 * mySize.x, sz, '0.7 0.7 0.7', a / 2, DRAWFLAG_NORMAL);
@@ -178,13 +175,13 @@ void Draw_ShowNames(entity this)
                        }
                }
                string s = entcs_GetName(this.sv_entnum - 1);
-               if ((autocvar_hud_shownames_decolorize == 1 && teamplay)
-                   || autocvar_hud_shownames_decolorize == 2) s = playername(s, entcs_GetTeam(this.sv_entnum - 1));
+               if ((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2)
+                       s = playername(s, entcs_GetTeam(this.sv_entnum - 1));
                drawfontscale = '1 1 0' * resize;
                s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
                float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
-               if (width != namewidth) namepos.x += (namewidth - width) / 2;
-               drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
+               myPos.x = o.x - (width * resize) / 2;
+               drawcolorcodedstring(myPos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
                drawfontscale = '1 1 0';
        }
 }
@@ -216,7 +213,8 @@ void Draw_ShowNames_All()
                        it.sameteam = false;
                }
                bool dead = entcs_IsDead(i) || entcs_IsSpectating(i);
-               if (!it.csqcmodel_isdead) setorigin(it, entcs.origin);
+               if (!it.csqcmodel_isdead || it.alpha > 0)
+                       setorigin(it, entcs.origin);
                it.csqcmodel_isdead = dead;
                Draw_ShowNames(it);
        });
index d45bdf36d4c0a4b29e30da4c65c6246cb5c49184..3713e9a1abc80601fe7aece807abd579a1714790 100644 (file)
@@ -9043,3 +9043,46 @@ SUB(tr_bullet_weak) {
        MY(underwater) = true;
        MY(velocityjitter) = '16.0 16.0 16.0';
 }
+
+// Vaporizer hit effect
+DEF(TE_TEI_G3_HIT);
+SUB(TE_TEI_G3_HIT) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+SUB(TE_TEI_G3_HIT) /* rings */ {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(sizeincrease) = -2;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(trailspacing) = 20;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '2.0 2.0 2.0';
+}
+SUB(TE_TEI_G3_HIT) {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(sizeincrease) = -6;
+       MY(size_min) = 10;
+       MY(size_max) = 10;
+       MY(trailspacing) = 40;
+       MY(type) = "smoke";
+}
index 11bbaea6fb0af43f62e8c014e98718327f0af364..9f38cd9c36252dfe596b2a62e92fc849d2462682 100644 (file)
@@ -438,7 +438,19 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype)
        if(!flag) { return; }
        if((droptype == DROP_PASS) && !receiver) { return; }
 
-       if(flag.speedrunning) { ctf_RespawnFlag(flag); return; }
+       if(flag.speedrunning)
+       {
+               // ensure old waypoints are removed before resetting the flag
+               WaypointSprite_Kill(player.wps_flagcarrier);
+
+               if(player.wps_enemyflagcarrier)
+                       WaypointSprite_Kill(player.wps_enemyflagcarrier);
+
+               if(player.wps_flagreturn)
+                       WaypointSprite_Kill(player.wps_flagreturn);
+               ctf_RespawnFlag(flag);
+               return;
+       }
 
        // reset the flag
        setattachment(flag, NULL, "");
@@ -1135,6 +1147,7 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher))
 .float last_respawn;
 void ctf_RespawnFlag(entity flag)
 {
+       flag.watertype = CONTENT_EMPTY; // TODO: it is unclear why this workaround is needed, likely many other potential breakage points!!
        // check for flag respawn being called twice in a row
        if(flag.last_respawn > time - 0.5)
                { backtrace("flag respawn called twice quickly! please notify Samual about this..."); }
index eaa60f82715cb73d70e1e66c28a8f0ac95275b5e..5b4c80e7f619c6fc0ce768f8c2cb2a09e5067004 100644 (file)
@@ -366,6 +366,9 @@ MUTATOR_HOOKFUNCTION(ft, PlayerDies)
                return true;
        }
 
+       frag_target.respawn_time = time + 1;
+       frag_target.respawn_flags |= RESPAWN_FORCE;
+
        // Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
        // you succeed changing team through the menu: you both really die (gibbing) and get frozen
        if(ITEM_DAMAGE_NEEDKILL(frag_deathtype)
index 1240ee4975596e185a0759ba24f1bc72316499af..5d52ed7cb0379916ea8841585c46c04f71718dfa 100644 (file)
@@ -541,7 +541,12 @@ void kh_WinnerTeam(int winner_team)  // runs when a team wins
                midpoint += thisorigin;
 
                if(!first)
-                       te_lightning2(NULL, lastorigin, thisorigin);
+               {
+                       // TODO: this effect has been replaced due to a possible crash it causes
+                       // see https://gitlab.com/xonotic/darkplaces/issues/123
+                       //te_lightning2(NULL, lastorigin, thisorigin);
+                       Send_Effect(EFFECT_TR_NEXUIZPLASMA, lastorigin, thisorigin, 1);
+               }
                lastorigin = thisorigin;
                if(first)
                        firstorigin = thisorigin;
@@ -549,7 +554,8 @@ void kh_WinnerTeam(int winner_team)  // runs when a team wins
        }
        if(NumTeams(kh_teams) > 2)
        {
-               te_lightning2(NULL, lastorigin, firstorigin);
+               //te_lightning2(NULL, lastorigin, firstorigin); // TODO see above
+               Send_Effect(EFFECT_TR_NEXUIZPLASMA, lastorigin, firstorigin, 1);
        }
        midpoint = midpoint * (1 / NumTeams(kh_teams));
        te_customflash(midpoint, 1000, 1, Team_ColorRGB(winner_team) * 0.5 + '0.5 0.5 0.5');  // make the color >=0.5 in each component
index 8ba0096713342a7c7a5364b95ffe8fb58674c2e2..d095c81347e25414956bbae4ae0fe8fc5ef4b7c4 100644 (file)
@@ -47,8 +47,8 @@ const int IT_STRENGTH                                 = BIT(22);
 const int IT_PICKUPMASK                        = IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS | IT_JETPACK | IT_FUEL_REGEN; // strength and invincible are handled separately
 
 #ifdef SVQC
-const .float strength_finished = _STAT(STRENGTH_FINISHED);
-const .float invincible_finished = _STAT(INVINCIBLE_FINISHED);
+.float strength_finished; // NOTE: this field is used only by map entities, it does not directly apply the strength stat
+.float invincible_finished; // ditto
 
 #define spawnfunc_body(item) \
        if (!Item_IsDefinitionAllowed(item)) \
index 257e5e40f185ddc0bf254b9dc11d926258365cc2..f771b0f83cfea0d7c2a9545c96ea28f04af00d10 100644 (file)
@@ -671,11 +671,8 @@ void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s,
                        }
                        else
                        {
-                               for (;;)
+                               while((s = fgets(fh)))
                                {
-                                       if (!((s = fgets(fh))))
-                                               break;
-
                                        // catch different sorts of comments
                                        if(s == "")                    // empty lines
                                                continue;
index db255ebb7aff0d80f596dfeb91cdf35a43cf988d..44cbd9045307f844f473b15e0895c4a959aebfa2 100644 (file)
@@ -5,11 +5,26 @@ void counter_reset(entity this);
 void counter_use(entity this, entity actor, entity trigger)
 {
        entity store = this;
-       if(this.spawnflags & COUNTER_PER_PLAYER) // FIXME: multiple counters in the map will not function correctly, and upon trigger reset the player won't be able to use it again!
+       if(this.spawnflags & COUNTER_PER_PLAYER)
        {
                if(!IS_PLAYER(actor))
                        return;
-               store = actor;
+               entity mycounter = NULL;
+               IL_EACH(g_counters, it.realowner == actor && it.owner == this,
+               {
+                       mycounter = it;
+                       break;
+               });
+               if(!mycounter)
+               {
+                       mycounter = new_pure(counter);
+                       IL_PUSH(g_counters, mycounter);
+                       mycounter.owner = this;
+                       mycounter.realowner = actor;
+                       mycounter.reset = counter_reset; // NOTE: this may be useless as the player deletes their counters upon respawning
+                       mycounter.counter_cnt = 0;
+               }
+               store = mycounter;
        }
 
        store.counter_cnt += 1;
@@ -27,8 +42,8 @@ void counter_use(entity this, entity actor, entity trigger)
 
                if(this.respawntime)
                {
-                       setthink(this, counter_reset);
-                       this.nextthink = time + this.respawntime;
+                       setthink(store, counter_reset);
+                       store.nextthink = time + this.respawntime;
                }
        }
        else
index d36bd0293cc933ead43f3e2248b46d157cdc91c3..403a87a8920b45361bbbd404a1ff55588c19b6ae 100644 (file)
@@ -4,6 +4,9 @@
 spawnfunc(trigger_counter);
 
 .float counter_cnt;
+
+IntrusiveList g_counters;
+STATIC_INIT(g_counters) { g_counters = IL_NEW(); }
 #endif
 
 const int COUNTER_FIRE_AT_COUNT = BIT(2);
index eee61c993535f063b5ba30eeccdd6db3550b0273..dde1a77c73aeb1a18568da54de88c600107ff70d 100644 (file)
@@ -2,18 +2,21 @@
 #ifdef SVQC
 void trigger_disablerelay_use(entity this, entity actor, entity trigger)
 {
+       if(this.active != ACTIVE_ACTIVE)
+               return;
+
        int a = 0, b = 0;
 
        for(entity e = NULL; (e = find(e, targetname, this.target)); )
        {
-               if(e.use == SUB_UseTargets)
+               if(e.active == ACTIVE_ACTIVE)
                {
-                       e.use = SUB_DontUseTargets;
+                       e.active = ACTIVE_NOT;
                        ++a;
                }
-               else if(e.use == SUB_DontUseTargets)
+               else if(e.active == ACTIVE_NOT)
                {
-                       e.use = SUB_UseTargets;
+                       e.active = ACTIVE_ACTIVE;
                        ++b;
                }
        }
@@ -24,6 +27,8 @@ void trigger_disablerelay_use(entity this, entity actor, entity trigger)
 
 spawnfunc(trigger_disablerelay)
 {
+       this.reset = spawnfunc_trigger_disablerelay; // this spawnfunc resets fully
+       this.active = ACTIVE_ACTIVE;
        this.use = trigger_disablerelay_use;
 }
 #endif
index 9adcd666ecc7ab3e73a8416ddfd118c869adce91..7586bd338428ef644cef1f060ff3db537b630ac2 100644 (file)
@@ -2,6 +2,9 @@
 #ifdef SVQC
 void trigger_relay_if_use(entity this, entity actor, entity trigger)
 {
+       if(this.active != ACTIVE_ACTIVE)
+               return;
+
        int n = this.count;
 
        // TODO make this generic AND faster than nextent()ing through all, if somehow possible
@@ -15,6 +18,8 @@ void trigger_relay_if_use(entity this, entity actor, entity trigger)
 
 spawnfunc(trigger_relay_if)
 {
+       this.reset = spawnfunc_trigger_relay_if; // this spawnfunc resets fully
+       this.active = ACTIVE_ACTIVE;
        this.use = trigger_relay_if_use;
 }
 #endif
index bf03b1542f0f957279c80f8f81ed1dbb891c0eaa..5291f529062b8dd57bfbcaa5d9beaa4342b0cf2b 100644 (file)
@@ -2,6 +2,9 @@
 #ifdef SVQC
 void trigger_relay_teamcheck_use(entity this, entity actor, entity trigger)
 {
+       if(this.active != ACTIVE_ACTIVE)
+               return;
+
        if(actor.team)
        {
                if(this.spawnflags & RELAYTEAMCHECK_INVERT)
@@ -24,11 +27,13 @@ void trigger_relay_teamcheck_use(entity this, entity actor, entity trigger)
 
 void trigger_relay_teamcheck_reset(entity this)
 {
+       this.active = ACTIVE_ACTIVE;
        this.team = this.team_saved;
 }
 
 spawnfunc(trigger_relay_teamcheck)
 {
+       this.active = ACTIVE_ACTIVE;
        this.team_saved = this.team;
        IL_PUSH(g_saved_team, this);
        this.use = trigger_relay_teamcheck_use;
index f7d9df2900c4c8c40403ede1f45bc71ea3fcf326..495deb7988693b565c3d5e9eec12816ec5d22853 100644 (file)
 *              2005 11 29
 */
 
-
-/*
-* Uses a entity calld swampslug to handle players in the swamp
-* It works like this: When the plyer enters teh swamp the spawnfunc_trigger_swamp
-* attaches a new "swampslug" to the player. As long as the plyer is inside
-* the swamp the swamp gives the slug new health. But the slug slowly kills itself
-* so when the player goes outside the swamp, it dies and releases the player from the
-* swamps curses (dmg/slowdown)
-*
-* I do it this way becuz there is no "untouch" event.
-*/
-void swampslug_think(entity this)
-{
-       //Slowly kill the slug
-       this.swamp_lifetime -= 1;
-
-       //Slug dead? then remove curses.
-       if(GetResource(this, RES_HEALTH) <= 0)
-       {
-               if(this.owner.swampslug == this)
-               {
-                       this.owner.in_swamp = false;
-                       this.owner.swampslug = NULL;
-               }
-               delete(this);
-               //centerprint(this.owner,"Killing slug...\n");
-               return;
-       }
-
-       // Slug still alive, so we are still in the swamp
-       // Or we have exited it very recently.
-       // Do the damage and renew the timer.
 #ifdef SVQC
-       Damage (this.owner, this, this, this.dmg, DEATH_SWAMP.m_id, DMG_NOWEP, this.owner.origin, '0 0 0');
-#endif
-
-       this.nextthink = time + this.swamp_interval;
-}
-
-void swamp_touch(entity this, entity toucher)
+void swamp_think(entity this)
 {
-       // If whatever thats touching the swamp is not a player
-       // or if its a dead player, just dont care abt it.
-       if(!IS_PLAYER(toucher) || IS_DEAD(toucher))
-               return;
-
-       EXACTTRIGGER_TOUCH(this, toucher);
+       // set myself as current swampslug where possible
+       IL_EACH(g_swamped, it.swampslug == this,
+       {
+               it.swampslug = NULL;
+               IL_REMOVE(g_swamped, it);
+       });
 
-       // Chech if player alredy got a swampslug.
-       if(!toucher.in_swamp)
+       if(this.active == ACTIVE_ACTIVE)
        {
-               // If not attach one.
-               //centerprint(toucher,"Entering swamp!\n");
-               if(!toucher.swampslug) // just incase
-                       toucher.swampslug = spawn();
-               toucher.swampslug.swamp_lifetime = 2;
-               setthink(toucher.swampslug, swampslug_think);
-               toucher.swampslug.nextthink = time;
-               toucher.swampslug.owner = toucher;
-               toucher.swampslug.dmg = this.dmg;
-               toucher.swampslug.swamp_interval = this.swamp_interval;
-               toucher.swamp_slowdown = this.swamp_slowdown;
-               toucher.in_swamp = true;
-               return;
+               FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, it.swampslug.active == ACTIVE_NOT && IS_PLAYER(it) && !IS_DEAD(it),
+               {
+                       vector emin = it.absmin;
+                       vector emax = it.absmax;
+                       if(this.solid == SOLID_BSP)
+                       {
+                               emin -= '1 1 1';
+                               emax += '1 1 1';
+                       }
+                       if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
+                               if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, it)) // accurate
+                               {
+                                       if(!it.swampslug)
+                                               IL_PUSH(g_swamped, it);
+                                       it.swampslug = this;
+                               }
+               });
+
+               IL_EACH(g_swamped, it.swampslug == this,
+               {
+                       if(time > it.swamp_interval)
+                       {
+                               Damage (it, this, this, this.dmg, DEATH_SWAMP.m_id, DMG_NOWEP, it.origin, '0 0 0');
+                               it.swamp_interval = time + this.swamp_interval;
+                       }
+               });
        }
 
-       //toucher.in_swamp = true;
-
-       //Revitalize players swampslug
-       toucher.swampslug.swamp_lifetime = 2;
-}
-
-REGISTER_NET_LINKED(ENT_CLIENT_SWAMP)
-
-#ifdef SVQC
-float swamp_send(entity this, entity to, float sf)
-{
-       WriteHeader(MSG_ENTITY, ENT_CLIENT_SWAMP);
-
-       WriteByte(MSG_ENTITY, this.dmg); // can probably get away with using a single byte here
-       WriteByte(MSG_ENTITY, this.swamp_slowdown);
-       WriteByte(MSG_ENTITY, this.swamp_interval);
-
-       trigger_common_write(this, false);
-
-       return true;
-}
-
-void swamp_link(entity this)
-{
-       trigger_link(this, swamp_send);
+       this.nextthink = time;
 }
 
 /*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
@@ -116,37 +66,18 @@ slowed down and damaged over time
 spawnfunc(trigger_swamp)
 {
        // Init stuff
-       trigger_init(this);
-       settouch(this, swamp_touch);
+       EXACTTRIGGER_INIT;
+       this.active = ACTIVE_ACTIVE;
+       //trigger_init(this);
+       setthink(this, swamp_think);
+       this.nextthink = time;
 
        // Setup default keys, if missing
-       if(this.dmg <= 0)
+       if(!this.dmg)
                this.dmg = 5;
-       if(this.swamp_interval <= 0)
+       if(!this.swamp_interval)
                this.swamp_interval = 1;
-       if(this.swamp_slowdown <= 0)
+       if(!this.swamp_slowdown)
                this.swamp_slowdown = 0.5;
-
-       swamp_link(this);
-}
-
-#elif defined(CSQC)
-
-NET_HANDLE(ENT_CLIENT_SWAMP, bool isnew)
-{
-       this.dmg = ReadByte();
-       this.swamp_slowdown = ReadByte();
-       this.swamp_interval = ReadByte();
-
-       trigger_common_read(this, false);
-
-       return = true;
-
-       this.classname = "trigger_swamp";
-       this.solid = SOLID_TRIGGER;
-       settouch(this, swamp_touch);
-       this.drawmask = MASK_NORMAL;
-       this.move_time = time;
-       this.entremove = trigger_remove_generic;
 }
 #endif
index bfe860ed03af9561d2c4e37720adb873a4f83438..acb0cb26a920a62a14b3a32394cf4b17fa4bca9d 100644 (file)
@@ -1,17 +1,11 @@
 #pragma once
 
-.float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
+#ifdef SVQC
+IntrusiveList g_swamped;
+STATIC_INIT(g_swamped) { g_swamped = IL_NEW(); }
 
-.bool in_swamp;
 .entity swampslug;            // Uses this to release from swamp ("untouch" fix)
 
 .float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
-.float swamp_lifetime;  // holds the points remaining until slug dies (not quite health!)
-
-#ifdef SVQC
-spawnfunc(trigger_swamp);
+.float swamp_slowdown; //Players in swamp get slowed down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
 #endif
-void swamp_touch(entity this, entity toucher);
-void swampslug_think(entity this);
index 2a0ebec455a3016b192630684880ab66703dcbd5..41ceaa91fab751c6bfa7761d77f15cdc44ff9058 100644 (file)
@@ -57,12 +57,12 @@ MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
 #ifdef CSQC
 MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
 {
-       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+       if(STAT(HEALTH) > 0 && STAT(HEALTH) <= STAT(BLOODLOSS))
                M_ARGV(1, bool) = true; // do_crouch
 }
 MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
 {
-       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+       if(STAT(HEALTH) > 0 && STAT(HEALTH) <= STAT(BLOODLOSS))
                return true;
 }
 #endif
index a65532307c1132a56680e3a9988289d276cf38fd..5b53b3d651c2d76e49ac25e6778fc24a781e7fde 100644 (file)
@@ -4,7 +4,8 @@ string Buff_UndeprecateName(string buffname)
     {
         case "ammoregen": return "ammo";
         case "haste": case "scout": return "speed";
-        case "guard": case "revival": case "regen": return "medic";
+        case "guard": return "resistance";
+        case "revival": case "regen": return "medic";
         case "invis": return "invisible";
         case "jumper": return "jump";
         default: return buffname;
@@ -27,7 +28,7 @@ REGISTER_BUFF(RESISTANCE) {
     this.m_color = '0.36 1 0.07';
 }
 BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(guard, BUFF_RESISTANCE)
 
 REGISTER_BUFF(SPEED) {
     this.m_name = _("Speed");
@@ -46,7 +47,6 @@ REGISTER_BUFF(MEDIC) {
     this.m_color = '1 0.12 0';
 }
 BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(guard, BUFF_MEDIC)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(regen, BUFF_MEDIC)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(revival, BUFF_MEDIC)
 
index 790a10a86b8f16da4b5f0f0f65900d1813ca89a2..349ca20b872c17f468117dccecaa1152128778ca 100644 (file)
@@ -3,10 +3,11 @@
 REGISTER_MUTATOR(cl_buffs, true);
 MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
 {
-    int allBuffs = STAT(BUFFS);
-    FOREACH(Buffs, it.m_itemid & allBuffs, {
-               addPowerupItem(it.m_name, strcat("buff_", it.netname), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
-       });
+       int allBuffs = STAT(BUFFS);
+       if (allBuffs)
+               FOREACH(Buffs, it.m_itemid & allBuffs, {
+                       addPowerupItem(it.m_name, strcat("buff_", it.netname), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
+               });
 }
 MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
 {
index 83b471cd810e0c6ae992c9f115d70abc0cabff2a..82c9a595a64455255c783a84a4ca87f27b7cb45e 100644 (file)
@@ -261,7 +261,7 @@ void buff_Think(entity this)
        }
 
        if(!game_stopped)
-       if((round_handler_IsActive() && !round_handler_IsRoundStarted()) || time >= game_starttime)
+       if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime)
        if(!this.buff_activetime_updated)
        {
                buff_SetCooldown(this, this.buff_activetime);
@@ -282,7 +282,7 @@ void buff_Think(entity this)
 
        if(this.buff_activetime)
        if(!game_stopped)
-       if((round_handler_IsActive() && !round_handler_IsRoundStarted()) || time >= game_starttime)
+       if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime)
        {
                this.buff_activetime = max(0, this.buff_activetime - frametime);
 
@@ -955,7 +955,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                BUFF_ONADD(BUFF_INVISIBLE)
                {
-                       if(time < player.strength_finished && MUTATOR_IS_ENABLED(mutator_instagib))
+                       if(time < STAT(STRENGTH_FINISHED, player) && MUTATOR_IS_ENABLED(mutator_instagib))
                                player.buff_invisible_prev_alpha = default_player_alpha; // we don't want to save the powerup's alpha, as player may lose the powerup while holding the buff
                        else
                                player.buff_invisible_prev_alpha = player.alpha;
@@ -964,7 +964,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                BUFF_ONREM(BUFF_INVISIBLE)
                {
-                       if(time < player.strength_finished && MUTATOR_IS_ENABLED(mutator_instagib))
+                       if(time < STAT(STRENGTH_FINISHED, player) && MUTATOR_IS_ENABLED(mutator_instagib))
                                player.alpha = autocvar_g_instagib_invis_alpha;
                        else
                                player.alpha = player.buff_invisible_prev_alpha;
index 88efc94ebb298e7df9158a872a274abb22e14fce..b585811873758a94aee4a68592364f36ca749005 100644 (file)
@@ -82,3 +82,5 @@ const vector BUFF_MAX = ('16 16 60');
 
 // client side options
 .float cvar_cl_buffs_autoreplace;
+
+float buff_Available(entity buff);
index 84f77314edde094cacbc1b03de4bef5a342f8a1b..696a2d9e5856c64c9c12329b66b4664fd607cbdc 100644 (file)
@@ -2,3 +2,6 @@
 
 float cvar_cl_dodging_timeout;
 REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+
+float cvar_cl_dodging;
+REPLICATE(cvar_cl_dodging, float, "cl_dodging");
index 66d18ac671e8ad9c5ce074c8f74eee7e494fb9f5..3651e9aa07286d42db46bc13b430cb869f74cf83 100644 (file)
@@ -18,6 +18,7 @@
 #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
+#define PHYS_DODGING_CLIENTSELECT                      autocvar_sv_dodging_clientselect
 
 // we ran out of stats slots! TODO: re-enable this when prediction is available for dodging
 #if 0
 #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)
+#define PHYS_DODGING_CLIENTSELECT                      STAT(DODGING_CLIENTSELECT, this)
 #endif
 
 #ifdef CSQC
        float cvar_cl_dodging_timeout;
+       bool cvar_cl_dodging;
+       bool autocvar_cl_dodging;
        #define PHYS_DODGING_FRAMETIME                          (1 / (frametime <= 0 ? 60 : frametime))
        #define PHYS_DODGING_TIMEOUT(s)                         STAT(DODGING_TIMEOUT)
        #define PHYS_DODGING_PRESSED_KEYS(s)            (s).pressedkeys
+       #define PHYS_DODGING_ENABLED(s)                         autocvar_cl_dodging
 #elif defined(SVQC)
        .float cvar_cl_dodging_timeout;
+       .bool cvar_cl_dodging;
        #define PHYS_DODGING_FRAMETIME                          sys_frametime
        #define PHYS_DODGING_TIMEOUT(s)                         CS(s).cvar_cl_dodging_timeout
        #define PHYS_DODGING_PRESSED_KEYS(s)            CS(s).pressedkeys
+       #define PHYS_DODGING_ENABLED(s)                         CS(s).cvar_cl_dodging
 #endif
 
 #ifdef SVQC
@@ -214,7 +221,7 @@ void PM_dodging(entity this)
        if (!this.dodging_action) return;
 
        // when swimming or dead, no dodging allowed..
-       if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this))
+       if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this) || (PHYS_DODGING_CLIENTSELECT && !PHYS_DODGING_ENABLED(this)))
        {
                this.dodging_action = 0;
                this.dodging_direction.x = 0;
@@ -299,6 +306,7 @@ MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
 #ifdef SVQC
 
 REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+REPLICATE(cvar_cl_dodging, bool, "cl_dodging");
 
 MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
 {
index 93812044c6b4b19ec79437ec8acd73dc9719451a..0e0716dd1805263c9eeb7b715bd979c3b91a00d0 100644 (file)
@@ -232,8 +232,8 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPowerups)
 
        if (player.items & ITEM_Invisibility.m_itemid)
        {
-               play_countdown(player, player.strength_finished, SND_POWEROFF);
-               if (time > player.strength_finished)
+               play_countdown(player, STAT(STRENGTH_FINISHED, player), SND_POWEROFF);
+               if (time > STAT(STRENGTH_FINISHED, player))
                {
                        player.alpha = default_player_alpha;
                        player.exteriorweaponentity.alpha = default_weapon_alpha;
@@ -243,7 +243,7 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPowerups)
        }
        else
        {
-               if (time < player.strength_finished)
+               if (time < STAT(STRENGTH_FINISHED, player))
                {
                        player.alpha = autocvar_g_instagib_invis_alpha;
                        player.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
@@ -255,8 +255,8 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPowerups)
 
        if (player.items & ITEM_Speed.m_itemid)
        {
-               play_countdown(player, player.invincible_finished, SND_POWEROFF);
-               if (time > player.invincible_finished)
+               play_countdown(player, STAT(INVINCIBLE_FINISHED, player), SND_POWEROFF);
+               if (time > STAT(INVINCIBLE_FINISHED, player))
                {
                        player.items &= ~ITEM_Speed.m_itemid;
                        Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_POWERDOWN_SPEED);
@@ -264,7 +264,7 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPowerups)
        }
        else
        {
-               if (time < player.invincible_finished)
+               if (time < STAT(INVINCIBLE_FINISHED, player))
                {
                        player.items |= ITEM_Speed.m_itemid;
                        Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_SPEED, player.netname);
index 0efd85635cc88503b9998675c59eaf2369fd347c..40bc9a33e96d57c469a5fa27e1dcef40a30e14d6 100644 (file)
@@ -20,16 +20,17 @@ REGISTER_MUTATOR(multijump, true);
 #define PHYS_MULTIJUMP_MAXSPEED(s)             STAT(MULTIJUMP_MAXSPEED, s)
 #define PHYS_MULTIJUMP_DODGING(s)              STAT(MULTIJUMP_DODGING, s)
 #define PHYS_MULTIJUMP_COUNT(s)                STAT(MULTIJUMP_COUNT, s)
+#define PHYS_MULTIJUMP_CLIENTDEFAULT(s)        STAT(MULTIJUMP_CLIENT, s)
 
 .bool multijump_ready;
 
 #ifdef CSQC
-bool cvar_cl_multijump;
-bool autocvar_cl_multijump = true;
+int cvar_cl_multijump;
+int autocvar_cl_multijump = -1;
 
        #define PHYS_MULTIJUMP_CLIENT(s)        autocvar_cl_multijump
 #elif defined(SVQC)
-.bool cvar_cl_multijump;
+.int cvar_cl_multijump;
 
        #define PHYS_MULTIJUMP_CLIENT(s)        CS(s).cvar_cl_multijump
 #endif
@@ -54,6 +55,8 @@ MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
        if(!PHYS_MULTIJUMP(player)) { return; }
 
        int client_multijump = PHYS_MULTIJUMP_CLIENT(player);
+       if(client_multijump == -1)
+               client_multijump = PHYS_MULTIJUMP_CLIENTDEFAULT(player);
        if(client_multijump > 1)
                return; // nope
 
@@ -115,7 +118,7 @@ MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
        }
 }
 
-REPLICATE(cvar_cl_multijump, bool, "cl_multijump");
+REPLICATE(cvar_cl_multijump, int, "cl_multijump");
 
 #ifdef SVQC
 
index 510fcf92e19345ca2d371d574f598af356a849df..9ac33b45bb328a612a395fb74f5a206fd62a7644 100644 (file)
@@ -1,6 +1,7 @@
 #include "nades.qh"
 
 #include "../overkill/okmachinegun.qh"
+#include "../overkill/okshotgun.qh"
 
 #ifdef SVQC
 bool autocvar_g_nades_nade_small;
@@ -670,7 +671,9 @@ void nade_heal_boom(entity this)
 
 void nade_monster_boom(entity this)
 {
-       entity e = spawnmonster(spawn(), this.pokenade_type, 0, this.realowner, this.realowner, this.origin, false, false, 1);
+       entity e = spawn();
+       e.noalign = true; // don't drop to floor
+       e = spawnmonster(e, this.pokenade_type, 0, this.realowner, this.realowner, this.origin, false, false, 1);
 
        if(autocvar_g_nades_pokenade_monster_lifetime > 0)
                e.monster_lifetime = time + autocvar_g_nades_pokenade_monster_lifetime;
@@ -892,7 +895,7 @@ void nade_damage(entity this, entity inflictor, entity attacker, float damage, i
        }
        else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_MACHINEGUN))
                damage = this.max_health * 0.1;
-       else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
+       else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_SHOTGUN)) // WEAPONTODO
        {
                if(!(deathtype & HITTYPE_SECONDARY))
                        damage = this.max_health * 1.15;
index a0a8962a7d02d899ca54f2ee2a483c08158a28b8..68d69ab2f027f25408d1b953cbc627b271b1b72f 100644 (file)
@@ -57,10 +57,8 @@ void W_OverkillHeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity
 
 METHOD(OverkillHeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
-    else
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+       if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
+               PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
 
 METHOD(OverkillHeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
index 17e71f06f8ea9b154f1b0da0881022601942b277..817e369816ac69ad599ac19474fd1d39b1798ab0 100644 (file)
@@ -53,8 +53,6 @@ METHOD(OverkillMachineGun, wr_aim, void(entity thiswep, entity actor, .entity we
 {
        if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
                PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
-       else
-               PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
 
 METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
index eb20082359ec1f25f92643bdd3f6a2b4624ebe17..c721f4571b58fadbaa6f895f6e389bc0a470c955 100644 (file)
@@ -121,16 +121,16 @@ MUTATOR_HOOKFUNCTION(superspec, ItemTouch)
                                }
                        }
 
-               if((it.autospec_flags & ASF_SHIELD && item.invincible_finished) ||
-                       (it.autospec_flags & ASF_STRENGTH && item.strength_finished) ||
-                       (it.autospec_flags & ASF_MEGA_AR && item.itemdef == ITEM_ArmorMega) ||
-                       (it.autospec_flags & ASF_MEGA_HP && item.itemdef == ITEM_HealthMega) ||
-                       (it.autospec_flags & ASF_FLAG_GRAB && item.classname == "item_flag_team"))
+               if(((it.autospec_flags & ASF_SHIELD) && item.invincible_finished) ||
+                       ((it.autospec_flags & ASF_STRENGTH) && item.strength_finished) ||
+                       ((it.autospec_flags & ASF_MEGA_AR) && item.itemdef == ITEM_ArmorMega) ||
+                       ((it.autospec_flags & ASF_MEGA_HP) && item.itemdef == ITEM_HealthMega) ||
+                       ((it.autospec_flags & ASF_FLAG_GRAB) && item.classname == "item_flag_team"))
                {
 
                        if((it.enemy != toucher) || IS_OBSERVER(it))
                        {
-                               if(it.autospec_flags & ASF_OBSERVER_ONLY && !IS_OBSERVER(it))
+                               if((it.autospec_flags & ASF_OBSERVER_ONLY) && !IS_OBSERVER(it))
                                {
                                        if(it.superspec_flags & SSF_VERBOSE)
                                                superspec_msg("", "", it, sprintf("^8Ignored that ^7%s^8 grabbed %s^8 since the observer_only option is ON\n", toucher.netname, item.netname), 2);
@@ -346,7 +346,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand)
 
        if(cmd_name == "followpowerup")
        {
-               FOREACH_CLIENT(IS_PLAYER(it) && (it.strength_finished > time || it.invincible_finished > time), { return superspec_Spectate(player, it); });
+               FOREACH_CLIENT(IS_PLAYER(it) && (STAT(STRENGTH_FINISHED, it) > time || STAT(INVINCIBLE_FINISHED, it) > time), { return superspec_Spectate(player, it); });
 
                superspec_msg("", "", player, "No active powerup\n", 1);
                return true;
@@ -354,7 +354,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand)
 
        if(cmd_name == "followstrength")
        {
-               FOREACH_CLIENT(IS_PLAYER(it) && it.strength_finished > time, { return superspec_Spectate(player, it); });
+               FOREACH_CLIENT(IS_PLAYER(it) && STAT(STRENGTH_FINISHED, it) > time, { return superspec_Spectate(player, it); });
 
                superspec_msg("", "", player, "No active Strength\n", 1);
                return true;
@@ -362,7 +362,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand)
 
        if(cmd_name == "followshield")
        {
-               FOREACH_CLIENT(IS_PLAYER(it) && it.invincible_finished > time, { return superspec_Spectate(player, it); });
+               FOREACH_CLIENT(IS_PLAYER(it) && STAT(INVINCIBLE_FINISHED, it) > time, { return superspec_Spectate(player, it); });
 
                superspec_msg("", "", player, "No active Shield\n", 1);
                return true;
@@ -442,7 +442,7 @@ MUTATOR_HOOKFUNCTION(superspec, PlayerDies)
        entity frag_target = M_ARGV(2, entity);
 
        FOREACH_CLIENT(IS_SPEC(it), {
-               if(it.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && it.enemy == frag_target)
+               if((it.autospec_flags & ASF_FOLLOWKILLER) && IS_PLAYER(frag_attacker) && it.enemy == frag_target)
                {
                        if(it.autospec_flags & ASF_SHOWWHAT)
                                superspec_msg("", "", it, sprintf("^7Following %s^7 due to followkiller\n", frag_attacker.netname), 2);
index 0b0ea6bd920d385915c71ea8b8cf185dfbbcc515..a9a2ee655139555dfc70bb72ae875d9fc2061a28 100644 (file)
 #define N_CONSOLE 1
 #define N_CHATCON 2
 
+// hack to work around the limitations of sprintf
+string multiteam_info_sprintf(string input, string teamname) { return ((input != "") ? sprintf(input, teamname) : ""); }
+
 #define MULTITEAM_INFO(prefix, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
     NOTIF_ADD_AUTOCVAR(INFO_##prefix, defaultvalue) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_1)), TCR(normal, type, 1), TCR(gentle, type, 1)) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_2)), TCR(normal, type, 2), TCR(gentle, type, 2)) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_3)), TCR(normal, type, 3), TCR(gentle, type, 3)) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_4)), TCR(normal, type, 4), TCR(gentle, type, 4))
+    MSG_INFO_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, strnum, flnum, args, hudargs, multiteam_info_sprintf(icon, strtolower(STATIC_NAME_TEAM_1)), TCR(normal, type, 1), TCR(gentle, type, 1)) \
+    MSG_INFO_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, strnum, flnum, args, hudargs, multiteam_info_sprintf(icon, strtolower(STATIC_NAME_TEAM_2)), TCR(normal, type, 2), TCR(gentle, type, 2)) \
+    MSG_INFO_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, strnum, flnum, args, hudargs, multiteam_info_sprintf(icon, strtolower(STATIC_NAME_TEAM_3)), TCR(normal, type, 3), TCR(gentle, type, 3)) \
+    MSG_INFO_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, strnum, flnum, args, hudargs, multiteam_info_sprintf(icon, strtolower(STATIC_NAME_TEAM_4)), TCR(normal, type, 4), TCR(gentle, type, 4))
 
 // MSG_INFO_NOTIFICATIONS
     MSG_INFO_NOTIF(CHAT_NOSPECTATORS,                       N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "")
     MSG_INFO_NOTIF(FREEZETAG_REVIVED,                       N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^BG%s^K3 was revived by ^BG%s"), "")
     MSG_INFO_NOTIF(FREEZETAG_REVIVED_FALL,                  N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^K3 was revived by falling"), "")
     MSG_INFO_NOTIF(FREEZETAG_REVIVED_NADE,                  N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^K3 was revived by their Nade explosion"), "")
-    MSG_INFO_NOTIF(FREEZETAG_AUTO_REVIVED,                  N_CONSOLE,  1, 1, "s1 f1", "",      "",     _("^BG%s^K3 was automatically revived after %s second(s)"), "")
+    MSG_INFO_NOTIF(FREEZETAG_AUTO_REVIVED,                  N_CONSOLE,  1, 1, "s1 f1", "",      "",     _("^BG%s^K3 was automatically revived after %s seconds"), "")
     MSG_INFO_NOTIF(FREEZETAG_SELF,                          N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^K1 froze themself"), "")
 
     MULTITEAM_INFO(ROUND_TEAM_WIN,                          N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG team wins the round"), "", NAME)
 
     #define VERBOSE_MURDER(type) strcat(MURDER_##type, "^BG%s")
 
-    #define MURDER_FRAG             _("^K3%sYou fragged ^BG%s")
-    #define MURDER_FRAG2            _("^K3%sYou scored against ^BG%s")
+    #define MURDER_FRAG             strcat(BOLD_OPERATOR, _("^K3%sYou fragged ^BG%s"))
+    #define MURDER_FRAG2            strcat(BOLD_OPERATOR, _("^K3%sYou scored against ^BG%s"))
     #define MURDER_FRAGGED          _("^K1%sYou were fragged by ^BG%s")
     #define MURDER_FRAGGED2         _("^K1%sYou were scored against by ^BG%s")
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG,                   N_ENABLE,  1, 1, "spree_cen s1",               CPID_Null,  "0 0",  MURDER_FRAG,                    MURDER_FRAG2                   )
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAGGED_VERBOSE,        N_ENABLE,  1, 4, "spree_cen s1 frag_stats",    CPID_Null,  "0 0",  VERBOSE_MURDER(FRAGGED),        VERBOSE_MURDER(FRAGGED2)       )
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_VERBOSE,           N_ENABLE,  1, 2, "spree_cen s1 frag_ping",     CPID_Null,  "0 0",  VERBOSE_MURDER(FRAG),           VERBOSE_MURDER(FRAG2)          )
 
-    #define MURDER_FRAG_FIRE        _("^K3%sYou burned ^BG%s")
-    #define MURDER_FRAG_FIRE2       _("^K3%sYou scored against ^BG%s")
+    #define MURDER_FRAG_FIRE        strcat(BOLD_OPERATOR, _("^K3%sYou burned ^BG%s"))
+    #define MURDER_FRAG_FIRE2       strcat(BOLD_OPERATOR, _("^K3%sYou scored against ^BG%s"))
     #define MURDER_FRAGGED_FIRE     _("^K1%sYou were burned by ^BG%s")
     #define MURDER_FRAGGED_FIRE2    _("^K1%sYou were scored against by ^BG%s")
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_FIRE,              N_ENABLE,  1, 1, "spree_cen s1",               CPID_Null,  "0 0",  MURDER_FRAG_FIRE,               MURDER_FRAG_FIRE2              )
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAGGED_FIRE_VERBOSE,   N_ENABLE,  1, 4, "spree_cen s1 frag_stats",    CPID_Null,  "0 0",  VERBOSE_MURDER(FRAGGED_FIRE),   VERBOSE_MURDER(FRAGGED_FIRE2)  )
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_FIRE_VERBOSE,      N_ENABLE,  1, 2, "spree_cen s1 frag_ping",     CPID_Null,  "0 0",  VERBOSE_MURDER(FRAG_FIRE),      VERBOSE_MURDER(FRAG_FIRE2)     )
 
-    #define MURDER_FRAG_FREEZE      _("^K3%sYou froze ^BG%s")
-    #define MURDER_FRAG_FREEZE2     _("^K3%sYou scored against ^BG%s")
+    #define MURDER_FRAG_FREEZE      strcat(BOLD_OPERATOR, _("^K3%sYou froze ^BG%s"))
+    #define MURDER_FRAG_FREEZE2     strcat(BOLD_OPERATOR, _("^K3%sYou scored against ^BG%s"))
     #define MURDER_FRAGGED_FREEZE   _("^K1%sYou were frozen by ^BG%s")
     #define MURDER_FRAGGED_FREEZE2  _("^K1%sYou were scored against by ^BG%s")
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_FREEZE,            N_ENABLE,  1, 1, "spree_cen s1",               CPID_Null,  "0 0",  MURDER_FRAG_FREEZE,             MURDER_FRAG_FREEZE2            )
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAGGED_FREEZE_VERBOSE, N_ENABLE,  1, 4, "spree_cen s1 frag_stats",    CPID_Null,  "0 0",  VERBOSE_MURDER(FRAGGED_FREEZE), VERBOSE_MURDER(FRAGGED_FREEZE2))
     MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_FREEZE_VERBOSE,    N_ENABLE,  1, 2, "spree_cen s1 frag_ping",     CPID_Null,  "0 0",  VERBOSE_MURDER(FRAG_FREEZE),    VERBOSE_MURDER(FRAG_FREEZE2)   )
 
-    #define MURDER_TYPEFRAG         _("^K1%sYou typefragged ^BG%s")
-    #define MURDER_TYPEFRAG2        _("^K1%sYou scored against ^BG%s^K1 while they were typing")
+    #define MURDER_TYPEFRAG         strcat(BOLD_OPERATOR, _("^K1%sYou typefragged ^BG%s"))
+    #define MURDER_TYPEFRAG2        strcat(BOLD_OPERATOR, _("^K1%sYou scored against ^BG%s^K1 while they were typing"))
     #define MURDER_TYPEFRAGGED      _("^K1%sYou were typefragged by ^BG%s")
     #define MURDER_TYPEFRAGGED2     _("^K1%sYou were scored against by ^BG%s^K1 while typing")
     MSG_CENTER_NOTIF(DEATH_MURDER_TYPEFRAG,               N_ENABLE,  1, 1, "spree_cen s1",               CPID_Null,  "0 0",  MURDER_TYPEFRAG,                MURDER_TYPEFRAG2               )
     MSG_CENTER_NOTIF(FREEZETAG_REVIVE,                  N_ENABLE,    1, 0, "s1",             CPID_Null,              "0 0",  _("^K3You revived ^BG%s"), "")
     MSG_CENTER_NOTIF(FREEZETAG_REVIVE_SELF,             N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^K3You revived yourself"), "")
     MSG_CENTER_NOTIF(FREEZETAG_REVIVED,                 N_ENABLE,    1, 0, "s1",             CPID_Null,              "0 0",  _("^K3You were revived by ^BG%s"), "")
-    MSG_CENTER_NOTIF(FREEZETAG_AUTO_REVIVED,            N_ENABLE,    0, 1, "f1",             CPID_Null,              "0 0",  _("^K3You were automatically revived after %s second(s)"), "")
+    MSG_CENTER_NOTIF(FREEZETAG_AUTO_REVIVED,            N_ENABLE,    0, 1, "f1",             CPID_Null,              "0 0",  _("^K3You were automatically revived after %s seconds"), "")
 
     MSG_CENTER_NOTIF(GENERATOR_UNDERATTACK,             N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^BGThe generator is under attack!"), "")
 
     MSG_CENTER_NOTIF(INSTAGIB_LIVES_REMAINING,          N_ENABLE,    0, 1, "f1",             CPID_Null,              "0 0",  _("^F2Extra lives remaining: ^K1%s"), "")
 
     MSG_CENTER_NOTIF(CAMPAIGN_MESSAGE,                  N_ENABLE,    1, 1, "f1 s1 join_key", CPID_CAMPAIGN_MESSAGE,  "-1 0", strcat(_("Level %s: "), "^BG%s\n^3\n", _("^BGPress ^F2%s^BG to enter the game")), "")
-    MSG_CENTER_NOTIF(MOTD,                              N_ENABLE,    1, 0, "s1 join_key",    CPID_MOTD,              "-1 0", strcat("^BG%s\n^3\n", _("^BGPress ^F2%s^BG to enter the game")), "")
+    MSG_CENTER_NOTIF(MOTD,                              N_ENABLE,    1, 0, "s1",             CPID_MOTD,              "-1 0", "^BG%s", "")
 
     MSG_CENTER_NOTIF(NIX_COUNTDOWN,                     N_ENABLE,    0, 2, "item_wepname",   CPID_NIX,               "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "")
     MSG_CENTER_NOTIF(NIX_NEWWEAPON,                     N_ENABLE,    0, 1, "item_wepname",   CPID_NIX,               "0 0",  _("^F2Active weapon: ^F1%s"), "")
index 192c2243252650ecd02a1936660781a9f09c8b69..3b009b25637a296b28cf93d2978e858df993cf73 100644 (file)
@@ -12,6 +12,9 @@
 #include <client/autocvars.qh>
 #endif
 
+// Operator for bold notifications
+#define BOLD_OPERATOR "^BOLD"
+
 /** main types/groups of notifications */
 ENUMCLASS(MSG)
        /** "Global" AND "personal" announcer messages */
index 5dce802a0461681336a592736bcad9a5248efd8c..cba24ff8e90f2e986ba041f2f8b0597c06b318ae 100644 (file)
@@ -40,7 +40,7 @@ void Physics_UpdateStats(entity this)
        STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
 
        MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
-       float maxspd_mod = PHYS_HIGHSPEED(this);
+       float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active) ? this.swampslug.swamp_slowdown : 1);
         STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
         if (autocvar_g_movement_highspeed_q3_compat) {
           STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
index 612e5b6cde29b84add48892088141f3a636544d3..c77ca16be2a432043f0d8808fa1506b25b0d3a7d 100644 (file)
@@ -16,18 +16,16 @@ const int MAX_CL_STATS = 256;
 // const int STAT_NAILS = 7;
 // const int STAT_ROCKETS = 8;
 // const int STAT_CELLS = 9;
-// const int STAT_ACTIVEWEAPON = 10;
 // const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28
 // const int STAT_VIEWHEIGHT = 16;
 
 #if defined(CSQC)
     #define g_stat_HEALTH getstati(STAT_HEALTH)
-    #define g_stat_ARMOR getstat_int(STAT_ARMOR)
-    #define g_stat_SHELLS getstat_int(STAT_SHELLS)
-    #define g_stat_NAILS getstat_int(STAT_NAILS)
-    #define g_stat_ROCKETS getstat_int(STAT_ROCKETS)
-    #define g_stat_CELLS getstat_int(STAT_CELLS)
-    #define g_stat_ACTIVEWEAPON getstat_int(STAT_ACTIVEWEAPON)
+    #define g_stat_ARMOR getstati(STAT_ARMOR)
+    #define g_stat_SHELLS getstati(STAT_SHELLS)
+    #define g_stat_NAILS getstati(STAT_NAILS)
+    #define g_stat_ROCKETS getstati(STAT_ROCKETS)
+    #define g_stat_CELLS getstati(STAT_CELLS)
     #define g_stat_ITEMS getstat_int(STAT_ITEMS)
     #define g_stat_VIEWHEIGHT getstati(STAT_VIEWHEIGHT)
 #elif defined(SVQC)
@@ -37,7 +35,6 @@ const int MAX_CL_STATS = 256;
     #define stat_NAILS ammo_nails
     #define stat_ROCKETS ammo_rockets
     #define stat_CELLS ammo_cells
-    #define stat_ACTIVEWEAPON weapon
     #define stat_ITEMS items
     #define stat_VIEWHEIGHT view_ofs_z
 #endif
@@ -85,6 +82,7 @@ REGISTER_STAT(NB_METERSTART, float)
 /** compressShotOrigin */
 REGISTER_STAT(SHOTORG, int)
 REGISTER_STAT(LEADLIMIT, float, autocvar_leadlimit)
+REGISTER_STAT(LEADLIMIT_AND_FRAGLIMIT, float, autocvar_leadlimit_and_fraglimit)
 
 REGISTER_STAT(LAST_PICKUP, float)
 REGISTER_STAT(HUD, int)
@@ -144,11 +142,13 @@ float autocvar_g_multijump_add;
 float autocvar_g_multijump_speed;
 float autocvar_g_multijump_maxspeed;
 float autocvar_g_multijump_dodging = 1;
+bool autocvar_g_multijump_client = true;
 #endif
 REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
 REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
 REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
 REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+REGISTER_STAT(MULTIJUMP_CLIENT, bool, autocvar_g_multijump_client)
 .int multijump_count;
 REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
 REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
@@ -243,6 +243,7 @@ bool autocvar_sv_dodging_wall_dodging;
 bool autocvar_sv_dodging_air_dodging;
 float autocvar_sv_dodging_maxspeed;
 float autocvar_sv_dodging_air_maxspeed;
+bool autocvar_sv_dodging_clientselect;
 #endif
 
 #if 0
@@ -262,6 +263,7 @@ 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)
+REGISTER_STAT(DODGING_CLIENTSELECT, bool, autocvar_sv_dodging_clientselect)
 #endif
 /** cvar loopback */
 REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
index bd7885d41f5273121d7956b968d2b221b2ee7211..e1d9d583bfbec7c42e13a557dbc2b0642fa56d51 100644 (file)
@@ -23,6 +23,7 @@
     #include <common/weapons/_all.qh>
 
     #include <common/mutators/mutator/buffs/buffs.qh>
+       #include <common/mutators/mutator/buffs/sv_buffs.qh>
 
     #include "../lib/warpzone/util_server.qh"
 #elif defined(CSQC)
@@ -825,17 +826,17 @@ bool Item_GiveTo(entity item, entity player)
        if (item.strength_finished)
        {
                pickedup = true;
-               player.strength_finished = max(player.strength_finished, time) + item.strength_finished;
+               STAT(STRENGTH_FINISHED, player) = max(STAT(STRENGTH_FINISHED, player), time) + item.strength_finished;
        }
        if (item.invincible_finished)
        {
                pickedup = true;
-               player.invincible_finished = max(player.invincible_finished, time) + item.invincible_finished;
+               STAT(INVINCIBLE_FINISHED, player) = max(STAT(INVINCIBLE_FINISHED, player), time) + item.invincible_finished;
        }
        if (item.superweapons_finished)
        {
                pickedup = true;
-               player.superweapons_finished = max(player.superweapons_finished, time) + item.superweapons_finished;
+               STAT(SUPERWEAPONS_FINISHED, player) = max(STAT(SUPERWEAPONS_FINISHED, player), time) + item.superweapons_finished;
        }
 
        // always eat teamed entities
@@ -1478,10 +1479,11 @@ spawnfunc(target_items)
        if(!this.superweapons_finished)
                this.superweapons_finished = autocvar_g_balance_superweapons_time;
 
+       string str;
        int n = tokenize_console(this.netname);
        if(argv(0) == "give")
        {
-               this.netname = substring(this.netname, argv_start_index(1), argv_end_index(-1) - argv_start_index(1));
+               str = substring(this.netname, argv_start_index(1), argv_end_index(-1) - argv_start_index(1));
        }
        else
        {
@@ -1549,27 +1551,29 @@ spawnfunc(target_items)
                        itemprefix = valueprefix = string_null;
                }
 
-               this.netname = "";
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_AMMO), "unlimited_weapon_ammo");
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
-               this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, this.strength_finished * boolean(this.items & ITEM_Strength.m_itemid), "strength");
-               this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, this.invincible_finished * boolean(this.items & ITEM_Shield.m_itemid), "invincible");
-               this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, this.superweapons_finished * boolean(this.items & IT_SUPERWEAPON), "superweapons");
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & ITEM_Jetpack.m_itemid), "jetpack");
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
-               if(GetResource(this, RES_SHELLS) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_SHELLS)), "shells");
-               if(GetResource(this, RES_BULLETS) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_BULLETS)), "nails");
-               if(GetResource(this, RES_ROCKETS) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_ROCKETS)), "rockets");
-               if(GetResource(this, RES_CELLS) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_CELLS)), "cells");
-               if(GetResource(this, RES_PLASMA) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_PLASMA)), "plasma");
-               if(GetResource(this, RES_FUEL) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_FUEL)), "fuel");
-               if(GetResource(this, RES_HEALTH) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_HEALTH)), "health");
-               if(GetResource(this, RES_ARMOR) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_ARMOR)), "armor");
-               FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
-               FOREACH(Weapons, it != WEP_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
-       }
-       this.netname = strzone(this.netname);
-       //print(this.netname, "\n");
+               str = "";
+               str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_AMMO), "unlimited_weapon_ammo");
+               str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
+               str = sprintf("%s %s%d %s", str, valueprefix, this.strength_finished * boolean(this.items & ITEM_Strength.m_itemid), "strength");
+               str = sprintf("%s %s%d %s", str, valueprefix, this.invincible_finished * boolean(this.items & ITEM_Shield.m_itemid), "invincible");
+               str = sprintf("%s %s%d %s", str, valueprefix, this.superweapons_finished * boolean(this.items & IT_SUPERWEAPON), "superweapons");
+               str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_Jetpack.m_itemid), "jetpack");
+               str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
+               float res;
+               res = GetResource(this, RES_SHELLS);  if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "shells");
+               res = GetResource(this, RES_BULLETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "nails");
+               res = GetResource(this, RES_ROCKETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "rockets");
+               res = GetResource(this, RES_CELLS);   if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "cells");
+               res = GetResource(this, RES_PLASMA);  if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "plasma");
+               res = GetResource(this, RES_FUEL);    if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "fuel");
+               res = GetResource(this, RES_HEALTH);  if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "health");
+               res = GetResource(this, RES_ARMOR);   if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "armor");
+               // HACK: buffs share a single timer, so we need to include enabled buffs AFTER disabled ones to avoid loss
+               FOREACH(Buffs, it != BUFF_Null && !(STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
+               FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
+               FOREACH(Weapons, it != WEP_Null, str = sprintf("%s %s%d %s", str, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
+       }
+       this.netname = strzone(str);
 
        n = tokenize_console(this.netname);
        for(int j = 0; j < n; ++j)
@@ -1615,28 +1619,36 @@ float GiveWeapon(entity e, float wpn, float op, float val)
 bool GiveBuff(entity e, Buff thebuff, int op, int val)
 {
        bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
+       float new_buff_time = ((had_buff) ? STAT(BUFF_TIME, e) : 0);
        switch (op)
        {
                case OP_SET:
-                       STAT(BUFF_TIME, e) = val;
+                       new_buff_time = val;
                        break;
                case OP_MIN:
-                       STAT(BUFF_TIME, e) = max(STAT(BUFF_TIME, e), val);
+                       new_buff_time = max(new_buff_time, val);
                        break;
                case OP_MAX:
-                       STAT(BUFF_TIME, e) = min(STAT(BUFF_TIME, e), val);
+                       new_buff_time = min(new_buff_time, val);
                        break;
                case OP_PLUS:
-                       STAT(BUFF_TIME, e) += val;
+                       new_buff_time += val;
                        break;
                case OP_MINUS:
-                       STAT(BUFF_TIME, e) -= val;
+                       new_buff_time -= val;
                        break;
        }
-       if(STAT(BUFF_TIME, e) <= 0)
+       if(new_buff_time <= 0)
+       {
+               if(had_buff)
+                       STAT(BUFF_TIME, e) = new_buff_time;
                STAT(BUFFS, e) &= ~thebuff.m_itemid;
+       }
        else
+       {
+               STAT(BUFF_TIME, e) = new_buff_time;
                STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
+       }
        bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
        return (had_buff != have_buff);
 }
@@ -1667,17 +1679,19 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 bool GiveResourceValue(entity e, int res_type, int op, int val)
 {
        int v0 = GetResource(e, res_type);
+       float new_val = 0;
        switch (op)
        {
                // min 100 cells = at least 100 cells
-               case OP_SET: SetResource(e, res_type, val); break;
-               case OP_MIN: SetResource(e, res_type, max(v0, val)); break;
-               case OP_MAX: SetResource(e, res_type, min(v0, val)); break;
-               case OP_PLUS: SetResource(e, res_type, v0 + val); break;
-               case OP_MINUS: SetResource(e, res_type, v0 - val); break;
-       }
-       int v1 = GetResource(e, res_type);
-       return v0 != v1;
+               case OP_SET: new_val = val; break;
+               case OP_MIN: new_val = max(v0, val); break;
+               case OP_MAX: new_val = min(v0, val); break;
+               case OP_PLUS: new_val = v0 + val; break;
+               case OP_MINUS: new_val = v0 - val; break;
+               default: return false;
+       }
+
+       return SetResourceExplicit(e, res_type, new_val);
 }
 
 float GiveItems(entity e, float beginarg, float endarg)
@@ -1703,16 +1717,16 @@ float GiveItems(entity e, float beginarg, float endarg)
                }
        }
 
-       e.strength_finished = max(0, e.strength_finished - time);
-       e.invincible_finished = max(0, e.invincible_finished - time);
-       e.superweapons_finished = max(0, e.superweapons_finished - time);
+       STAT(STRENGTH_FINISHED, e) = max(0, STAT(STRENGTH_FINISHED, e) - time);
+       STAT(INVINCIBLE_FINISHED, e) = max(0, STAT(INVINCIBLE_FINISHED, e) - time);
+       STAT(SUPERWEAPONS_FINISHED, e) = max(0, STAT(SUPERWEAPONS_FINISHED, e) - time);
        STAT(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
 
        PREGIVE(e, items);
        PREGIVE_WEAPONS(e);
-       PREGIVE(e, strength_finished);
-       PREGIVE(e, invincible_finished);
-       PREGIVE(e, superweapons_finished);
+       PREGIVE(e, stat_STRENGTH_FINISHED);
+       PREGIVE(e, stat_INVINCIBLE_FINISHED);
+       PREGIVE(e, stat_SUPERWEAPONS_FINISHED);
        PREGIVE_RESOURCE(e, RES_BULLETS);
        PREGIVE_RESOURCE(e, RES_CELLS);
        PREGIVE_RESOURCE(e, RES_PLASMA);
@@ -1751,9 +1765,9 @@ float GiveItems(entity e, float beginarg, float endarg)
                                continue;
                        case "ALL":
                                got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
-                               got += GiveValue(e, strength_finished, op, val);
-                               got += GiveValue(e, invincible_finished, op, val);
-                               got += GiveValue(e, superweapons_finished, op, val);
+                               got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
+                               got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
+                               got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
                                got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
                        case "all":
                                got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
@@ -1788,13 +1802,13 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
                                break;
                        case "strength":
-                               got += GiveValue(e, strength_finished, op, val);
+                               got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
                                break;
                        case "invincible":
-                               got += GiveValue(e, invincible_finished, op, val);
+                               got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
                                break;
                        case "superweapons":
-                               got += GiveValue(e, superweapons_finished, op, val);
+                               got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
                                break;
                        case "cells":
                                got += GiveResourceValue(e, RES_CELLS, op, val);
@@ -1822,7 +1836,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveResourceValue(e, RES_FUEL, op, val);
                                break;
                        default:
-                               FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.netname,
+                               FOREACH(Buffs, it != BUFF_Null && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
                                {
                                        got += GiveBuff(e, it, op, val);
                                        break;
@@ -1847,9 +1861,9 @@ float GiveItems(entity e, float beginarg, float endarg)
                        if(STAT(WEAPONS, e) & (it.m_wepset))
                                it.wr_init(it);
        });
-       POSTGIVE_VALUE(e, strength_finished, 1, SND_POWERUP, SND_POWEROFF);
-       POSTGIVE_VALUE(e, invincible_finished, 1, SND_Shield, SND_POWEROFF);
-       //POSTGIVE_VALUE(e, superweapons_finished, 1, SND_Null, SND_Null);
+       POSTGIVE_VALUE(e, stat_STRENGTH_FINISHED, 1, SND_POWERUP, SND_POWEROFF);
+       POSTGIVE_VALUE(e, stat_INVINCIBLE_FINISHED, 1, SND_Shield, SND_POWEROFF);
+       //POSTGIVE_VALUE(e, stat_SUPERWEAPONS_FINISHED, 1, SND_Null, SND_Null);
        POSTGIVE_RESOURCE(e, RES_BULLETS, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_RESOURCE(e, RES_CELLS, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_RESOURCE(e, RES_PLASMA, 0, SND_ITEMPICKUP, SND_Null);
@@ -1859,22 +1873,22 @@ float GiveItems(entity e, float beginarg, float endarg)
        POSTGIVE_RES_ROT(e, RES_ARMOR, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_ARMOR25, SND_Null);
        POSTGIVE_RES_ROT(e, RES_HEALTH, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_MEGAHEALTH, SND_Null);
 
-       if(e.superweapons_finished <= 0)
+       if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
                if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
-                       e.superweapons_finished = autocvar_g_balance_superweapons_time;
+                       STAT(SUPERWEAPONS_FINISHED, e) = autocvar_g_balance_superweapons_time;
 
-       if(e.strength_finished <= 0)
-               e.strength_finished = 0;
+       if(STAT(STRENGTH_FINISHED, e) <= 0)
+               STAT(STRENGTH_FINISHED, e) = 0;
        else
-               e.strength_finished += time;
-       if(e.invincible_finished <= 0)
-               e.invincible_finished = 0;
+               STAT(STRENGTH_FINISHED, e) += time;
+       if(STAT(INVINCIBLE_FINISHED, e) <= 0)
+               STAT(INVINCIBLE_FINISHED, e) = 0;
        else
-               e.invincible_finished += time;
-       if(e.superweapons_finished <= 0)
-               e.superweapons_finished = 0;
+               STAT(INVINCIBLE_FINISHED, e) += time;
+       if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
+               STAT(SUPERWEAPONS_FINISHED, e) = 0;
        else
-               e.superweapons_finished += time;
+               STAT(SUPERWEAPONS_FINISHED, e) += time;
        if(STAT(BUFF_TIME, e) <= 0)
                STAT(BUFF_TIME, e) = 0;
        else
index 21069a94997a4fbf5e93a75c061ffcfeaad74081..ff124d0b496bf42effdc92c167d0a052716b6ad6 100644 (file)
@@ -163,6 +163,8 @@ bool racer_frame(entity this, float dt)
 
        int cont = Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(vehic.origin));
        if(!(cont & DPCONTENTS_WATER))
+               vehic.air_finished = 0;
+       else if (!vehic.air_finished)
                vehic.air_finished = time + autocvar_g_vehicle_racer_water_time;
 
        if(IS_DEAD(vehic))
@@ -253,6 +255,7 @@ bool racer_frame(entity this, float dt)
                }
 
 #ifdef SVQC
+               // NOTE: reusing .invincible_finished here as delay counter for the smoke effect
                if(vehic.invincible_finished < time)
                {
                        traceline(vehic.origin, vehic.origin - '0 0 256', MOVE_NORMAL, vehic);
@@ -262,6 +265,7 @@ bool racer_frame(entity this, float dt)
                        vehic.invincible_finished = time + 0.1 + (random() * 0.1);
                }
 
+               // NOTE: reusing .strength_finished here as a sound delay counter
                if(vehic.strength_finished < time)
                {
                        vehic.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
index f7253d8d8e9985c426adf353858332d0b478f6b4..473f9a7574a32c5cf54da9b0053db68461fd6a95 100644 (file)
@@ -17,12 +17,12 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone
         string tagname = (veh.cnt)
             ? (veh.cnt = 0, "tag_fire1")
             : (veh.cnt = 1, "tag_fire2");
-        vector shotorg = gettaginfo(veh, gettagindex(veh, tagname));
-        w_shotorg = shotorg;
+        vector vshotorg = gettaginfo(veh, gettagindex(veh, tagname));
+        w_shotorg = vshotorg;
         w_shotdir = v_forward;
         // Fix z-aim (for chase mode)
         crosshair_trace(player);
-        w_shotdir.z = normalize(trace_endpos - shotorg).z * 0.5;
+        w_shotdir.z = normalize(trace_endpos - vshotorg).z * 0.5;
 
         if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_WAKI_GUN.m_id);
         vector org = w_shotorg;
index fce84c3b8eb88cc3d0b36a37861a361e5810f103..997f6eb36865648470cf398e2b78294a1ffe1ee1 100644 (file)
@@ -401,7 +401,7 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor, .entity weaponenti
         });
         float desirabledamage;
         desirabledamage = enemydamage;
-        if(time > actor.invincible_finished && time > actor.spawnshieldtime)
+        if(time > STAT(INVINCIBLE_FINISHED, actor) && time > actor.spawnshieldtime)
             desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
         if(teamplay && actor.team)
             desirabledamage = desirabledamage - teamdamage;
index 7f60c5b571d90c84b9d8ff52717c19462300d89d..90090077c1b4c63c3f8207406c82cf6cb3ff32f5 100644 (file)
@@ -389,7 +389,7 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentit
 
         float desirabledamage;
         desirabledamage = enemydamage;
-        if(time > actor.invincible_finished && time > actor.spawnshieldtime)
+        if(time > STAT(INVINCIBLE_FINISHED, actor) && time > actor.spawnshieldtime)
             desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
         if(teamplay && actor.team)
             desirabledamage = desirabledamage - teamdamage;
index cfdbe7b7e933461e0566c9a053255fe9f418da22..e71ed7478a327227a021e91491aaf352bec50784 100644 (file)
@@ -280,7 +280,7 @@ void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
 
 METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(GetResource(actor, thiswep.ammo_type) > 0)
+    if((actor.items & IT_UNLIMITED_AMMO) || GetResource(actor, thiswep.ammo_type) > 0)
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 1, false);
     else
         PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
index 9453157f7000591bf273c07ed20aff7438404636..eaea70f5e9eb33d3fb45377a5d1c6e907aa5d119 100644 (file)
 #undef STAT_MOVEVARS_TIMESCALE
 #undef STAT_MOVEVARS_GRAVITY
 
-#pragma noref 0
-
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
 #define touch move_touch
 
-// deglobalization:
-
 void(vector ang) _makevectors_hidden = #1;
-//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
-
-#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
-//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
-
 void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
-//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
-
-#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 void(vector org, float radius, vector lightcolours) _adddynamiclight_hidden = #305;
-//#define adddynamiclight DO_NOT_USE_GLOBALS_PREFER_ADD_DYNAMIC_LIGHT_MACRO_INSTEAD
-#define adddynamiclight2 DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 void(vector dir) _vectorvectors_hidden = #432;
-#define vectorvectors DO_NOT_USE_GLOBALS_PREFER_VECTOR_VECTORS_MACRO_INSTEAD
-
 vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
-//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
 
-#define getentity DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-#define getentityvec DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+#pragma noref 0
index d6f6a072a0fea688e192219b28e21184a8c7b76b..578d58b27b3c2f68477973fa37035c7dd9cb8347 100644 (file)
@@ -62,21 +62,8 @@ int(string s1, string s2, int len) _strncasecmp = #230;
 int() _buf_create = #460;
 #define buf_create _buf_create
 
-#pragma noref 0
-
-// deglobalization:
-
-#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
-//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
-
 void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
-//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
-
-#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
-//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
+
+#pragma noref 0
index 70e5f378422af7850a91ec65cf8857d6c61ae0d8..93ea3612b7cc50e1fc19547f767a0ce077554b04 100644 (file)
 #else
        #define NULL (RVALUE, world)
 #endif
+
+// Shadow functions which use globals - see deglobalization.qh for details.
+#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
+#define aim DO_NOT_USE_GLOBALS
+#define makestatic DO_NOT_USE_GLOBALS
+#define skel_get_bonerel DO_NOT_USE_GLOBALS
+#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
+#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
+#define skel_mul_bone DO_NOT_USE_GLOBALS
+#define skel_mul_bones DO_NOT_USE_GLOBALS
+#define adddynamiclight DO_NOT_USE_GLOBALS_PREFER_ADD_DYNAMIC_LIGHT_MACRO_INSTEAD
+#define adddynamiclight2 DO_NOT_USE_GLOBALS
+#define vectorvectors DO_NOT_USE_GLOBALS_PREFER_VECTOR_VECTORS_MACRO_INSTEAD
+#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
+#define getentity DO_NOT_USE_GLOBALS
+#define getentityvec DO_NOT_USE_GLOBALS
index a8d8a4a486a0824cb200182a176ebf856762f8ed..f4e2bdaf7b182777ea2fdfcfb417112a19450b2b 100644 (file)
     if (IS_REAL_CLIENT(_cl)) stuffcmd(_cl, __VA_ARGS__); \
 MACRO_END
 
-#pragma noref 0
-
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
 
-// deglobalization:
-
 void(vector ang) _makevectors_hidden = #1;
-//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
 
-#define aim DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+#pragma noref 0
index b9eca8ca8e971859d2385633cad132de62ee1fd7..41506ec31778f41344218c81b42bf70d8cc711f9 100644 (file)
@@ -33,7 +33,12 @@ void sys_phys_update(entity this, float dt)
        if (IS_SVQC) {
                if (this.move_movetype == MOVETYPE_NONE) { return; }
                // when we get here, disableclientprediction cannot be 2
-               this.disableclientprediction = (this.move_qcphysics) ? -1 : 0;
+               if(this.move_movetype == MOVETYPE_FOLLOW) // not compatible with prediction
+                       this.disableclientprediction = 1;
+               else if(this.move_qcphysics)
+                       this.disableclientprediction = -1;
+               else
+                       this.disableclientprediction = 0;
        }
 
        viewloc_PlayerPhysics(this);
@@ -42,7 +47,7 @@ void sys_phys_update(entity this, float dt)
 
        PM_check_blocked(this);
 
-       float maxspeed_mod = (!this.in_swamp) ? 1 : this.swamp_slowdown;  // cvar("g_balance_swamp_moverate");
+       float maxspeed_mod = 1;
 
 // conveyors: first fix velocity
        if (this.conveyor.active) { this.velocity -= this.conveyor.movedir; }
index 3bbb17ccf8715ddfced52d63453e41e7f40cc3e2..0bef0b6e0e944feebfe54c14fea8728a9bc6d295 100644 (file)
 
 #include "warpzone/mathlib.qc"
 
+// needs to be included before any of the functions which use globals are called
+#include "deglobalization.qh"
+
 #include "accumulate.qh"
 #include "angle.qc"
 #include "arraylist.qh"
 #include "counting.qh"
 #include "cvar.qh"
 #include "defer.qh"
-#include "deglobalization.qh"
 #include "draw.qh"
 #include "enumclass.qh"
 #include "file.qh"
index 25fd5cdfa1d84874bf5bb70939ee35f027141e3b..a5610b3de4024428a748bb7aaf375376d569e827 100644 (file)
@@ -108,6 +108,8 @@ void CSQCPlayer_SetMinsMaxs(entity this)
        {
                this.mins = PHYS_PL_MIN(this);
                this.maxs = PHYS_PL_MAX(this);
+               if (IS_DEAD(this))
+                       this.maxs.z = 5;
                this.view_ofs = PHYS_PL_VIEWOFS(this);
        }
 }
@@ -567,7 +569,8 @@ void CSQCPlayer_SetCamera()
 #endif
                        CSQCPlayer_SetMinsMaxs(e);
 
-                       e.angles_y = input_angles.y;
+                       if (!IS_DEAD(e))
+                               e.angles.y = input_angles.y;
                }
 
                // relink
index e8e2c54880a1a29eed6c48d50a6ac0cd44c016ff..4b292a3a5b20a614b7d2fc3f9326c9e79758a8bf 100644 (file)
@@ -30,23 +30,12 @@ string MakeConsoleSafe(string input)
        return input;
 }
 
-ERASEABLE
-void cvar_describe(string name, string desc)
-{
-       localcmd(sprintf("\nset %1$s \"$%1$s\" \"%2$s\"\n", name, MakeConsoleSafe(desc)));
-}
-
-ERASEABLE
-void cvar_archive(string name)
-{
-       localcmd(sprintf("\nseta %1$s \"$%1$s\"\n", name));
-}
-
 ERASEABLE
 void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
 {
-       cvar_describe(name, desc);
-       if (archive) cvar_archive(name);
+       localcmd(sprintf("\nset %1$s \"$%1$s\" \"%2$s\"\n", name, MakeConsoleSafe(desc)));
+       if (archive)
+               localcmd(sprintf("\nseta %1$s \"$%1$s\"\n", name));
 }
 
 int RegisterCvars_Save_fd;
index 3d7f82067440137e64db91a8bc7c78cf53c5ca37..3f71fd8ace4cf920e5a036047208b14b20f8bdeb 100644 (file)
@@ -1,40 +1,85 @@
+#include "lib/accumulate.qh"
 #include "lib/float.qh"
+#include "lib/log.qh"
 #include "lib/misc.qh"
 #include "lib/static.qh"
 #include "lib/vector.qh"
 
-// These macros wrap functions which use globals so mutation only occurs inside them and is not visible from outside.
-// Functions for which all usages are replaced with these macros can be hidden by #defines inside our `*defs.qh` files
-// to prevent anyone from using them accidentally in the future
+// These macros wrap functions which use globals so mutation of global state only occurs inside them and is not visible from outside.
+// This helps prevent bugs where refactoring accidentally breaks implicit assumptions about global state ("pls call makevectors before calling this").
+// Currently only functions that use v_forward/v_right/v_up are wrapped since those are most common.
+// Some functions don't have wrappers because they're not used anywhere.
 
-// TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
-//  - RF_USEAXIS, addentities, predraw,
-//    - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
-//    - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
-//  - e.camera_transform / CL_VM_TransformView (in engine)
-//    - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
+// Steps (slightly inspired by steps in self.qh):
+// 1) (done) Create alternative names for the builtins (e.g. _makevectors_hidden) to be used inside wrappers.
+//    Shadow the originals with macros that tell the user to use the wrappers instead. These are in the *defs.qh files.
+// 2) Create wrapper macros with the same name (e.g. makevectors) that still use globals but log their usage.
+//     - Would be nice to also log reads and writes to the globals themselves. Probably possible with macros, comma expressions and [[alias]].
+// 3) Create wrapper macros that use locals (e.g. MAKE_VECTORS).
+//    TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
+//     - RF_USEAXIS, addentities, predraw,
+//       - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
+//       - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
+//     - e.camera_transform / CL_VM_TransformView (in engine)
+//       - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
+// 4) Gradually replace uses of each function with its wrapper.
+// 5) When a function is no longer used, remove the wrapper with the same name to cause compile errors that will prevent accidental use in the future.
 
-// convenience for deglobalization code - don't use these just to hide that globals are still used
-#define CLEAR_V_GLOBALS() v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN
-#define GET_V_GLOBALS(forward, right, up) forward = v_forward; right = v_right; up = v_up
-#define SET_V_GLOBALS(forward, right, up) v_forward = forward; v_right = right; v_up = up
+// Final checking:
+// When all functions which use a global have been replaced with the wrappers,
+// the wrappers can check that the global contains NaN before its use and set it to NaN after its use.
+// This should detect if there is any remaining global mutation (even in the engine).
+// NaN is the most likely value to expose remaining usages - e.g. functions like traceline crash on it.
+
+#ifdef GAMEQC // menu doesn't use any globals
+
+// compile time switches in case perf is an issue
+#define DEGLOB_LOGGING 1
+#define DEGLOB_CLEAR 1
+
+const int DEGLOB_ORIGINAL = 1;
+const int DEGLOB_WRAPPED = 2;
+#if DEGLOB_LOGGING
+int autocvar_debug_deglobalization_logging = 0;
+// Varargs to this should already be stringized, otherwise they're expanded first which makes them less readable.
+// The downside is redundant quotes, fortunately none of these functions take strings.
+#define DEGLOB_LOG(kind, name, ...) deglob_log(kind, name, __FILE__, __LINE__, __FUNC__, #__VA_ARGS__)
+// This needs to be a function, not a macro,
+// because some wrappers of the old functions need to use comma expressions
+// because they return values.
+void deglob_log(int kind, string name, string file, int line, string func, string more_text) {
+       if (autocvar_debug_deglobalization_logging & kind) {
+               LOG_INFOF("%s %f %s %s:%d:%s args: %s", PROGNAME, time, name, file, line, func, more_text);
+       }
+}
+#else
+#define DEGLOB_LOG(kind, name, ...)
+void deglob_log(int kind, string name, string file, int line, string func, string more_text) {}
+#endif
 
-#ifdef GAMEQC
+// convenience for deglobalization code - don't use these just to hide that globals are still used
+#define GET_V_GLOBALS(forward, right, up) MACRO_BEGIN forward = v_forward; right = v_right; up = v_up; MACRO_END
+#define SET_V_GLOBALS(forward, right, up) MACRO_BEGIN v_forward = forward; v_right = right; v_up = up; MACRO_END
+#if DEGLOB_CLEAR
+bool autocvar_debug_deglobalization_clear = true;
+#define CLEAR_V_GLOBALS() MACRO_BEGIN \
+       if (autocvar_debug_deglobalization_clear) { \
+               v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN \
+       } \
+MACRO_END
 STATIC_INIT(globals) {
        // set to NaN to more easily detect uninitialized use
-       // TODO when all functions are wrapped and the raw functions are not used anymore,
-       // uncomment the defines in *progs.qh files that hide the raw functions
-       // and assert that the global vectors are NaN before calling the raw functions here
-       // to make sure nobody (even builtins) is accidentally using them - NaN is the most likely value to expose remaining usages
-
        CLEAR_V_GLOBALS();
 }
+#else
+#define CLEAR_V_GLOBALS()
 #endif
 
 /// Same as the `makevectors` builtin but uses the provided locals instead of the `v_*` globals.
 /// Always use this instead of raw `makevectors` to make the data flow clear.
 /// Note that you might prefer `FIXED_MAKE_VECTORS` for new code.
 #define MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "MAKE_VECTORS", #angles); \
        _makevectors_hidden(angles); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
@@ -42,24 +87,28 @@ MACRO_END
 
 /// Returns all 4 vectors by assigning to them (instead of returning a value) for consistency (and sanity)
 #define SKEL_GET_BONE_ABS(skel, bonenum, forward, right, up, origin) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "SKEL_GET_BONE_ABS", #skel, #bonenum); \
        origin = _skel_get_boneabs_hidden(skel, bonenum) \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define SKEL_SET_BONE(skel, bonenum, org, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "SKEL_SET_BONE", #skel, #bonenum, #org); \
        SET_V_GLOBALS(forward, right, up); \
        _skel_set_bone_hidden(skel, bonenum, org); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define ADD_DYNAMIC_LIGHT(org, radius, lightcolours, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "ADD_DYNAMIC_LIGHT", #org, #radius, #lightcolours); \
        SET_V_GLOBALS(forward, right, up); \
        _adddynamiclight_hidden(org, radius, lightcolours); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define VECTOR_VECTORS(forward_in, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "VECTOR_VECTORS", #forward_in); \
        _vectorvectors_hidden(forward_in); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
@@ -67,7 +116,40 @@ MACRO_END
 
 /// Note that this only avoids the v_* globals, not the gettaginfo_* ones
 #define GET_TAG_INFO(ent, tagindex, forward, right, up, origin) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "GET_TAG_INFO", #ent, #tagindex); \
        origin = _gettaginfo_hidden(ent, tagindex); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
+
+#undef makevectors
+#define makevectors(angles) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "makevectors", #angles); \
+       _makevectors_hidden(angles); \
+MACRO_END
+
+#undef skel_get_boneabs
+#define skel_get_boneabs(skel, bonenum) ( \
+       deglob_log(DEGLOB_ORIGINAL, "skel_get_boneabs", __FILE__, __LINE__, __FUNC__, #skel ", " #bonenum), \
+       _skel_get_boneabs_hidden(skel, bonenum) \
+)
+
+#undef skel_set_bone
+#define skel_set_bone(skel, bonenum, org) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "skel_set_bone", #skel, #bonenum, #org); \
+       _skel_set_bone_hidden(skel, bonenum, org); \
+MACRO_END
+
+#undef adddynamiclight
+#define adddynamiclight(org, radius, lightcolours) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "adddynamiclight", #org, #radius, #lightcolours); \
+       _adddynamiclight_hidden(org, radius, lightcolours); \
+MACRO_END
+
+#undef gettaginfo
+#define gettaginfo(ent, tagindex) ( \
+       deglob_log(DEGLOB_ORIGINAL, "gettaginfo", __FILE__, __LINE__, __FUNC__, #ent ", " #tagindex), \
+       _gettaginfo_hidden(ent, tagindex) \
+)
+
+#endif // GAMEQC
index 0f609cae8a98b524b86c8cd2245cc814bc190b8f..3069f519dc33454a5310a68a52e9ba16d2570fd8 100644 (file)
@@ -8,7 +8,7 @@
 string prvm_language;
 
 /**
- * @deprecated prefer _("translated") - GMQCC's -ftranslatable-strings feature
+ * @deprecated prefer _("translatable text") - GMQCC's -ftranslatable-strings feature
  */
 ERASEABLE
 string language_filename(string s)
index 279210fb1808040aae9479d827fc43e5a3135ce4..be3fb00fa88ad72aad651d185bc974a4a518fd8e 100644 (file)
@@ -248,7 +248,7 @@ void ONREMOVE(entity this)
        if (this.il_lists) {
                for (int i = 0; i < IL_MAX; ++i) {
                        IntrusiveList list = il_links[i];
-                       if (this.il_lists & list.il_listmask && IL_CONTAINS(list, this)) {
+                       if ((this.il_lists & list.il_listmask) && IL_CONTAINS(list, this)) {
                                IL_REMOVE(list, this);
                        }
                }
index ea7f0e1fe26f62143774a14a217047780abb9e6c..d89dc2b6457ed51d632307c7d41c550646f61567 100644 (file)
@@ -69,7 +69,7 @@ ERASEABLE
 void db_dump(int db, string filename)
 {
        int fh = fopen(filename, FILE_WRITE);
-       if (fh < 0) LOG_FATALF("Can't dump DB to %s");
+       if (fh < 0) LOG_FATALF("Can't dump DB to %s", filename);
        fputs(fh, "0\n");
        for (int i = 0, n = buf_getsize(db); i < n; ++i)
        {
index 57754d04e4334d05da4a3701217d7bf6e17d7cb4..3ce4fcfc8ec01a3506d69bc12ab7ae0f89b07afd 100644 (file)
@@ -147,7 +147,7 @@ void MX_JLF_(entity fh, entity pass, int status)
     switch (status) {
         case URL_READY_CANWRITE: {
             fh.url_content_type = "application/json";
-            url_fputs(fh, sprintf("{}", pass.message));
+            url_fputs(fh, sprintf("{%s}", pass.message));
             url_fclose(fh);
             break;
         }
index ca0e84f67a95b4b8f118eac268d461a64ae6a8a7..6f419954cc5a333f18b856fc6882586debaa65d3 100644 (file)
@@ -69,18 +69,6 @@ float vlen_minnorm2d(vector v)
        return min(max(v.x, -v.x), max(v.y, -v.y));
 }
 
-ERASEABLE
-float dist_point_line(vector p, vector l0, vector ldir)
-{
-       ldir = normalize(ldir);
-
-       // remove the component in line direction
-       p = p - (p * ldir) * ldir;
-
-       // vlen of the remaining vector
-       return vlen(p);
-}
-
 /** requires that m2>m1 in all coordinates, and that m4>m3 */
 ERASEABLE
 float boxesoverlap(vector m1, vector m2, vector m3, vector m4) { return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z; }
@@ -122,6 +110,19 @@ vector Rotate(vector v, float a)
 noref vector _yinvert;
 #define yinvert(v) (_yinvert = (v), _yinvert.y = 1 - _yinvert.y, _yinvert)
 
+/// \param[in] p point
+/// \param[in] l0 starting point of ldir
+/// \param[in] ldir line
+/// \return Vector starting from p perpendicular to ldir
+ERASEABLE
+vector point_line_vec(vector p, vector l0, vector ldir)
+{
+       ldir = normalize(ldir);
+       p = l0 - p;
+       // remove the component in line direction from p
+       return p - ((p * ldir) * ldir);
+}
+
 /**
  * @param dir the directional vector
  * @param norm the normalized normal
index 4f6e4a04a6dbe3201e43430975b00ede72e53c6b..f9b2be71cf770feb9efedcdc0be4de699f3d94aa 100644 (file)
@@ -14,7 +14,7 @@ string KeyBinds_Functions[MAX_KEYBINDS];
 string KeyBinds_Descriptions[MAX_KEYBINDS];
 int KeyBinds_Count = -1;
 
-void KeyBinds_Read()
+void KeyBinds_BuildList()
 {
        KeyBinds_Count = 0;
 
@@ -30,7 +30,7 @@ void KeyBinds_Read()
        #define KEYBIND_HEADER(str) KEYBIND_DEF("", str)
 
        #define KEYBIND_IS_SPECIAL(func) (substring(func, 0 ,1) == "*")
-       #define KEYBIND_SPECIAL_DEF(key) KEYBIND_DEF(strcat("*", key), "")
+       #define KEYBIND_SPECIAL_DEF(key, desc) KEYBIND_DEF(strcat("*", key), desc)
 
        KEYBIND_HEADER(_("Moving"));
        KEYBIND_DEF("+forward"                              , _("forward"));
@@ -56,8 +56,6 @@ void KeyBinds_Read()
        KEYBIND_DEF("reload"                                , _("reload"));
        KEYBIND_DEF("dropweapon"                            , _("drop weapon / throw nade"));
 
-       int i;
-
        #define ADD_TO_W_LIST(pred) \
                FOREACH(Weapons, it != WEP_Null, { \
                        if (it.impulse != imp) continue; \
@@ -92,7 +90,7 @@ void KeyBinds_Read()
        KEYBIND_DEF("spec"                                  , _("enter spectator mode"));
        KEYBIND_EMPTY_LINE();
 
-       KEYBIND_HEADER(_("Communicate"));
+       KEYBIND_HEADER(_("Communication"));
        KEYBIND_DEF("messagemode"                           , _("public chat"));
        KEYBIND_DEF("messagemode2"                          , _("team chat"));
        KEYBIND_DEF("+con_chat_maximize"                    , _("show chat history"));
@@ -106,31 +104,36 @@ void KeyBinds_Read()
        // display the hardcoded shortcut to open the console as it works for all
        // non-English keyboard layouts, unlike default keys (` and ~)
        KEYBIND_DEF("toggleconsole"                         , _("enter console"));
-               KEYBIND_SPECIAL_DEF(strcat(translate_key("SHIFT"), "+", translate_key("ESCAPE")));
+               string console_shortcut = strcat(translate_key("SHIFT"), "+", translate_key("ESCAPE"));
+               KEYBIND_SPECIAL_DEF(console_shortcut, _("enter console"));
        KEYBIND_DEF("disconnect"                            , _("disconnect"));
        KEYBIND_DEF("menu_showquitdialog"                   , _("quit"));
        KEYBIND_EMPTY_LINE();
 
        KEYBIND_HEADER(_("Teamplay"));
-       KEYBIND_DEF("messagemode2"                          , _("team chat"));
        KEYBIND_DEF("team_auto"                             , _("auto-join team"));
        KEYBIND_DEF("menu_showteamselect"                   , _("team menu"));
-       KEYBIND_DEF("+use"                                  , _("drop key / drop flag"));
+       KEYBIND_DEF("spec"                                  , _("spectate"));
        KEYBIND_EMPTY_LINE();
 
        KEYBIND_HEADER(_("Misc"));
-       KEYBIND_DEF("kill"                                  , _("respawn"));
+       KEYBIND_DEF("+use"                                  , _("drop key/flag, exit vehicle"));
+       KEYBIND_DEF("kill"                                  , _("suicide / respawn"));
        KEYBIND_DEF("quickmenu"                             , _("quick menu"));
-       KEYBIND_DEF("menu_showsandboxtools"                 , _("sandbox menu"));
-       KEYBIND_DEF("wpeditor_menu"                         , _("waypoint editor menu"));
-       KEYBIND_DEF("+button8"                              , _("drag object"));
        KEYBIND_EMPTY_LINE();
 
        KEYBIND_HEADER(_("User defined"));
 
-       for(i = 1; i <= 32; ++i)
+       for(int i = 1; i <= 32; ++i)
                KEYBIND_DEF(strcat("+userbind ", itos(i)), strcat("$userbind", itos(i)));
 
+       KEYBIND_EMPTY_LINE();
+
+       KEYBIND_HEADER(_("Development"));
+       KEYBIND_DEF("menu_showsandboxtools"                 , _("sandbox menu"));
+       KEYBIND_DEF("+button8"                              , _("drag object (sandbox)"));
+       KEYBIND_DEF("wpeditor_menu"                         , _("waypoint editor menu"));
+
        #undef KEYBIND_DEF
 }
 
@@ -177,7 +180,7 @@ void XonoticKeyBinder_loadKeyBinds(entity me)
        bool force_initial_selection = false;
        if(KeyBinds_Count < 0) // me.handle not loaded yet?
                force_initial_selection = true;
-       KeyBinds_Read();
+       KeyBinds_BuildList();
        me.nItems = KeyBinds_Count;
        if(force_initial_selection)
                me.setSelected(me, 0);
@@ -246,8 +249,10 @@ void XonoticKeyBinder_keyGrabbed(entity me, int key, bool ascii)
                {
                        k = stof(argv(j));
                        if(k != -1)
-                               //localcmd("\nunbind \"", keynumtostring(k), "\"\n");
+                       {
+                               // bind to empty cmd instead of using unbind so it gets saved in config and overrides any default binds
                                localcmd("\nbind \"", keynumtostring(k), "\" \"", KEY_NOT_BOUND_CMD, "\"\n");
+                       }
                }
        }
        m_play_click_sound(MENU_SOUND_SELECT);
@@ -318,8 +323,10 @@ void KeyBinder_Bind_Clear(entity btn, entity me)
        {
                k = stof(argv(j));
                if(k != -1)
-                       //localcmd("\nunbind \"", keynumtostring(k), "\"\n");
+               {
+                       // bind to empty cmd instead of using unbind so it gets saved in config and overrides any default binds
                        localcmd("\nbind \"", keynumtostring(k), "\" \"", KEY_NOT_BOUND_CMD, "\"\n");
+               }
        }
        m_play_click_sound(MENU_SOUND_CLEAR);
        localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state
@@ -393,9 +400,6 @@ float XonoticKeyBinder_keyDown(entity me, int key, bool ascii, float shift)
 
 void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
-       string s;
-       int j, n;
-       float k;
        vector theColor;
        float theAlpha;
        float extraMargin;
@@ -405,7 +409,6 @@ void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isS
 
        if(func == "")
        {
-               theAlpha = 1;
                theColor = SKINCOLOR_KEYGRABBER_TITLES;
                theAlpha = SKINALPHA_KEYGRABBER_TITLES;
                extraMargin = 0;
@@ -432,7 +435,7 @@ void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isS
 
        if(substring(descr, 0, 1) == "$")
        {
-               s = substring(descr, 1, strlen(descr) - 1);
+               string s = substring(descr, 1, strlen(descr) - 1);
                descr = cvar_string(strcat(s, "_description"));
                if(descr == "")
                        descr = s;
@@ -441,7 +444,7 @@ void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isS
                                theAlpha *= SKINALPHA_DISABLED;
        }
 
-       s = draw_TextShortenToWidth(descr, me.columnFunctionSize, 0, me.realFontSize);
+       string s = draw_TextShortenToWidth(descr, me.columnFunctionSize, 0, me.realFontSize);
        draw_Text(me.realUpperMargin * eY + extraMargin * eX, s, me.realFontSize, theColor, theAlpha, 0);
 
        if (func == "")
@@ -452,15 +455,19 @@ void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isS
                s = substring(func, 1, -1);
        else
        {
-               n = tokenize(findkeysforcommand(func, 0)); // uses '...' strings
-               for(j = 0; j < n; ++j)
+               bool joy_active = cvar("joy_active");
+               int n = tokenize(findkeysforcommand(func, 0)); // uses '...' strings
+               for(int j = 0; j < n; ++j)
                {
-                       k = stof(argv(j));
+                       float k = stof(argv(j));
                        if(k != -1)
                        {
+                               string key = keynumtostring(k);
+                               if (!joy_active && startsWith(key, "JOY"))
+                                       continue;
                                if(s != "")
                                        s = strcat(s, ", ");
-                               s = strcat(s, translate_key(keynumtostring(k)));
+                               s = strcat(s, translate_key(key));
                        }
                }
        }
index 5184ee1fd546a0f90ad3838462a57c005b7b4a9e..a18037db63178830a7e85d675a66564cf01a7a47 100644 (file)
@@ -365,11 +365,11 @@ float XonoticMapList_keyDown(entity me, float scan, float ascii, float shift)
                if(MapInfo_FindName_firstResult >= 0)
                        me.setSelected(me, MapInfo_FindName_firstResult);
        }
-       else if(shift & S_CTRL && scan == 'f') // ctrl-f (as in "F"ind)
+       else if((shift & S_CTRL) && scan == 'f') // ctrl-f (as in "F"ind)
        {
                me.parent.setFocus(me.parent, me.stringFilterBox);
        }
-       else if(shift & S_CTRL && scan == 'u') // ctrl-u (remove stringFilter line
+       else if((shift & S_CTRL) && scan == 'u') // ctrl-u (remove stringFilter line
        {
                me.stringFilterBox.setText(me.stringFilterBox, "");
                MapList_StringFilterBox_Change(me.stringFilterBox, me);
index 021e9765119d7bf70861a5cdccca8d99c1108280..21278f720cc6e37c1ed13d78dc5eca8280885c33 100644 (file)
@@ -8,10 +8,9 @@
 
 void SL_ProcessCategoryOverrides(.string override_field_string, .float override_field)
 {
-       string s;
        for (int i = 0; i < category_ent_count; ++i)
        {
-               s = categories[i].override_field_string;
+               string s = categories[i].override_field_string;
                if (s != "" && s != categories[i].cat_name)
                {
                        int catnum = 0;
@@ -70,22 +69,19 @@ entity RetrieveCategoryEnt(int catnum)
 
 bool IsServerInList(string list, string srv)
 {
-       string p;
-       int i, n;
        if(srv == "")
                return false;
        srv = netaddress_resolve(srv, 26000);
        if(srv == "")
                return false;
-       p = crypto_getidfp(srv);
-       n = tokenize_console(list);
-       for(i = 0; i < n; ++i)
+       string p = crypto_getidfp(srv);
+       int n = tokenize_console(list);
+       for(int i = 0; i < n; ++i)
        {
                if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
                {
-                       if(p)
-                               if(argv(i) == p)
-                                       return true;
+                       if(p && argv(i) == p)
+                               return true;
                }
                else
                {
@@ -96,7 +92,7 @@ bool IsServerInList(string list, string srv)
        return false;
 }
 
-int CheckCategoryOverride(int cat)
+int CategoryOverride(int cat)
 {
        entity catent = RetrieveCategoryEnt(cat);
        if(catent)
@@ -107,12 +103,12 @@ int CheckCategoryOverride(int cat)
        }
        else
        {
-               error(sprintf("CheckCategoryOverride(%d): Improper category number!\n", cat));
+               error(sprintf("CategoryOverride(%d): Improper category number!\n", cat));
                return cat;
        }
 }
 
-int CheckCategoryForEntry(int entry)
+int CategoryForEntry(int entry)
 {
        string s, k, v, modtype = "";
        int j, m, impure = 0, freeslots = 0, sflags = 0;
@@ -199,8 +195,6 @@ int CheckCategoryForEntry(int entry)
                        case "minstagib":
                        case "instagib": { return CAT_INSTAGIB; }
                        case "overkill": { return CAT_OVERKILL; }
-                       //case "nix": { return CAT_NIX; }
-                       //case "newtoys": { return CAT_NEWTOYS; }
 
                        // "cts" is allowed as compat, xdf is replacement
                        case "cts":
@@ -259,8 +253,8 @@ void ServerList_Update_favoriteButton(entity btn, entity me)
        entity e = me.favoriteButton;
        if(IsFavorite(me.ipAddressBox.text))
        {
-               e.setText(e, _("Remove"));
-               clearTooltip(e);
+               e.setText(e, _("Remove favorite"));
+               setZonedTooltip(e, _("Remove the currently highlighted server from bookmarks"), string_null);
        }
        else
        {
@@ -314,14 +308,10 @@ void XonoticServerList_refreshServerList(entity me, int mode)
 
        if(mode >= REFRESHSERVERLIST_REFILTER)
        {
-               float m;
-               int i, n;
-               int listflags = 0;
-               string s, typestr, modstr;
-
-               s = me.filterString;
+               string s = me.filterString;
 
-               m = strstrofs(s, ":", 0);
+               string typestr;
+               int m = strstrofs(s, ":", 0);
                if(m >= 0)
                {
                        typestr = substring(s, 0, m);
@@ -332,7 +322,7 @@ void XonoticServerList_refreshServerList(entity me, int mode)
                else
                        typestr = "";
 
-               modstr = cvar_string("menu_slist_modfilter");
+               string modstr = cvar_string("menu_slist_modfilter");
 
                m = SLIST_MASK_AND - 1;
                resethostcachemasks();
@@ -365,8 +355,8 @@ void XonoticServerList_refreshServerList(entity me, int mode)
                }
 
                // server banning
-               n = tokenizebyseparator(_Nex_ExtResponseSystem_BannedServers, " ");
-               for(i = 0; i < n; ++i)
+               int n = tokenizebyseparator(_Nex_ExtResponseSystem_BannedServers, " ");
+               for(int i = 0; i < n; ++i)
                        if(argv(i) != "")
                                sethostcachemaskstring(++m, SLIST_FIELD_CNAME, argv(i), SLIST_TEST_NOTSTARTSWITH);
 
@@ -379,11 +369,11 @@ void XonoticServerList_refreshServerList(entity me, int mode)
                        sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(s, ":"), SLIST_TEST_STARTSWITH);
                }
 
-               // sorting flags
-               //listflags |= SLSF_FAVORITES;
-               listflags |= SLSF_CATEGORIES;
-               if(me.currentSortOrder < 0) { listflags |= SLSF_DESCENDING; }
-               sethostcachesort(me.currentSortField, listflags);
+               int sorting_flags = 0;
+               //sorting_flags |= SLSF_FAVORITES;
+               sorting_flags |= SLSF_CATEGORIES;
+               if(me.currentSortOrder < 0) { sorting_flags |= SLSF_DESCENDING; }
+               sethostcachesort(me.currentSortField, sorting_flags);
        }
 
        resorthostcache();
@@ -404,9 +394,6 @@ void XonoticServerList_focusEnter(entity me)
 
 void XonoticServerList_draw(entity me)
 {
-       int i;
-       bool found = false, owned;
-
        if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh)
        {
                if(!me.needsRefresh)
@@ -448,9 +435,9 @@ void XonoticServerList_draw(entity me)
                me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
        }
 
-       owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
+       bool owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
 
-       for(i = 0; i < category_draw_count; ++i) { category_name[i] = -1; category_item[i] = -1; }
+       for(int i = 0; i < category_draw_count; ++i) { category_name[i] = -1; category_item[i] = -1; }
        category_draw_count = 0;
 
        if(autocvar_menu_slist_categories >= 0) // if less than 0, don't even draw a category heading for favorites
@@ -541,11 +528,12 @@ void XonoticServerList_draw(entity me)
        }
        else { me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT); }
 
-       me.connectButton.disabled = (me.lockedSelectedItem || (me.nItems == 0 && me.ipAddressBox.text == ""));
+       me.connectButton.disabled = (me.ipAddressBox.text == "");
        //me.disconnectButton.disabled = (!(gamestatus & (GAME_ISSERVER | GAME_CONNECTED)));
-       me.infoButton.disabled = (me.lockedSelectedItem || me.nItems == 0 || !owned);
-       me.favoriteButton.disabled = (me.lockedSelectedItem || (me.nItems == 0 && me.ipAddressBox.text == ""));
+       me.infoButton.disabled = !owned;
+       me.favoriteButton.disabled = (me.ipAddressBox.text == "");
 
+       bool found = false;
        if(me.lockedSelectedItem)
        {
                if(me.nItems > 0)
@@ -559,7 +547,7 @@ void XonoticServerList_draw(entity me)
        }
        else if(me.selectedServer)
        {
-               for(i = 0; i < me.nItems; ++i)
+               for(int i = 0; i < me.nItems; ++i)
                {
                        if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
                        {
@@ -708,13 +696,11 @@ void XonoticServerList_setSortOrder(entity me, int fld, int direction)
 }
 void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
 {
-       vector originInLBSpace, sizeInLBSpace;
-       originInLBSpace = eY * (-me.itemHeight);
-       sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
+       vector originInLBSpace = eY * (-me.itemHeight);
+       vector sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
 
-       vector originInDialogSpace, sizeInDialogSpace;
-       originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
-       sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
+       vector originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
+       vector sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
 
        btn.Container_origin_x = originInDialogSpace.x + sizeInDialogSpace.x * theOrigin;
        btn.Container_size_x   =                         sizeInDialogSpace.x * theSize;
@@ -759,10 +745,8 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize,
 }
 void ServerList_Connect_Click(entity btn, entity me)
 {
-       if (me.lockedSelectedItem)
-               return;
-       string sv = (me.ipAddressBox.text != "") ? me.ipAddressBox.text : me.selectedServer;
-       localcmd(sprintf("connect %s\n", sv));
+       if (me.ipAddressBox.text != "")
+               localcmd(sprintf("connect %s\n", me.ipAddressBox.text));
 }
 void ServerList_Favorite_Click(entity btn, entity this)
 {
@@ -788,33 +772,22 @@ void XonoticServerList_doubleClickListBoxItem(entity me, int i, vector where)
 }
 void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
-       // layout: Ping, Server name, Map name, NP, TP, MP
-       float p;
-       int q;
-       bool isv4, isv6;
-       vector theColor;
-       float theAlpha;
-       bool pure = false, pure_available = false;
-       int freeslots = -1, sflags = -1, j, m;
-       string s, typestr, versionstr, k, v, modname;
-
-       //printf("time: %f, i: %d, item: %d, nitems: %d\n", time, i, item, me.nItems);
-
        vector oldscale = draw_scale;
        vector oldshift = draw_shift;
 #define SET_YRANGE(start,end) \
        draw_scale = boxToGlobalSize(eX + eY * (end - start), oldscale); \
        draw_shift = boxToGlobal(eY * start, oldshift, oldscale);
 
-       for (j = 0; j < category_draw_count; ++j) {
+       int c;
+       for (c = 0; c < category_draw_count; ++c) {
                // Matches exactly the headings with increased height.
-               if (i == category_item[j])
+               if (i == category_item[c])
                        break;
        }
 
-       if (j < category_draw_count)
+       if (c < category_draw_count)
        {
-               entity catent = RetrieveCategoryEnt(category_name[j]);
+               entity catent = RetrieveCategoryEnt(category_name[c]);
                if(catent)
                {
                        SET_YRANGE(
@@ -848,33 +821,34 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
        }
 
-       s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
-       m = tokenizebyseparator(s, ":");
-       typestr = "";
+       string s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
+       int m = tokenizebyseparator(s, ":");
+       string typestr = "", versionstr = "";
        if(m >= 2)
        {
                typestr = argv(0);
                versionstr = argv(1);
        }
-       freeslots = -1;
-       modname = "";
-       for(j = 2; j < m; ++j)
+       bool pure = false, pure_available = false;
+       int freeslots = -1, sflags = -1;
+       string modname = "";
+       for(int j = 2; j < m; ++j)
        {
                if(argv(j) == "")
                        break;
-               k = substring(argv(j), 0, 1);
-               v = substring(argv(j), 1, -1);
-               if(k == "P")
+               string key = substring(argv(j), 0, 1);
+               string value = substring(argv(j), 1, -1);
+               if(key == "P")
                {
-                       pure = (stof(v) == 0);
+                       pure = (stof(value) == 0);
                        pure_available = true;
                }
-               else if(k == "S")
-                       freeslots = stof(v);
-               else if(k == "F")
-                       sflags = stoi(v);
-               else if(k == "M")
-                       modname = v;
+               else if(key == "S")
+                       freeslots = stof(value);
+               else if(key == "F")
+                       sflags = stoi(value);
+               else if(key == "M")
+                       modname = value;
        }
 
 #ifdef COMPAT_NO_MOD_IS_XONOTIC
@@ -901,6 +875,7 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
        if(modname != "newtoys")
                pure_available = false;
 
+       float theAlpha;
        if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
                theAlpha = SKINALPHA_SERVERLIST_FULL;
        else if(freeslots == 0)
@@ -910,18 +885,19 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
        else
                theAlpha = 1;
 
-       p = gethostcachenumber(SLIST_FIELD_PING, i);
+       float ping = gethostcachenumber(SLIST_FIELD_PING, i);
        const int PING_LOW = 75;
        const int PING_MED = 200;
        const int PING_HIGH = 500;
-       if(p < PING_LOW)
-               theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / PING_LOW);
-       else if(p < PING_MED)
-               theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - PING_LOW) / (PING_MED - PING_LOW));
-       else if(p < PING_HIGH)
+       vector theColor;
+       if(ping < PING_LOW)
+               theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (ping / PING_LOW);
+       else if(ping < PING_MED)
+               theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((ping - PING_LOW) / (PING_MED - PING_LOW));
+       else if(ping < PING_HIGH)
        {
                theColor = SKINCOLOR_SERVERLIST_HIGHPING;
-               theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - PING_MED) / (PING_HIGH - PING_MED));
+               theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((ping - PING_MED) / (PING_HIGH - PING_MED));
        }
        else
        {
@@ -937,7 +913,7 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
 
        s = gethostcachestring(SLIST_FIELD_CNAME, i);
 
-       isv4 = isv6 = false;
+       bool isv4 = false, isv6 = false;
        if(substring(s, 0, 1) == "[")
        {
                isv6 = true;
@@ -949,27 +925,27 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
                me.seenIPv4 += 1;
        }
 
-       q = stof(substring(crypto_getencryptlevel(s), 0, 1));
-       if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
+       int crypto = stof(substring(crypto_getencryptlevel(s), 0, 1));
+       if((crypto <= 0 && cvar("crypto_aeslevel") >= 3) || (crypto >= 3 && cvar("crypto_aeslevel") <= 0))
        {
                theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
                theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
        }
 
-       if(q == 1)
+       if(crypto == 1)
        {
                if(cvar("crypto_aeslevel") >= 2)
-                       q |= 4;
+                       crypto |= 4;
        }
-       if(q == 2)
+       if(crypto == 2)
        {
                if(cvar("crypto_aeslevel") >= 1)
-                       q |= 4;
+                       crypto |= 4;
        }
-       if(q == 3)
-               q = 5;
-       else if(q >= 3)
-               q -= 2;
+       if(crypto == 3)
+               crypto = 5;
+       else if(crypto >= 3)
+               crypto -= 2;
        // possible status:
        // 0: crypto off
        // 1: AES possible
@@ -1001,8 +977,8 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
        iconPos.x += iconSize.x;
 
        // AES
-       if(q > 0)
-               draw_Picture(iconPos, strcat("icon_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
+       if(crypto > 0)
+               draw_Picture(iconPos, strcat("icon_aeslevel", ftos(crypto)), iconSize, '1 1 1', 1);
 
        iconPos.x += iconSize.x;
 
@@ -1040,7 +1016,7 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
                string t = "";
                if(me.seenIPv4 && me.seenIPv6)
                        t = strcat(t, (isv6) ? "IPv6, " : "IPv4, ");
-               t = strcat(t, _("encryption:"), " ", (q ? sprintf(_("AES level %d"), q) : ZCTX(_("ENC^none"))), ", ");
+               t = strcat(t, _("encryption:"), " ", (crypto ? sprintf(_("AES level %d"), crypto) : ZCTX(_("ENC^none"))), ", ");
                t = strcat(t, sprintf(_("mod: %s"), ((modname == "xonotic") ? ZCTX(_("MOD^Default")) : original_modname)));
                if(pure_available)
                        t = strcat(t, sprintf(" (%s)", (pure) ? _("official settings") : _("modified settings")));
@@ -1053,7 +1029,7 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
        // --------------
 
        // ping
-       s = ftos(p);
+       s = ftos(ping);
        draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
 
        // server name
@@ -1140,8 +1116,7 @@ float XonoticServerList_getTotalHeight(entity me)
 int XonoticServerList_getItemAtPos(entity me, float pos)
 {
        pos = pos / me.itemHeight;
-       int i;
-       for (i = category_draw_count - 1; i >= 0; --i) {
+       for (int i = category_draw_count - 1; i >= 0; --i) {
                int itemidx = category_item[i];
                float itempos = i * me.categoriesHeight + category_item[i];
                if (pos >= itempos + me.categoriesHeight + 1)
@@ -1154,8 +1129,7 @@ int XonoticServerList_getItemAtPos(entity me, float pos)
 }
 float XonoticServerList_getItemStart(entity me, int item)
 {
-       int i;
-       for (i = category_draw_count - 1; i >= 0; --i) {
+       for (int i = category_draw_count - 1; i >= 0; --i) {
                int itemidx = category_item[i];
                float itempos = i * me.categoriesHeight + category_item[i];
                if (item >= itemidx + 1)
@@ -1168,8 +1142,7 @@ float XonoticServerList_getItemStart(entity me, int item)
 }
 float XonoticServerList_getItemHeight(entity me, int item)
 {
-       int i;
-       for (i = 0; i < category_draw_count; ++i) {
+       for (int i = 0; i < category_draw_count; ++i) {
                // Matches exactly the headings with increased height.
                if (item == category_item[i])
                        return me.itemHeight * (me.categoriesHeight + 1);
index 01b065df78b302d31d160590b7c76489ed19c189..8ad1856b07986ba5477b1f5a6b104e7ed486cab4 100644 (file)
@@ -71,7 +71,7 @@ ENDCLASS(XonoticServerList)
 entity makeXonoticServerList();
 
 void RegisterSLCategories();
-float CheckCategoryForEntry(float entry);
+float CategoryForEntry(float entry);
 void ServerList_Filter_Change(entity box, entity me);
 void ServerList_Categories_Click(entity box, entity me);
 void ServerList_ShowEmpty_Click(entity box, entity me);
@@ -127,8 +127,8 @@ float IsServerInList(string list, string srv);
 
 entity RetrieveCategoryEnt(float catnum);
 
-float CheckCategoryOverride(float cat);
-float m_gethostcachecategory(float entry) { return CheckCategoryOverride(CheckCategoryForEntry(entry)); }
+float CategoryOverride(float cat);
+float m_gethostcachecategory(float entry) { return CategoryOverride(CategoryForEntry(entry)); }
 
 
 // fields for category entities
index a126b9e5da2713f68fc1cf4f952950a035aadec8..5e9fdb03d96d9a0ab079810d52fe799fdbf41625 100644 (file)
@@ -127,6 +127,7 @@ void makeCallback(entity e, entity cbent, void(entity, entity) cbfunc)
 .bool disabled;
 void setDependent_Check(entity e)
 {
+       bool disabled_prev = e.disabled;
        float f;
        string s;
        if(e.func_setDependent)
@@ -165,6 +166,8 @@ void setDependent_Check(entity e)
                                e.disabled = (e.disabled + ((f >= e.cvar3Max_setDependent) && (f <= e.cvar3Min_setDependent)) > e.op_setDependent);
                }
        }
+       if (disabled_prev != e.disabled && e.loadCvars)
+               e.loadCvars(e);
 }
 void setDependent_Draw(entity e)
 {
index 6aa798afb9b8b823f6363a914cde396fb165d55f..79989cc176d1a3e70200cd3fe03f60da91458817 100644 (file)
@@ -159,6 +159,7 @@ bool autocvar_g_maplist_votable_suggestions;
 bool autocvar_g_maplist_votable_suggestions_override_mostrecent;
 float autocvar_g_maplist_votable_timeout;
 bool autocvar_g_maplist_ignore_sizes;
+bool autocvar_g_maplist_sizes_count_maxplayers = true;
 bool autocvar_g_maplist_sizes_count_bots = true;
 int autocvar_g_maxplayers;
 float autocvar_g_maxplayers_spectator_blocktime;
index 4d0d4cdff2ad2a03c954fb7e56ec3e30434f94ba..7b30b62dfabbd720111f6cafad9296c231ce7a66 100644 (file)
@@ -104,7 +104,8 @@ void bot_think(entity this)
 
        // clear buttons
        PHYS_INPUT_BUTTON_ATCK(this) = false;
-       PHYS_INPUT_BUTTON_JUMP(this) = false;
+       // keep jump button pressed for a short while, useful with ramp jumps
+       PHYS_INPUT_BUTTON_JUMP(this) = (!IS_DEAD(this) && time < this.bot_jump_time + 0.2);
        PHYS_INPUT_BUTTON_ATCK2(this) = false;
        PHYS_INPUT_BUTTON_ZOOM(this) = false;
        PHYS_INPUT_BUTTON_CROUCH(this) = false;
@@ -309,6 +310,10 @@ void bot_setnameandstuff(entity this)
 
 void bot_custom_weapon_priority_setup()
 {
+       static string bot_priority_far_prev;
+       static string bot_priority_mid_prev;
+       static string bot_priority_close_prev;
+       static string bot_priority_distances_prev;
        float tokens, i, w;
 
        bot_custom_weapon = false;
@@ -316,70 +321,50 @@ void bot_custom_weapon_priority_setup()
        if(     autocvar_bot_ai_custom_weapon_priority_far == "" ||
                autocvar_bot_ai_custom_weapon_priority_mid == "" ||
                autocvar_bot_ai_custom_weapon_priority_close == "" ||
-               autocvar_bot_ai_custom_weapon_priority_distances == ""
+               autocvar_bot_ai_custom_weapon_priority_distances == ""
        )
                return;
 
-       // Parse distances
-       tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
-
-       if (tokens!=2)
-               return;
-
-       bot_distance_far = stof(argv(0));
-       bot_distance_close = stof(argv(1));
-
-       if(bot_distance_far < bot_distance_close){
-               bot_distance_far = stof(argv(1));
-               bot_distance_close = stof(argv(0));
-       }
+       if (bot_priority_distances_prev != autocvar_bot_ai_custom_weapon_priority_distances)
+       {
+               strcpy(bot_priority_distances_prev, autocvar_bot_ai_custom_weapon_priority_distances);
+               tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
 
-       // Initialize list of weapons
-       bot_weapons_far[0] = -1;
-       bot_weapons_mid[0] = -1;
-       bot_weapons_close[0] = -1;
+               if (tokens!=2)
+                       return;
 
-       // Parse far distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
+               bot_distance_far = stof(argv(0));
+               bot_distance_close = stof(argv(1));
 
-       int c = 0;
-       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_far[c] = w;
-                       ++c;
+               if(bot_distance_far < bot_distance_close){
+                       bot_distance_far = stof(argv(1));
+                       bot_distance_close = stof(argv(0));
                }
        }
-       if(c < Weapons_COUNT)
-               bot_weapons_far[c] = -1;
 
-       // Parse mid distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_mid)," ");
-
-       c = 0;
-       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_mid[c] = w;
-                       ++c;
-               }
-       }
-       if(c < Weapons_COUNT)
-               bot_weapons_mid[c] = -1;
+       int c;
+
+       #define PARSE_WEAPON_PRIORITIES(dist) MACRO_BEGIN \
+               if (bot_priority_##dist##_prev != autocvar_bot_ai_custom_weapon_priority_##dist) { \
+                       strcpy(bot_priority_##dist##_prev, autocvar_bot_ai_custom_weapon_priority_##dist); \
+                       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_##dist)," "); \
+                       bot_weapons_##dist[0] = -1; \
+                       c = 0; \
+                       for(i = 0; i < tokens && c < Weapons_COUNT; ++i) { \
+                               w = stof(argv(i)); \
+                               if (w >= WEP_FIRST && w <= WEP_LAST) { \
+                                       bot_weapons_##dist[c] = w; \
+                                       ++c; \
+                               } \
+                       } \
+                       if (c < Weapons_COUNT) \
+                               bot_weapons_##dist[c] = -1; \
+               } \
+       MACRO_END
 
-       // Parse close distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_close)," ");
-
-       c = 0;
-       for(i=0; i < tokens && i < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_close[c] = w;
-                       ++c;
-               }
-       }
-       if(c < Weapons_COUNT)
-               bot_weapons_close[c] = -1;
+       PARSE_WEAPON_PRIORITIES(far);
+       PARSE_WEAPON_PRIORITIES(mid);
+       PARSE_WEAPON_PRIORITIES(close);
 
        bot_custom_weapon = true;
 }
@@ -846,10 +831,6 @@ void bot_serverframe()
        if (autocvar_g_waypointeditor_auto)
                botframe_autowaypoints();
 
-       if(time > bot_cvar_nextthink)
-       {
-               if(currentbots>0)
-                       bot_custom_weapon_priority_setup();
-               bot_cvar_nextthink = time + 5;
-       }
+       if (currentbots > 0)
+               bot_custom_weapon_priority_setup();
 }
index 98b2ae3df78fb4d970ffd60528d65339b834f687..88dba449d5fe245d9a63b05c019f9c1ffd1009ec 100644 (file)
@@ -65,6 +65,7 @@ entity bot_list;
 .bool bot_pickup_respawning;
 .float bot_canfire;
 .float bot_strategytime;
+.float bot_jump_time;
 
 .float bot_forced_team;
 .float bot_config_loaded;
@@ -75,7 +76,6 @@ entity bot_strategytoken;
 float botframe_spawnedwaypoints;
 float botframe_nextthink;
 float botframe_nextdangertime;
-float bot_cvar_nextthink;
 
 int _content_type;
 #define IN_LAVA(pos) (_content_type = pointcontents(pos), (_content_type == CONTENT_LAVA || _content_type == CONTENT_SLIME))
index 55bc9c8f3f1ce218751bf1c57fdf5e6c3b6e86bc..269cd68044fe5902009a8fe610b3e67da8472985 100644 (file)
@@ -19,10 +19,12 @@ float autocvar_bot_ai_aimskill_order_mix_3th;
 float autocvar_bot_ai_aimskill_order_mix_4th;
 float autocvar_bot_ai_aimskill_order_mix_5th;
 float autocvar_bot_ai_aimskill_think;
-float autocvar_bot_ai_bunnyhop_firstjumpdelay;
 float autocvar_bot_ai_bunnyhop_skilloffset;
-float autocvar_bot_ai_bunnyhop_startdistance;
-float autocvar_bot_ai_bunnyhop_stopdistance;
+float autocvar_bot_ai_bunnyhop_dir_deviation_max;
+float autocvar_bot_ai_bunnyhop_downward_pitch_max;
+float autocvar_bot_ai_bunnyhop_turn_angle_min;
+float autocvar_bot_ai_bunnyhop_turn_angle_max;
+float autocvar_bot_ai_bunnyhop_turn_angle_reduction;
 float autocvar_bot_ai_chooseweaponinterval;
 string autocvar_bot_ai_custom_weapon_priority_close;
 string autocvar_bot_ai_custom_weapon_priority_distances;
@@ -31,6 +33,7 @@ string autocvar_bot_ai_custom_weapon_priority_mid;
 float autocvar_bot_ai_dangerdetectioninterval;
 float autocvar_bot_ai_dangerdetectionupdates;
 float autocvar_bot_ai_enemydetectioninterval;
+float autocvar_bot_ai_enemydetectioninterval_stickingtoenemy;
 float autocvar_bot_ai_enemydetectionradius;
 float autocvar_bot_ai_friends_aware_pickup_radius;
 float autocvar_bot_ai_ignoregoal_timeout;
index 477d1ec464c9c4af95f10f6dd3d2b260bd5bc6e3..6515cc44efad6bdcbb63a6f11c55f16586ed7bab 100644 (file)
@@ -47,8 +47,12 @@ void havocbot_ai(entity this)
                }
                else
                {
-                       if (!this.jumppadcount && !STAT(FROZEN, this))
+                       if (!this.jumppadcount && !STAT(FROZEN, this)
+                               && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP) && !IS_ONGROUND(this)))
+                       {
+                               // find a new goal
                                this.havocbot_role(this); // little too far down the rabbit hole
+                       }
                }
 
                // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
@@ -100,6 +104,8 @@ void havocbot_ai(entity this)
        {
                if (this.goalcurrent)
                        navigation_clearroute(this);
+               this.enemy = NULL;
+               this.bot_aimtarg = NULL;
                return;
        }
 
@@ -198,6 +204,63 @@ void havocbot_ai(entity this)
        }
 }
 
+void havocbot_bunnyhop(entity this, vector dir)
+{
+       bool can_run = false;
+       if (!(this.aistatus & AI_STATUS_ATTACKING) && this.goalcurrent && !IS_PLAYER(this.goalcurrent)
+               && vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed) && !(this.aistatus & AI_STATUS_DANGER_AHEAD)
+               && this.waterlevel <= WATERLEVEL_WETFEET && !IS_DUCKED(this)
+               && IS_ONGROUND(this) && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
+       {
+               vector vel_angles = vectoangles(this.velocity);
+               vector deviation = vel_angles - vectoangles(dir);
+               while (deviation.y < -180) deviation.y = deviation.y + 360;
+               while (deviation.y > 180) deviation.y = deviation.y - 360;
+               if (fabs(deviation.y) < autocvar_bot_ai_bunnyhop_dir_deviation_max)
+               {
+                       vector gco = get_closer_dest(this.goalcurrent, this.origin);
+                       float vel = vlen(vec2(this.velocity));
+
+                       // with the current physics, jump distance grows linearly with the speed
+                       float jump_distance = 52.661 + 0.606 * vel;
+                       jump_distance += this.origin.z - gco.z; // roughly take into account vertical distance too
+                       if (vdist(vec2(gco - this.origin), >, max(0, jump_distance)))
+                               can_run = true;
+                       else if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP)
+                               && !(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+                               && this.goalstack01 && !wasfreed(this.goalstack01) && !(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP)
+                               && vdist(vec2(gco - this.goalstack01.origin), >, 70))
+                       {
+                               vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+                               vector ang = vectoangles(gco - this.origin);
+                               deviation = vectoangles(gno - gco) - vel_angles;
+                               while (deviation.y < -180) deviation.y = deviation.y + 360;
+                               while (deviation.y > 180) deviation.y = deviation.y - 360;
+
+                               float max_turn_angle = autocvar_bot_ai_bunnyhop_turn_angle_max;
+                               max_turn_angle -= autocvar_bot_ai_bunnyhop_turn_angle_reduction * ((vel - autocvar_sv_maxspeed) / autocvar_sv_maxspeed);
+                               if ((ang.x < 90 || ang.x > 360 - autocvar_bot_ai_bunnyhop_downward_pitch_max)
+                                       && fabs(deviation.y) < max(autocvar_bot_ai_bunnyhop_turn_angle_min, max_turn_angle))
+                               {
+                                       can_run = true;
+                               }
+                       }
+               }
+       }
+
+       if (can_run)
+       {
+               PHYS_INPUT_BUTTON_JUMP(this) = true;
+               this.bot_jump_time = time;
+               this.aistatus |= AI_STATUS_RUNNING;
+       }
+       else
+       {
+               if (IS_ONGROUND(this) || this.waterlevel > WATERLEVEL_WETFEET)
+                       this.aistatus &= ~AI_STATUS_RUNNING;
+       }
+}
+
 void havocbot_keyboard_movement(entity this, vector destorg)
 {
        if(time <= this.havocbot_keyboardtime)
@@ -268,114 +331,6 @@ void havocbot_keyboard_movement(entity this, vector destorg)
        CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
 }
 
-void havocbot_bunnyhop(entity this, vector dir)
-{
-       // Don't jump when attacking
-       if(this.aistatus & AI_STATUS_ATTACKING)
-               return;
-
-       if (!this.goalcurrent || IS_PLAYER(this.goalcurrent))
-               return;
-
-       if((this.aistatus & AI_STATUS_RUNNING) && vdist(this.velocity, <, autocvar_sv_maxspeed * 0.75)
-               || (this.aistatus & AI_STATUS_DANGER_AHEAD))
-       {
-               this.aistatus &= ~AI_STATUS_RUNNING;
-               PHYS_INPUT_BUTTON_JUMP(this) = false;
-               this.bot_canruntogoal = 0;
-               this.bot_timelastseengoal = 0;
-               return;
-       }
-
-       if(this.waterlevel > WATERLEVEL_WETFEET || IS_DUCKED(this))
-       {
-               this.aistatus &= ~AI_STATUS_RUNNING;
-               return;
-       }
-
-       if(this.bot_lastseengoal != this.goalcurrent && !(this.aistatus & AI_STATUS_RUNNING))
-       {
-               this.bot_canruntogoal = 0;
-               this.bot_timelastseengoal = 0;
-       }
-
-       // Run only to visible goals
-       if(IS_ONGROUND(this))
-       if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
-       if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
-       {
-               this.bot_lastseengoal = this.goalcurrent;
-
-               // seen it before
-               if(this.bot_timelastseengoal)
-               {
-                       vector gco = get_closer_dest(this.goalcurrent, this.origin);
-                       // for a period of time
-                       if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
-                       {
-                               bool checkdistance = true;
-
-                               // don't run if it is too close
-                               if(this.bot_canruntogoal==0)
-                               {
-                                       if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_startdistance))
-                                               this.bot_canruntogoal = 1;
-                                       else
-                                               this.bot_canruntogoal = -1;
-                               }
-
-                               if(this.bot_canruntogoal != 1)
-                                       return;
-
-                               if(this.aistatus & AI_STATUS_ROAMING)
-                               if(this.goalcurrent.classname == "waypoint")
-                               if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
-                               if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
-                               if (this.goalstack01 && !wasfreed(this.goalstack01))
-                               if (!(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP))
-                               {
-                                       vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
-                                       vector deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
-                                       while (deviation.y < -180) deviation.y = deviation.y + 360;
-                                       while (deviation.y > 180) deviation.y = deviation.y - 360;
-
-                                       if(fabs(deviation.y) < 20)
-                                       if(vlen2(this.origin - gco) < vlen2(this.origin - gno))
-                                       if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
-                                       {
-                                               if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
-                                               if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
-                                               {
-                                                       checkdistance = false;
-                                               }
-                                       }
-                               }
-
-                               if(checkdistance)
-                               {
-                                       this.aistatus &= ~AI_STATUS_RUNNING;
-                                       // increase stop distance in case the goal is on a slope or a lower platform
-                                       if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_stopdistance + (this.origin.z - gco.z)))
-                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
-                               }
-                               else
-                               {
-                                       this.aistatus |= AI_STATUS_RUNNING;
-                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
-                               }
-                       }
-               }
-               else
-               {
-                       this.bot_timelastseengoal = time;
-               }
-       }
-       else
-       {
-               this.bot_timelastseengoal = 0;
-       }
-}
-
 // return true when bot isn't getting closer to the current goal
 bool havocbot_checkgoaldistance(entity this, vector gco)
 {
@@ -436,8 +391,6 @@ void havocbot_movetogoal(entity this)
        vector diff;
        vector dir;
        vector flatdir;
-       vector evadeobstacle;
-       vector evadelava;
        float dodge_enemy_factor = 1;
        float maxspeed;
        //float dist;
@@ -608,12 +561,31 @@ void havocbot_movetogoal(entity this)
        if (skill > 6 && !(IS_ONGROUND(this)))
        {
                #define ROCKETJUMP_DAMAGE() WEP_CVAR(devastator, damage) * 0.8 \
-                       * ((this.strength_finished > time) ? autocvar_g_balance_powerup_strength_selfdamage : 1) \
-                       * ((this.invincible_finished > time) ? autocvar_g_balance_powerup_invincible_takedamage : 1)
+                       * ((STAT(STRENGTH_FINISHED, this) > time) ? autocvar_g_balance_powerup_strength_selfdamage : 1) \
+                       * ((STAT(INVINCIBLE_FINISHED, this) > time) ? autocvar_g_balance_powerup_invincible_takedamage : 1)
+
+               // save some CPU cycles by checking trigger_hurt after checking
+               // that something can be done to evade it (cheaper checks)
+               int action_for_trigger_hurt = 0;
+               if (this.items & IT_JETPACK)
+                       action_for_trigger_hurt = 1;
+               else if (!this.jumppadcount && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
+                       && !(this.goalcurrent_prev && this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)
+                       && GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR) > ROCKETJUMP_DAMAGE())
+               {
+                       action_for_trigger_hurt = 2;
+               }
+               else if (!this.goalcurrent)
+                       action_for_trigger_hurt = 3;
 
-               tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
-               if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos ))
-               if(this.items & IT_JETPACK)
+               if (action_for_trigger_hurt)
+               {
+                       tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
+                       if(!tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos))
+                               action_for_trigger_hurt = 0;
+               }
+
+               if(action_for_trigger_hurt == 1) // jetpack
                {
                        tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 65536', MOVE_NOMONSTERS, this);
                        if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos + '0 0 1' ))
@@ -651,9 +623,7 @@ void havocbot_movetogoal(entity this)
 
                        return;
                }
-               else if(!this.jumppadcount && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
-                       && !(this.goalcurrent_prev && this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)
-                       && GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR) > ROCKETJUMP_DAMAGE())
+               else if(action_for_trigger_hurt == 2) // rocketjump
                {
                        if(this.velocity.z < 0)
                        {
@@ -687,11 +657,10 @@ void havocbot_movetogoal(entity this)
                                }
                        }
                }
-               else
+               else if(action_for_trigger_hurt == 3) // no goal
                {
                        // If there is no goal try to move forward
-                       if(this.goalcurrent==NULL)
-                               CS(this).movement_x = maxspeed;
+                       CS(this).movement_x = maxspeed;
                }
        }
 
@@ -703,8 +672,6 @@ void havocbot_movetogoal(entity this)
                        dir.z = 1;
                else if(this.velocity.z >= 0 && !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER))
                        PHYS_INPUT_BUTTON_JUMP(this) = true;
-               else
-                       PHYS_INPUT_BUTTON_JUMP(this) = false;
                makevectors(this.v_angle.y * '0 1 0');
                vector v = dir * maxspeed;
                CS(this).movement.x = v * v_forward;
@@ -910,12 +877,13 @@ void havocbot_movetogoal(entity this)
                dir = normalize(diff);
        flatdir = (diff.z == 0) ? dir : normalize(vec2(diff));
 
+       bool danger_detected = false;
+       vector do_break = '0 0 0';
+
        //if (this.bot_dodgevector_time < time)
        {
                //this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
                //this.bot_dodgevector_jumpbutton = 1;
-               evadeobstacle = '0 0 0';
-               evadelava = '0 0 0';
 
                this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
                makevectors(this.v_angle.y * '0 1 0');
@@ -938,7 +906,6 @@ void havocbot_movetogoal(entity this)
                                }
                                else
                                {
-                                       PHYS_INPUT_BUTTON_JUMP(this) = false;
                                        if (destorg.z > this.origin.z)
                                                dir = flatdir;
                                }
@@ -982,15 +949,14 @@ void havocbot_movetogoal(entity this)
                                )
                                {
                                        PHYS_INPUT_BUTTON_JUMP(this) = true;
-                                       // avoid changing route while bot is jumping a gap
-                                       navigation_goalrating_timeout_extend_if_needed(this, 1.5);
+                                       this.bot_jump_time = time;
                                }
                        }
                        else if (!this.goalstack01 || (this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER)))
                        {
                                if (vlen2(flat_diff) < vlen2(offset))
                                {
-                                       if (this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP && this.goalstack01)
+                                       if ((this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP) && this.goalstack01)
                                        {
                                                // oblique warpzones need a jump otherwise bots gets stuck
                                                PHYS_INPUT_BUTTON_JUMP(this) = true;
@@ -1059,13 +1025,19 @@ void havocbot_movetogoal(entity this)
                                                vector jump_height = (IS_ONGROUND(this)) ? stepheightvec + jumpheight_vec : jumpstepheightvec;
                                                tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
                                                if (trace_fraction > s)
+                                               {
                                                        PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                                       this.bot_jump_time = time;
+                                               }
                                                else
                                                {
                                                        jump_height = stepheightvec + jumpheight_vec / 2;
                                                        tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
                                                        if (trace_fraction > s)
+                                                       {
                                                                PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                                               this.bot_jump_time = time;
+                                                       }
                                                }
                                        }
                                }
@@ -1099,15 +1071,15 @@ void havocbot_movetogoal(entity this)
                                this.goalcurrent_distance_time = -time; // mark second try
                        }
 
-                       // Check for water/slime/lava and dangerous edges
-                       // (only when the bot is on the ground or jumping intentionally)
-
                        if (skill + this.bot_moveskill <= 3 && time > this.bot_stop_moving_timeout
                                && current_speed > maxspeed * 0.9 && fabs(deviation.y) > 70)
                        {
                                this.bot_stop_moving_timeout = time + 0.4 + random() * 0.2;
                        }
 
+                       // Check for water/slime/lava and dangerous edges
+                       // (only when the bot is on the ground or jumping intentionally)
+
                        offset = (vdist(this.velocity, >, 32) ? this.velocity * 0.2 : flatdir * 32);
                        vector dst_ahead = this.origin + this.view_ofs + offset;
                        vector dst_down = dst_ahead - '0 0 3000';
@@ -1126,37 +1098,42 @@ void havocbot_movetogoal(entity this)
                                //te_lightning2(NULL, dst_ahead, trace_endpos); // Draw "downwards" look
                                if(trace_endpos.z < this.origin.z + this.mins.z)
                                {
-                                       s = pointcontents(trace_endpos + '0 0 1');
-                                       if (s != CONTENT_SOLID)
-                                       if (s == CONTENT_LAVA || s == CONTENT_SLIME)
-                                               evadelava = normalize(this.velocity) * -1;
-                                       else if (s == CONTENT_SKY)
-                                               evadeobstacle = normalize(this.velocity) * -1;
-                                       else if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+                                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+                                               danger_detected = true;
+                                       else if (trace_endpos.z < min(this.origin.z + this.mins.z, this.goalcurrent.origin.z) - 100)
+                                               danger_detected = true;
+                                       else
                                        {
-                                               // the traceline check isn't enough but is good as optimization,
-                                               // when not true (most of the time) this tracebox call is avoided
-                                               tracebox(dst_ahead, this.mins, this.maxs, dst_down, true, this);
-                                               if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+                                               s = pointcontents(trace_endpos + '0 0 1');
+                                               if (s != CONTENT_SOLID)
                                                {
-                                                       if (destorg.z > this.origin.z + jumpstepheightvec.z)
+                                                       if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+                                                               danger_detected = true;
+                                                       else if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
                                                        {
-                                                               // the goal is probably on an upper platform, assume bot can't get there
-                                                               unreachable = true;
+                                                               // the traceline check isn't enough but is good as optimization,
+                                                               // when not true (most of the time) this tracebox call is avoided
+                                                               tracebox(dst_ahead, this.mins, this.maxs, dst_down, true, this);
+                                                               if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+                                                               {
+                                                                       if (destorg.z > this.origin.z + jumpstepheightvec.z)
+                                                                       {
+                                                                               // the goal is probably on an upper platform, assume bot can't get there
+                                                                               unreachable = true;
+                                                                       }
+                                                                       else
+                                                                               danger_detected = true;
+                                                               }
                                                        }
-                                                       else
-                                                               evadelava = normalize(this.velocity) * -1;
                                                }
                                        }
                                }
                        }
 
                        dir = flatdir;
-                       evadeobstacle.z = 0;
-                       evadelava.z = 0;
                        makevectors(this.v_angle.y * '0 1 0');
 
-                       if(evadeobstacle || evadelava || (s == CONTENT_WATER))
+                       if (danger_detected || (s == CONTENT_WATER))
                        {
                                this.aistatus |= AI_STATUS_DANGER_AHEAD;
                                if(IS_PLAYER(this.goalcurrent))
@@ -1171,7 +1148,7 @@ void havocbot_movetogoal(entity this)
                                // tracebox wouldn't work when bot is still on the ledge
                                traceline(this.origin, this.origin - '0 0 200', true, this);
                                if (this.origin.z - trace_endpos.z > 120)
-                                       evadeobstacle = normalize(this.velocity) * -1;
+                                       do_break = normalize(this.velocity) * -1;
                        }
 
                        if(unreachable)
@@ -1186,8 +1163,6 @@ void havocbot_movetogoal(entity this)
                dodge = havocbot_dodge(this);
                if (dodge)
                        dodge *= bound(0, 0.5 + (skill + this.bot_dodgeskill) * 0.1, 1);
-               dodge += evadeobstacle + evadelava;
-               evadelava = evadelava * bound(1,3-(skill+this.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it
                if (this.enemy)
                {
                        traceline(this.origin, (this.enemy.absmin + this.enemy.absmax) * 0.5, true, NULL);
@@ -1240,10 +1215,27 @@ void havocbot_movetogoal(entity this)
                        bot_aimdir(this, dir, 0);
        }
 
+       vector evadedanger = '0 0 0';
        if (!ladder_zdir)
        {
                dir *= dodge_enemy_factor;
-               dir = normalize(dir + dodge);
+               if (danger_detected && vdist(this.velocity, >, maxspeed * 0.8) && this.goalcurrent_prev
+                       && this.goalcurrent.classname == "waypoint")
+               {
+                       vector p = this.origin + this.velocity * 0.2;
+                       vector evadedanger = point_line_vec(p, vec2(this.goalcurrent_prev.origin) + eZ * p.z,
+                               vec2(destorg - this.goalcurrent_prev.origin));
+                       if (vdist(evadedanger, >, 20))
+                       {
+                               if (vdist(evadedanger, >, 40))
+                                       do_break = normalize(this.velocity) * -1;
+                               evadedanger = normalize(evadedanger);
+                               evadedanger *= bound(1, 3 - (skill + this.bot_dodgeskill), 3); // Noobs fear dangers a lot and take more distance from them
+                       }
+                       else
+                               evadedanger = '0 0 0';
+               }
+               dir = normalize(dir + dodge + do_break + evadedanger);
        }
 
        makevectors(this.v_angle);
@@ -1259,7 +1251,7 @@ void havocbot_movetogoal(entity this)
                havocbot_keyboard_movement(this, destorg);
 
        // Bunnyhop!
-       if (!bunnyhop_forbidden && skill + this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
+       if (!bunnyhop_forbidden && !evadedanger && !do_break && skill + this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
                havocbot_bunnyhop(this, dir);
 
        if (dir * v_up >= autocvar_sv_jumpvelocity * 0.5 && IS_ONGROUND(this))
@@ -1300,6 +1292,7 @@ void havocbot_chooseenemy(entity this)
                this.enemy = NULL;
                return;
        }
+
        if (this.enemy)
        {
                if (!bot_shouldattack(this, this.enemy))
@@ -1308,26 +1301,21 @@ void havocbot_chooseenemy(entity this)
                        this.enemy = NULL;
                        this.havocbot_chooseenemy_finished = time;
                }
-               else if (this.havocbot_stickenemy)
+               else if (this.havocbot_stickenemy_time && time < this.havocbot_stickenemy_time)
                {
                        // tracking last chosen enemy
-                       // if enemy is visible
-                       // and not really really far away
-                       // and we're not severely injured
-                       // then keep tracking for a half second into the future
-                       traceline(this.origin+this.view_ofs, ( this.enemy.absmin + this.enemy.absmax ) * 0.5,false,NULL);
+                       vector targ_pos = (this.enemy.absmin + this.enemy.absmax) * 0.5;
+                       traceline(this.origin + this.view_ofs, targ_pos, false, NULL);
                        if (trace_ent == this.enemy || trace_fraction == 1)
-                       if (vdist(((this.enemy.absmin + this.enemy.absmax) * 0.5) - this.origin, <, 1000))
-                       if (GetResource(this, RES_HEALTH) > 30)
+                       if (vdist(targ_pos - this.origin, <, 1000))
                        {
                                // remain tracking him for a shot while (case he went after a small corner or pilar
                                this.havocbot_chooseenemy_finished = time + 0.5;
                                return;
                        }
-                       // enemy isn't visible, or is far away, or we're injured severely
-                       // so stop preferring this enemy
-                       // (it will still take a half second until a new one is chosen)
-                       this.havocbot_stickenemy = 0;
+
+                       // stop preferring this enemy
+                       this.havocbot_stickenemy_time = 0;
                }
        }
        if (time < this.havocbot_chooseenemy_finished)
@@ -1335,7 +1323,7 @@ void havocbot_chooseenemy(entity this)
        this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
        vector eye = this.origin + this.view_ofs;
        entity best = NULL;
-       float bestrating = 100000000;
+       float bestrating = autocvar_bot_ai_enemydetectionradius ** 2;
 
        // Backup hit flags
        int hf = this.dphitcontentsmask;
@@ -1366,9 +1354,7 @@ LABEL(scan_targets)
 
                        vector v = (it.absmin + it.absmax) * 0.5;
                        float rating = vlen2(v - eye);
-                       if (vdist(v - eye, <, autocvar_bot_ai_enemydetectionradius))
-                       if (bestrating > rating)
-                       if (bot_shouldattack(this, it))
+                       if (rating < bestrating && bot_shouldattack(this, it))
                        {
                                traceline(eye, v, true, this);
                                if (trace_ent == it || trace_fraction >= 1)
@@ -1383,7 +1369,7 @@ LABEL(scan_targets)
                {
                        scan_secondary_targets = true;
                        // restart the loop
-                       bestrating = 100000000;
+                       bestrating = autocvar_bot_ai_enemydetectionradius ** 2;
                        goto scan_targets;
                }
 
@@ -1404,9 +1390,9 @@ LABEL(scan_targets)
        this.dphitcontentsmask = hf;
 
        this.enemy = best;
-       this.havocbot_stickenemy = true;
+       this.havocbot_stickenemy_time = time + autocvar_bot_ai_enemydetectioninterval_stickingtoenemy;
        if(best && best.classname == "misc_breakablemodel")
-               this.havocbot_stickenemy = false;
+               this.havocbot_stickenemy_time = 0;
 }
 
 float havocbot_chooseweapon_checkreload(entity this, .entity weaponentity, int new_weapon)
index d1a36a117260027569b229cb291cc78e2cd0a70a..02c0f3e7d76b3d8912afcea77f8f0ea5fb779df1 100644 (file)
 
 .float havocbot_keyboardtime;
 .float havocbot_ducktime;
-.float bot_timelastseengoal;
-.float bot_canruntogoal;
 .float bot_chooseweapontime;
 .float rocketjumptime;
 .float nextaim;
 .float havocbot_personal_waypoint_searchtime;
 .float havocbot_personal_waypoint_failcounter;
 .float havocbot_chooseenemy_finished;
-.float havocbot_stickenemy;
+.float havocbot_stickenemy_time;
 .float havocbot_role_timeout;
 
 .float bot_stop_moving_timeout;
index 84c597329ea5fda0eb0930dfec079be15e7edb22..d078cae8604903d461bf824bb3a8b4283f0b7755 100644 (file)
@@ -200,10 +200,10 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
                t = bound(0, 1 + t, 3);
                if (skill > 3)
                {
-                       if (time < this.strength_finished - 1) t += 0.5;
-                       if (time < it.strength_finished - 1) t -= 0.5;
-                       if (time < this.invincible_finished - 1) t += 0.2;
-                       if (time < it.invincible_finished - 1) t -= 0.4;
+                       if (time < STAT(STRENGTH_FINISHED, this) - 1) t += 0.5;
+                       if (time < STAT(STRENGTH_FINISHED, it) - 1) t -= 0.5;
+                       if (time < STAT(INVINCIBLE_FINISHED, this) - 1) t += 0.2;
+                       if (time < STAT(INVINCIBLE_FINISHED, it) - 1) t -= 0.4;
                }
                t += max(0, 8 - skill) * 0.05; // less skilled bots attack more mindlessly
                ratingscale *= t;
index 5457211d84d2305bfa70ba1cd74a694a61239fbe..ebc18a6875353a2306ea07c6304d989860b76cac 100644 (file)
@@ -47,6 +47,7 @@ bool navigation_goalrating_timeout(entity this)
        return this.bot_strategytime < time;
 }
 
+ERASEABLE
 void navigation_goalrating_timeout_extend_if_needed(entity this, float seconds)
 {
        this.bot_strategytime = max(this.bot_strategytime, time + seconds);
@@ -943,10 +944,7 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
                        if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
                        {
                                if(walkfromwp && !ent.navigation_dynamicgoal)
-                               {
                                        waypoint_clearlinks(ent); // initialize wpXXmincost fields
-                                       navigation_item_addlink(it, ent);
-                               }
                                return it;
                        }
                });
@@ -965,24 +963,6 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
                org.z = ent.origin.z + ent.mins.z - PL_MIN_CONST.z; // player height
        }
 
-       if(!autocvar_g_waypointeditor && walkfromwp && !ent.navigation_dynamicgoal)
-       {
-               waypoint_clearlinks(ent); // initialize wpXXmincost fields
-               IL_EACH(g_waypoints, it != ent,
-               {
-                       if (walkfromwp && (it.wpflags & WPFLAGMASK_NORELINK))
-                               continue;
-
-                       set_tracewalk_dest(ent, it.origin, false);
-                       if (vdist(tracewalk_dest - it.origin, <, 1050)
-                               && tracewalk(ent, it.origin, PL_MIN_CONST, PL_MAX_CONST,
-                               tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
-                       {
-                               navigation_item_addlink(it, ent);
-                       }
-               });
-       }
-
        // box check failed, try walk
        IL_EACH(g_waypoints, it != ent,
        {
@@ -1507,7 +1487,7 @@ bool navigation_routetogoal(entity this, entity e, vector startposition)
        if(e == NULL)
                return false;
 
-       if(nearest_wp && nearest_wp.enemy)
+       if(nearest_wp && nearest_wp.enemy && !(nearest_wp.enemy.wpflags & WPFLAGMASK_NORELINK))
        {
                // often path can be optimized by not adding the nearest waypoint
                if (this.goalentity.navigation_dynamicgoal || autocvar_g_waypointeditor)
@@ -1529,8 +1509,35 @@ bool navigation_routetogoal(entity this, entity e, vector startposition)
                                }
                        }
                }
-               else if(navigation_item_islinked(nearest_wp.enemy, this.goalentity))
-                       e = nearest_wp.enemy;
+               else
+               {
+                       // NOTE unlike waypoints, items hold incoming links
+                       navigation_item_initlinks_ifneeded(this.goalentity);
+                       int link_num = navigation_item_getlinknum(this.goalentity, nearest_wp.enemy);
+                       if (link_num >= 0)
+                       {
+                               if (navigation_item_iswalkablelink(this.goalentity, link_num))
+                                       e = nearest_wp.enemy;
+                       }
+                       else // untested link
+                       {
+                               entity wp = nearest_wp.enemy;
+                               entity goal = this.goalentity;
+                               bool walkable = false;
+                               if (checkpvs(wp.origin, goal))
+                               {
+                                       set_tracewalk_dest(goal, wp.origin, false);
+                                       if (vdist(tracewalk_dest - wp.origin, <, 1050)
+                                               && tracewalk(goal, wp.origin, PL_MIN_CONST, PL_MAX_CONST,
+                                               tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+                                       {
+                                               walkable = true;
+                                               e = nearest_wp.enemy;
+                                       }
+                               }
+                               navigation_item_add_link(wp, goal, walkable);
+                       }
+               }
        }
 
        for (;;)
@@ -1647,7 +1654,7 @@ int navigation_poptouchedgoals(entity this)
                if(this.lastteleporttime > 0 && TELEPORT_USED(this, this.goalcurrent))
                {
                        if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-                       if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+                       if((this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) && this.goalcurrent.owner==this)
                        {
                                this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
                                this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
@@ -1689,7 +1696,7 @@ int navigation_poptouchedgoals(entity this)
                if (tele_ent && TELEPORT_USED(this, tele_ent))
                {
                        if (this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-                       if (tele_ent.wpflags & WAYPOINTFLAG_PERSONAL && tele_ent.owner == this)
+                       if ((tele_ent.wpflags & WAYPOINTFLAG_PERSONAL) && tele_ent.owner == this)
                        {
                                this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
                                this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
@@ -1710,18 +1717,23 @@ int navigation_poptouchedgoals(entity this)
        }
 
        // Loose goal touching check when running
-       if(this.aistatus & AI_STATUS_RUNNING)
-       if(this.goalcurrent.classname=="waypoint")
-       if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running
-       {
-               if(vdist(this.origin - this.goalcurrent.origin, <, 150))
+       // check goalstack01 to make sure waypoint isn't the final goal
+       if((this.aistatus & AI_STATUS_RUNNING) && this.goalcurrent.classname == "waypoint" && !(this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP)
+               && this.goalstack01 && !wasfreed(this.goalstack01) && vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
+       {
+               vector gco = this.goalcurrent.origin;
+               float min_dist = BOT_BUNNYHOP_WP_DETECTION_RANGE;
+               // also detect waypoints when bot is way above them but with a narrower horizontal range
+               // so to increase chances bot ends up in the standard range (optimizes nearest waypoint finding)
+               if(vdist(this.origin - gco, <, min_dist)
+                       || (vdist(vec2(this.origin - gco), <, min_dist * 0.5) && vdist(this.origin - eZ * 1.5 * min_dist - gco, <, min_dist)))
                {
                        traceline(this.origin + this.view_ofs , this.goalcurrent.origin, true, NULL);
                        if(trace_fraction==1)
                        {
                                // Detect personal waypoints
                                if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-                               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+                               if((this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) && this.goalcurrent.owner==this)
                                {
                                        this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
                                        this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
@@ -1742,7 +1754,7 @@ int navigation_poptouchedgoals(entity this)
                if(this.goalcurrent.classname == "waypoint" && !this.goalcurrent.wpisbox)
                {
                        gc_min = this.goalcurrent.origin - '1 1 1' * 12;
-                       gc_max = this.goalcurrent.origin + '1 1 1' * 12;
+                       gc_max = this.goalcurrent.origin + '1 1 1' * 12 + eZ * (jumpheight_vec.z + STAT(PL_MIN, this).z);
                }
                if (time < this.ladder_time)
                {
@@ -1757,7 +1769,7 @@ int navigation_poptouchedgoals(entity this)
 
                // Detect personal waypoints
                if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+               if((this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) && this.goalcurrent.owner==this)
                {
                        this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
                        this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
@@ -1778,7 +1790,8 @@ entity navigation_get_really_close_waypoint(entity this)
                wp = this.goalcurrent_prev;
        if(!wp)
                return NULL;
-       if(wp != this.goalcurrent_prev && vdist(wp.origin - this.origin, >, 50))
+       float min_dist = ((this.aistatus & AI_STATUS_RUNNING) ? BOT_BUNNYHOP_WP_DETECTION_RANGE : 50);
+       if(wp != this.goalcurrent_prev && vdist(wp.origin - this.origin, >, min_dist))
        {
                wp = this.goalcurrent_prev;
                if(!wp)
@@ -1790,12 +1803,12 @@ entity navigation_get_really_close_waypoint(entity this)
                if(!wp)
                        return NULL;
        }
-       if(vdist(wp.origin - this.origin, >, 50))
+       if(vdist(wp.origin - this.origin, >, min_dist))
        {
                wp = NULL;
                IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_JUMP)),
                {
-                       if(vdist(it.origin - this.origin, <, 50))
+                       if(vdist(it.origin - this.origin, <, min_dist))
                        {
                                wp = it;
                                break;
index 026d326b9e6fba8524b95a73862eb284e3f06d86..07eacc1860f4d4176a77f2a8bfaf07df1ada6e9d 100644 (file)
@@ -41,6 +41,9 @@ entity navigation_bestgoal;
 /*
 // item it is linked from waypoint it.wpXX (INCOMING link)
 // links are sorted by their cost (wpXXmincost)
+// one of these links is added in game every time a bot heads to an item
+// even links that are not walkable are added (marked with a high cost)
+// so that bots next time know if they can walk it or not saving a tracewalk call
 .entity wp00, wp01, wp02, wp03, wp04, wp05, wp06, wp07, wp08, wp09, wp10, wp11, wp12, wp13, wp14, wp15;
 .entity wp16, wp17, wp18, wp19, wp20, wp21, wp22, wp23, wp24, wp25, wp26, wp27, wp28, wp29, wp30, wp31;
 
@@ -50,9 +53,12 @@ entity navigation_bestgoal;
 .float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
 */
 
-#define navigation_item_islinked(from_wp, to_item) waypoint_islinked(to_item, from_wp)
-#define navigation_item_addlink(from_wp, to_item) \
-       waypoint_addlink_customcost(to_item, from_wp, waypoint_getlinkcost(from_wp, to_item))
+#define navigation_item_initlinks_ifneeded(e) MACRO_BEGIN if (!e.wp00) waypoint_clearlinks(e); MACRO_END // initialize wpXXmincost fields
+#define navigation_item_getlinknum(to_item, from_wp) waypoint_getlinknum(to_item, from_wp)
+#define navigation_item_iswalkablelink(to_item, from_wp) (waypoint_get_assigned_link_cost(to_item, from_wp) < 999)
+
+#define navigation_item_add_link(from_wp, to_item, walkable) \
+       waypoint_addlink_customcost(to_item, from_wp, (walkable ? waypoint_getlinkcost(from_wp, to_item) : 999))
 
 #define TELEPORT_USED(pl, tele_wp) \
        boxesoverlap(tele_wp.absmin, tele_wp.absmax, pl.lastteleport_origin + STAT(PL_MIN, pl), pl.lastteleport_origin + STAT(PL_MAX, pl))
@@ -82,6 +88,8 @@ entity bot_waypoint_queue_goal;               // Head of the temporary list of goals
 entity bot_waypoint_queue_bestgoal;
 float bot_waypoint_queue_bestgoalrating;
 
+const float BOT_BUNNYHOP_WP_DETECTION_RANGE = 100;
+
 .entity bot_basewaypoint;
 .bool navigation_dynamicgoal;
 void navigation_dynamicgoal_init(entity this, bool initially_static);
index 176b6361de30bb83ca0870475a3b49b00bfab804..9c2c6825db0342164159eef90cd99c0e59f8ca91 100644 (file)
@@ -1211,12 +1211,12 @@ float bot_execute_commands_once(entity this)
 
        // Handle conditions
        if (!(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE))
-       if(this.bot_cmd_condition_status & CMD_CONDITION_true && this.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK)
+       if((this.bot_cmd_condition_status & CMD_CONDITION_true) && this.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK)
        {
                bot_command_executed(this, true);
                return -1;
        }
-       else if(this.bot_cmd_condition_status & CMD_CONDITION_false && this.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK)
+       else if((this.bot_cmd_condition_status & CMD_CONDITION_false) && this.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK)
        {
                bot_command_executed(this, true);
                return -1;
index c09d8f81d4fc927bdabe934b27ac86a9e0f3dcab..da407cbbc8673d7cfd2be4603898c0bf5aa1f120 100644 (file)
@@ -1572,6 +1572,46 @@ void waypoint_load_hardwiredlinks()
        LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired");
 }
 
+float waypoint_get_assigned_link_cost(entity w, float i)
+{
+       switch(i)
+       {
+               case  0: return w.wp00mincost;
+               case  1: return w.wp01mincost;
+               case  2: return w.wp02mincost;
+               case  3: return w.wp03mincost;
+               case  4: return w.wp04mincost;
+               case  5: return w.wp05mincost;
+               case  6: return w.wp06mincost;
+               case  7: return w.wp07mincost;
+               case  8: return w.wp08mincost;
+               case  9: return w.wp09mincost;
+               case 10: return w.wp10mincost;
+               case 11: return w.wp11mincost;
+               case 12: return w.wp12mincost;
+               case 13: return w.wp13mincost;
+               case 14: return w.wp14mincost;
+               case 15: return w.wp15mincost;
+               case 16: return w.wp16mincost;
+               case 17: return w.wp17mincost;
+               case 18: return w.wp18mincost;
+               case 19: return w.wp19mincost;
+               case 20: return w.wp20mincost;
+               case 21: return w.wp21mincost;
+               case 22: return w.wp22mincost;
+               case 23: return w.wp23mincost;
+               case 24: return w.wp24mincost;
+               case 25: return w.wp25mincost;
+               case 26: return w.wp26mincost;
+               case 27: return w.wp27mincost;
+               case 28: return w.wp28mincost;
+               case 29: return w.wp29mincost;
+               case 30: return w.wp30mincost;
+               case 31: return w.wp31mincost;
+               default: return -1;
+       }
+}
+
 entity waypoint_get_link(entity w, float i)
 {
        switch(i)
index 25356446a4d1c05d40ece80c5e6f81f64cbfab7e..e9aa1ee12a64213aa9fb8af5feb11347495ba02e 100644 (file)
@@ -67,6 +67,8 @@ void waypoint_think(entity this);
 void waypoint_clearlinks(entity wp);
 void waypoint_schedulerelink(entity wp);
 
+float waypoint_get_assigned_link_cost(entity w, float i);
+
 float waypoint_getlinkcost(entity from, entity to);
 float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent);
 float waypoint_getlinearcost(float dist);
index 336d825a7f58cc2ba4aa99ae1a45d81781293b80..110704f2bbd9b2d80cfba1f6325faa321b53f378 100644 (file)
@@ -124,7 +124,7 @@ void CampaignPreInit()
                {
                        string arg = argv(j);
                        if(arg == "") continue;
-                       _MapInfo_Parse_Settemp(mapname, MAPINFO_SETTEMP_ACL_USER, 0, arg, 0); // no recursion!
+                       _MapInfo_Parse_Settemp(mapname, MAPINFO_SETTEMP_ACL_USER, 0, arg, 1);
                }
        }
 #endif
index 1acab9c00535d647e18a26f1ba35ff55d0ba7cf2..186677df9492f4caf1fa7c7d22711a62692ed133 100644 (file)
@@ -168,8 +168,8 @@ float CheatImpulse(entity this, int imp)
                        this.personal.pauserothealth_finished = this.pauserothealth_finished;
                        this.personal.pauserotfuel_finished = this.pauserotfuel_finished;
                        this.personal.pauseregen_finished = this.pauseregen_finished;
-                       this.personal.strength_finished = this.strength_finished;
-                       this.personal.invincible_finished = this.invincible_finished;
+                       STAT(STRENGTH_FINISHED, this.personal) = STAT(STRENGTH_FINISHED, this);
+                       STAT(INVINCIBLE_FINISHED, this.personal) = STAT(INVINCIBLE_FINISHED, this);
                        this.personal.teleport_time = time;
                        break; // this part itself doesn't cheat, so let's not count this
                case CHIMPULSE_CLONE_MOVING.impulse:
@@ -229,8 +229,8 @@ float CheatImpulse(entity this, int imp)
                                this.pauserothealth_finished = time + this.personal.pauserothealth_finished - this.personal.teleport_time;
                                this.pauserotfuel_finished = time + this.personal.pauserotfuel_finished - this.personal.teleport_time;
                                this.pauseregen_finished = time + this.personal.pauseregen_finished - this.personal.teleport_time;
-                               this.strength_finished = time + this.personal.strength_finished - this.personal.teleport_time;
-                               this.invincible_finished = time + this.personal.invincible_finished - this.personal.teleport_time;
+                               STAT(STRENGTH_FINISHED, this) = time + STAT(STRENGTH_FINISHED, this.personal) - this.personal.teleport_time;
+                               STAT(INVINCIBLE_FINISHED, this) = time + STAT(INVINCIBLE_FINISHED, this.personal) - this.personal.teleport_time;
 
                                if(!autocvar_g_allow_checkpoints)
                                        DID_CHEAT();
index dcddced84ffc39ba07b961850b1fa28cfca81fcb..2f45c06aed9adbab7ebd8d499e1bf4ee3d6e768b 100644 (file)
@@ -334,10 +334,10 @@ void PutObserverInServer(entity this)
        this.fade_time = 0;
        this.pain_frame = 0;
        this.pain_finished = 0;
-       this.strength_finished = 0;
-       this.invincible_finished = 0;
-       this.superweapons_finished = 0;
-       this.air_finished_stat = 0;
+       STAT(STRENGTH_FINISHED, this) = 0;
+       STAT(INVINCIBLE_FINISHED, this) = 0;
+       STAT(SUPERWEAPONS_FINISHED, this) = 0;
+       this.air_finished = 0;
        //this.dphitcontentsmask = 0;
        this.dphitcontentsmask = DPCONTENTS_SOLID;
        if (autocvar_g_playerclip_collisions)
@@ -589,7 +589,7 @@ void PutPlayerInServer(entity this)
 
        PS(this).dual_weapons = '0 0 0';
 
-       this.superweapons_finished = (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
+       STAT(SUPERWEAPONS_FINISHED, this) = (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
 
        this.items = start_items;
 
@@ -638,8 +638,8 @@ void PutPlayerInServer(entity this)
        this.punchangle = '0 0 0';
        this.punchvector = '0 0 0';
 
-       this.strength_finished = 0;
-       this.invincible_finished = 0;
+       STAT(STRENGTH_FINISHED, this) = 0;
+       STAT(INVINCIBLE_FINISHED, this) = 0;
        this.fire_endtime = -1;
        STAT(REVIVE_PROGRESS, this) = 0;
        this.revival_time = 0;
@@ -648,7 +648,7 @@ void PutPlayerInServer(entity this)
        STAT(BUFFS, this) = 0;
        STAT(BUFF_TIME, this) = 0;
 
-       this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+       this.air_finished = 0;
        this.waterlevel = WATERLEVEL_NONE;
        this.watertype = CONTENT_EMPTY;
 
@@ -687,8 +687,13 @@ void PutPlayerInServer(entity this)
                IL_REMOVE(g_conveyed, this);
        this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
        if(this.swampslug)
-               delete(this.swampslug);
-       this.in_swamp = false;
+               IL_REMOVE(g_swamped, this);
+       this.swampslug = NULL;
+       this.swamp_interval = 0;
+       IL_EACH(g_counters, it.realowner == this,
+       {
+               delete(it);
+       });
        STAT(HUD, this) = HUD_NORMAL;
 
        this.event_damage = PlayerDamage;
@@ -1042,7 +1047,9 @@ string getwelcomemessage(entity this)
        modifications = substring(modifications, 2, strlen(modifications) - 2);
 
        string versionmessage = GetClientVersionMessage(this);
-       string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
+       string s = strcat(versionmessage, "^8\n^8\nhost is ^9", autocvar_hostname, "^8\n");
+
+       s = strcat(s, "^8\nmatch type is ^1", gamemode_name, "^8\n");
 
        if(modifications != "")
                s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
@@ -1230,6 +1237,11 @@ void ClientDisconnect(entity this)
        if (this.chatbubbleentity) delete(this.chatbubbleentity);
        if (this.killindicator) delete(this.killindicator);
 
+       IL_EACH(g_counters, it.realowner == this,
+       {
+               delete(it);
+       });
+
        WaypointSprite_PlayerGone(this);
 
        bot_relinkplayerlist();
@@ -1415,9 +1427,9 @@ void player_powerups(entity this)
        {
                if (this.items & ITEM_Strength.m_itemid)
                {
-                       play_countdown(this, this.strength_finished, SND_POWEROFF);
+                       play_countdown(this, STAT(STRENGTH_FINISHED, this), SND_POWEROFF);
                        this.effects = this.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > this.strength_finished)
+                       if (time > STAT(STRENGTH_FINISHED, this))
                        {
                                this.items = this.items - (this.items & ITEM_Strength.m_itemid);
                                //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
@@ -1426,7 +1438,7 @@ void player_powerups(entity this)
                }
                else
                {
-                       if (time < this.strength_finished)
+                       if (time < STAT(STRENGTH_FINISHED, this))
                        {
                                this.items = this.items | ITEM_Strength.m_itemid;
                                if(!g_cts)
@@ -1436,9 +1448,9 @@ void player_powerups(entity this)
                }
                if (this.items & ITEM_Shield.m_itemid)
                {
-                       play_countdown(this, this.invincible_finished, SND_POWEROFF);
+                       play_countdown(this, STAT(INVINCIBLE_FINISHED, this), SND_POWEROFF);
                        this.effects = this.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > this.invincible_finished)
+                       if (time > STAT(INVINCIBLE_FINISHED, this))
                        {
                                this.items = this.items - (this.items & ITEM_Shield.m_itemid);
                                //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
@@ -1447,7 +1459,7 @@ void player_powerups(entity this)
                }
                else
                {
-                       if (time < this.invincible_finished)
+                       if (time < STAT(INVINCIBLE_FINISHED, this))
                        {
                                this.items = this.items | ITEM_Shield.m_itemid;
                                if(!g_cts)
@@ -1459,7 +1471,7 @@ void player_powerups(entity this)
                {
                        if (!(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
                        {
-                               this.superweapons_finished = 0;
+                               STAT(SUPERWEAPONS_FINISHED, this) = 0;
                                this.items = this.items - (this.items & IT_SUPERWEAPON);
                                //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_LOST, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
@@ -1470,8 +1482,8 @@ void player_powerups(entity this)
                        }
                        else
                        {
-                               play_countdown(this, this.superweapons_finished, SND_POWEROFF);
-                               if (time > this.superweapons_finished)
+                               play_countdown(this, STAT(SUPERWEAPONS_FINISHED, this), SND_POWEROFF);
+                               if (time > STAT(SUPERWEAPONS_FINISHED, this))
                                {
                                        this.items = this.items - (this.items & IT_SUPERWEAPON);
                                        STAT(WEAPONS, this) &= ~WEPSET_SUPERWEAPONS;
@@ -1482,7 +1494,7 @@ void player_powerups(entity this)
                }
                else if(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)
                {
-                       if (time < this.superweapons_finished || (this.items & IT_UNLIMITED_SUPERWEAPONS))
+                       if (time < STAT(SUPERWEAPONS_FINISHED, this) || (this.items & IT_UNLIMITED_SUPERWEAPONS))
                        {
                                this.items = this.items | IT_SUPERWEAPON;
                                if(!(this.items & IT_UNLIMITED_SUPERWEAPONS))
@@ -1494,13 +1506,13 @@ void player_powerups(entity this)
                        }
                        else
                        {
-                               this.superweapons_finished = 0;
+                               STAT(SUPERWEAPONS_FINISHED, this) = 0;
                                STAT(WEAPONS, this) &= ~WEPSET_SUPERWEAPONS;
                        }
                }
                else
                {
-                       this.superweapons_finished = 0;
+                       STAT(SUPERWEAPONS_FINISHED, this) = 0;
                }
        }
 
@@ -1537,8 +1549,10 @@ float CalcRot(float current, float stable, float rotfactor, float rotframetime)
                return max(stable, current + (stable - current) * rotfactor * rotframetime);
 }
 
-float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit)
+void RotRegen(entity this, int res, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod)
 {
+       float old = GetResource(this, res);
+       float current = old;
        if(current > rotstable)
        {
                if(rotframetime > 0)
@@ -1556,10 +1570,12 @@ float CalcRotRegen(float current, float regenstable, float regenfactor, float re
                }
        }
 
+       float limit = GetResourceLimit(this, res) * limit_mod;
        if(current > limit)
                current = limit;
 
-       return current;
+       if (current != old)
+               SetResource(this, res, current);
 }
 
 void player_regen(entity this)
@@ -1589,23 +1605,16 @@ void player_regen(entity this)
        if(!mutator_returnvalue)
        if(!STAT(FROZEN, this))
        {
-               float mina, maxa, limith, limita;
-               maxa = autocvar_g_balance_armor_rotstable;
-               mina = autocvar_g_balance_armor_regenstable;
-               limith = GetResourceLimit(this, RES_HEALTH);
-               limita = GetResourceLimit(this, RES_ARMOR);
+               float maxa = autocvar_g_balance_armor_rotstable;
+               float mina = autocvar_g_balance_armor_regenstable;
 
-               regen_health_rotstable = regen_health_rotstable * max_mod;
-               regen_health_stable = regen_health_stable * max_mod;
-               limith = limith * limit_mod;
-               limita = limita * limit_mod;
+               RotRegen(this, RES_ARMOR, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
+                       regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
+                       rot_mod * frametime * (time > this.pauserotarmor_finished), limit_mod);
 
-               SetResource(this, RES_ARMOR, CalcRotRegen(GetResource(this, RES_ARMOR), mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, 
-                                                                       regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
-                                                                       rot_mod * frametime * (time > this.pauserotarmor_finished), limita));
-               SetResource(this, RES_HEALTH, CalcRotRegen(GetResource(this, RES_HEALTH), regen_health_stable, regen_health, regen_health_linear,
-                                                                       regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable, regen_health_rot, regen_health_rotlinear,
-                                                                       rot_mod * frametime * (time > this.pauserothealth_finished), limith));
+               RotRegen(this, RES_HEALTH, regen_health_stable * max_mod, regen_health, regen_health_linear,
+                       regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable * max_mod, regen_health_rot, regen_health_rotlinear,
+                       rot_mod * frametime * (time > this.pauserothealth_finished), limit_mod);
        }
 
        // if player rotted to death...  die!
@@ -1620,15 +1629,12 @@ void player_regen(entity this)
 
        if (!(this.items & IT_UNLIMITED_AMMO))
        {
-               float minf, maxf, limitf;
+               float maxf = autocvar_g_balance_fuel_rotstable;
+               float minf = autocvar_g_balance_fuel_regenstable;
 
-               maxf = autocvar_g_balance_fuel_rotstable;
-               minf = autocvar_g_balance_fuel_regenstable;
-               limitf = GetResourceLimit(this, RES_FUEL);
-
-               SetResource(this, RES_FUEL, CalcRotRegen(GetResource(this, RES_FUEL), minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, 
-                                                                               frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
-                                                                               maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), limitf));
+               RotRegen(this, RES_FUEL, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
+                       frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
+                       maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), 1);
        }
 }
 
@@ -1688,10 +1694,10 @@ void SpectateCopy(entity this, entity spectatee)
        this.items = spectatee.items;
        STAT(LAST_PICKUP, this) = STAT(LAST_PICKUP, spectatee);
        STAT(HIT_TIME, this) = STAT(HIT_TIME, spectatee);
-       this.strength_finished = spectatee.strength_finished;
-       this.invincible_finished = spectatee.invincible_finished;
-       this.superweapons_finished = spectatee.superweapons_finished;
-       this.air_finished_stat = spectatee.air_finished_stat;
+       STAT(STRENGTH_FINISHED, this) = STAT(STRENGTH_FINISHED, spectatee);
+       STAT(INVINCIBLE_FINISHED, this) = STAT(INVINCIBLE_FINISHED, spectatee);
+       STAT(SUPERWEAPONS_FINISHED, this) = STAT(SUPERWEAPONS_FINISHED, spectatee);
+       this.air_finished = spectatee.air_finished;
        STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee);
        STAT(WEAPONS, this) = STAT(WEAPONS, spectatee);
        this.punchangle = spectatee.punchangle;
@@ -1949,6 +1955,8 @@ void Join(entity this)
 
 int GetPlayerLimit()
 {
+       if(g_duel)
+               return 2; // TODO: this workaround is needed since the mutator hook from duel can't be activated before the gametype is loaded (e.g. switching modes via gametype vote screen)
        int player_limit = autocvar_g_maxplayers;
        MUTATOR_CALLHOOK(GetPlayerLimit, player_limit);
        player_limit = M_ARGV(0, int);
@@ -1995,11 +2003,11 @@ int nJoinAllowed(entity this, entity ignore)
        else if(currentlyPlaying < player_limit)
                free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying);
 
-       static float join_prevent_msg_time = 0;
-       if(this && ignore && !free_slots && time > join_prevent_msg_time)
+       static float msg_time = 0;
+       if(this && !this.caplayer && ignore && !free_slots && time > msg_time)
        {
                Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
-               join_prevent_msg_time = time + 3;
+               msg_time = time + 0.5;
        }
 
        return free_slots;
@@ -2277,7 +2285,8 @@ void ObserverThink(entity this)
                        if(this.flags & FL_SPAWNING)
                        {
                                this.flags &= ~FL_SPAWNING;
-                               Join(this);
+                               if(joinAllowed(this))
+                                       Join(this);
                                return;
                        }
                }
@@ -2611,27 +2620,32 @@ void PlayerPreThink (entity this)
 
 void DrownPlayer(entity this)
 {
-       if(IS_DEAD(this) || game_stopped || time < game_starttime)
+       if(IS_DEAD(this) || game_stopped || time < game_starttime || this.vehicle
+               || STAT(FROZEN, this) || this.watertype != CONTENT_WATER)
+       {
+               this.air_finished = 0;
                return;
+       }
 
-       if (this.waterlevel != WATERLEVEL_SUBMERGED || this.vehicle)
+       if (this.waterlevel != WATERLEVEL_SUBMERGED)
        {
-               if(this.air_finished < time)
+               if(this.air_finished && this.air_finished < time)
                        PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
-               this.air_finished = time + autocvar_g_balance_contents_drowndelay;
-               this.air_finished_stat = 0;
+               this.air_finished = 0;
        }
-       else if (this.air_finished < time)
-       {       // drown!
-               if (this.pain_finished < time)
-               {
-                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
-                       this.pain_finished = time + 0.5;
+       else
+       {
+               if (!this.air_finished)
+                       this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+               if (this.air_finished < time)
+               {       // drown!
+                       if (this.pain_finished < time)
+                       {
+                               Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                               this.pain_finished = time + 0.5;
+                       }
                }
-               this.air_finished_stat = this.air_finished;
        }
-       else
-               this.air_finished_stat = this.air_finished;
 }
 
 .bool move_qcphysics;
index b20a8af93cdd5a72539e334adaefabf7b47ae3ac..20148933cbc5421d5a87fb56b105c6c022885ef3 100644 (file)
@@ -141,6 +141,7 @@ CLASS(Client, Object)
     ATTRIB(Client, autoswitch, bool, this.autoswitch);
     ATTRIB(Client, cvar_cl_casings, bool, this.cvar_cl_casings);
     ATTRIB(Client, cvar_cl_dodging_timeout, float, this.cvar_cl_dodging_timeout);
+    ATTRIB(Client, cvar_cl_dodging, float, this.cvar_cl_dodging);
     ATTRIB(Client, cvar_cl_multijump, bool, this.cvar_cl_multijump);
     ATTRIB(Client, cvar_cl_accuracy_data_share, bool, this.cvar_cl_accuracy_data_share);
     ATTRIB(Client, cvar_cl_accuracy_data_receive, bool, this.cvar_cl_accuracy_data_receive);
@@ -265,7 +266,7 @@ void DebugPrintToChatTeam(int team_num, string text);
 
 void play_countdown(entity this, float finished, Sound samp);
 
-float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit);
+void RotRegen(entity this, float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod);
 
 bool Spectate(entity this, entity pl);
 
index 5ff2d3472ae22ebbf2d3d898e0ecbd5f4ae4c910..2383669547fc0e12c0114b0da239424bb828f244 100644 (file)
@@ -1025,23 +1025,22 @@ void GameCommand_moveplayer(int request, int argc)
                                                        if (teamplay)
                                                        {
                                                                // set up
-                                                               float team_id;
                                                                int save = Player_GetForcedTeamIndex(client);
                                                                Player_SetForcedTeamIndex(client, TEAM_FORCE_DEFAULT);
 
                                                                // find the team to move the player to
-                                                               team_id = Team_ColorToTeam(destination);
+                                                               int team_num = Team_ColorToTeam(destination);
                                                                entity balance;
-                                                               if (team_id == client.team)  // already on the destination team
+                                                               if (team_num == client.team)  // already on the destination team
                                                                {
                                                                        // keep the forcing undone
                                                                        LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") is already on the ", Team_ColoredFullName(client.team), (targets ? "^7, skipping to next player.\n" : "^7."));
                                                                        continue;
                                                                }
-                                                               else if (team_id == 0)  // auto team
+                                                               else if (team_num == 0)  // auto team
                                                                {
                                                                        balance = TeamBalance_CheckAllowedTeams(client);
-                                                                       team_id = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false));
+                                                                       team_num = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false));
                                                                }
                                                                else
                                                                {
@@ -1050,62 +1049,24 @@ void GameCommand_moveplayer(int request, int argc)
                                                                Player_SetForcedTeamIndex(client, save);
 
                                                                // Check to see if the destination team is even available
-                                                               switch (team_id)
+                                                               int team_id = Team_TeamToIndex(team_num);
+                                                               if (team_id == -1)
                                                                {
-                                                                       case NUM_TEAM_1:
-                                                                       {
-                                                                               if (!TeamBalance_IsTeamAllowed(balance, 1))
-                                                                               {
-                                                                                       LOG_INFO("Sorry, can't move player to red team if it doesn't exist.");
-                                                                                       TeamBalance_Destroy(balance);
-                                                                                       return;
-                                                                               }
-                                                                               TeamBalance_Destroy(balance);
-                                                                               break;
-                                                                       }
-                                                                       case NUM_TEAM_2:
-                                                                       {
-                                                                               if (!TeamBalance_IsTeamAllowed(balance, 2))
-                                                                               {
-                                                                                       LOG_INFO("Sorry, can't move player to blue team if it doesn't exist.");
-                                                                                       TeamBalance_Destroy(balance);
-                                                                                       return;
-                                                                               }
-                                                                               TeamBalance_Destroy(balance);
-                                                                               break;
-                                                                       }
-                                                                       case NUM_TEAM_3:
-                                                                       {
-                                                                               if (!TeamBalance_IsTeamAllowed(balance, 3))
-                                                                               {
-                                                                                       LOG_INFO("Sorry, can't move player to yellow team if it doesn't exist.");
-                                                                                       TeamBalance_Destroy(balance);
-                                                                                       return;
-                                                                               }
-                                                                               TeamBalance_Destroy(balance);
-                                                                               break;
-                                                                       }
-                                                                       case NUM_TEAM_4:
-                                                                       {
-                                                                               if (!TeamBalance_IsTeamAllowed(balance, 4))
-                                                                               {
-                                                                                       LOG_INFO("Sorry, can't move player to pink team if it doesn't exist.");
-                                                                                       TeamBalance_Destroy(balance);
-                                                                                       return;
-                                                                               }
-                                                                               TeamBalance_Destroy(balance);
-                                                                               break;
-                                                                       }
-                                                                       default:
-                                                                       {
-                                                                               LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist.");
-                                                                               return;
-                                                                       }
+                                                                       LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist.");
+                                                                       TeamBalance_Destroy(balance);
+                                                                       return;
+                                                               }
+                                                               if (!TeamBalance_IsTeamAllowed(balance, team_id))
+                                                               {
+                                                                       LOG_INFOF("Sorry, can't move player to %s team if it doesn't exist.", destination);
+                                                                       TeamBalance_Destroy(balance);
+                                                                       return;
                                                                }
+                                                               TeamBalance_Destroy(balance);
 
                                                                // If so, lets continue and finally move the player
                                                                Player_SetForcedTeamIndex(client, TEAM_FORCE_DEFAULT);
-                                                               if (MoveToTeam(client, Team_TeamToIndex(team_id), 6))
+                                                               if (MoveToTeam(client, team_id, 6))
                                                                {
                                                                        successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
                                                                        LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
@@ -1145,8 +1106,8 @@ void GameCommand_moveplayer(int request, int argc)
                        LOG_INFO("  'clients' is a list (separated by commas) of player entity ID's or nicknames");
                        LOG_INFO("  'destination' is what to send the player to, be it team or spectating");
                        LOG_INFO("  Full list of destinations here: \"spec, spectator, red, blue, yellow, pink, auto.\"");
-                       LOG_INFO("Examples: sv_cmd moveplayer 1,3,5 red 3");
-                       LOG_INFO("          sv_cmd moveplayer 2 spec ");
+                       LOG_INFO("Examples: sv_cmd moveplayer 1,3,5 red");
+                       LOG_INFO("          sv_cmd moveplayer 2 spec");
                        LOG_INFO("See also: ^2allspec, shuffleteams^7");
                        return;
                }
index 630b1ceb850702ff30eb1323ba559317cd97600e..4d469b455dc1919c1061c238e10d8be061afc8fc 100644 (file)
@@ -100,24 +100,34 @@ void target_init_use(entity this, entity actor, entity trigger)
 
        if (!(this.spawnflags & 4))
        {
-               SetResource(actor, RES_SHELLS, start_ammo_shells);
-               SetResource(actor, RES_BULLETS, start_ammo_nails);
-               SetResource(actor, RES_ROCKETS, start_ammo_rockets);
-               SetResource(actor, RES_CELLS, start_ammo_cells);
-               SetResource(actor, RES_PLASMA, start_ammo_plasma);
-               SetResource(actor, RES_FUEL, start_ammo_fuel);
-
-               STAT(WEAPONS, actor) = start_weapons;
-               if (this.spawnflags & 32)
+               if(this.spawnflags & 32) // spawn with only melee
                {
-                       // TODO
+                       SetResource(actor, RES_SHELLS, 0);
+                       SetResource(actor, RES_BULLETS, 0);
+                       SetResource(actor, RES_ROCKETS, 0);
+                       SetResource(actor, RES_CELLS, 0);
+                       SetResource(actor, RES_PLASMA, 0);
+                       SetResource(actor, RES_FUEL, 0);
+
+                       STAT(WEAPONS, actor) = WEPSET(SHOTGUN);
+               }
+               else
+               {
+                       SetResource(actor, RES_SHELLS, start_ammo_shells);
+                       SetResource(actor, RES_BULLETS, start_ammo_nails);
+                       SetResource(actor, RES_ROCKETS, start_ammo_rockets);
+                       SetResource(actor, RES_CELLS, start_ammo_cells);
+                       SetResource(actor, RES_PLASMA, start_ammo_plasma);
+                       SetResource(actor, RES_FUEL, start_ammo_fuel);
+
+                       STAT(WEAPONS, actor) = start_weapons;
                }
        }
 
        if (!(this.spawnflags & 8))
        {
-               actor.strength_finished = 0;
-               actor.invincible_finished = 0;
+               STAT(STRENGTH_FINISHED, actor) = 0;
+               STAT(INVINCIBLE_FINISHED, actor) = 0;
                if(STAT(BUFFS, actor)) // TODO: make a dropbuffs function to handle this
                {
                        int buffid = buff_FirstFromFlags(STAT(BUFFS, actor)).m_id;
@@ -173,6 +183,10 @@ void target_give_init(entity this)
                        SetResourceExplicit(this, RES_ROCKETS, GetResource(this, RES_ROCKETS) + it.count * WEP_CVAR_PRI(mortar, ammo)); // WEAPONTODO
                        this.netname = cons(this.netname, "mortar");
                }
+               else if (it.classname == "weapon_shotgun") {
+                       SetResourceExplicit(this, RES_SHELLS, GetResource(this, RES_SHELLS) + it.count * WEP_CVAR_PRI(shotgun, ammo)); // WEAPONTODO
+                       this.netname = cons(this.netname, "shotgun");
+               }
                else if (it.classname == "item_armor_mega")
                        SetResourceExplicit(this, RES_ARMOR, 100);
                else if (it.classname == "item_health_mega")
index 9036ee22219f46aa4baf8724c5d2faee709a818a..9d7421987c1ce254c5ce4da58139214d594a6d53 100644 (file)
@@ -50,8 +50,8 @@ float server_is_dedicated;
 .float pain_frame;                     //"
 .float  crouch;        // Crouching or not?
 
-const .float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
-const .float air_finished_stat = _STAT(AIR_FINISHED);
+.float superweapons_finished; // NOTE: this field is used only by map entities, it does not directly apply the superweapons stat
+const .float air_finished = _STAT(AIR_FINISHED);
 
 .float cnt; // used in too many places
 .float count;
@@ -93,7 +93,6 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 .float railgunhitsolidbackup;
 .vector railgunhitloc;
 
-.float         air_finished;
 .float         dmgtime;
 
 .float         killcount;
@@ -141,7 +140,6 @@ float blockSpectators; //if set, new or existing spectators or observers will be
 .float spectatortime; //point in time since the client is spectating or observing
 void checkSpectatorBlock(entity this);
 
-float game_completion_ratio; // 0 at start, 1 near end
 .float winning;
 .float jointime; // time of connecting
 .float startplaytime; // time of switching from spectator to player
index e14ecd6ce7808ebeeca7dd436dc1aa4d41db2127..555a73472fb35cff23435bc2c9b7f2cdfbc66525 100644 (file)
@@ -85,9 +85,9 @@ string AppendItemcodes(string s, entity player)
                if(w != 0 || slot == 0)
                        s = strcat(s, ftos(w));
        }
-       if(time < player.strength_finished)
+       if(time < STAT(STRENGTH_FINISHED, player))
                s = strcat(s, "S");
-       if(time < player.invincible_finished)
+       if(time < STAT(INVINCIBLE_FINISHED, player))
                s = strcat(s, "I");
        if(PHYS_INPUT_BUTTON_CHAT(player))
                s = strcat(s, "T");
@@ -199,9 +199,9 @@ float Obituary_WeaponDeath(
        else
        {
                LOG_TRACEF(
-                       "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %d!\n",
+                       "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
                        deathtype,
-                       death_weapon
+                       death_weapon.netname
                );
        }
 
@@ -683,7 +683,8 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
                    }
                }
 
-               if(deathtype != DEATH_HURTTRIGGER.m_id && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id && STAT(FROZEN, targ))
+               if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
+                       && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
                {
                        if(autocvar_g_frozen_revive_falldamage > 0 && deathtype == DEATH_FALL.m_id && damage >= autocvar_g_frozen_revive_falldamage)
                        {
@@ -698,12 +699,12 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
                        force *= autocvar_g_frozen_force;
                }
 
-               if(IS_PLAYER(targ) && STAT(FROZEN, targ) && deathtype == DEATH_HURTTRIGGER.m_id && !autocvar_g_frozen_damage_trigger)
+               if(IS_PLAYER(targ) && STAT(FROZEN, targ)
+                       && ITEM_DAMAGE_NEEDKILL(deathtype) && !autocvar_g_frozen_damage_trigger)
                {
                        Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
 
-                       entity spot = SelectSpawnPoint (targ, false);
-
+                       entity spot = SelectSpawnPoint(targ, false);
                        if(spot)
                        {
                                damage = 0;
index fd8631f31a8657e82d664149f6ba16c83b729b7d..bee939d9ac55fc5da8766fb70d0510123d1b71f3 100644 (file)
@@ -398,6 +398,7 @@ void cvar_changes_init()
                //   :%s,//\([^ ]*\).*,BADCVAR("\1");,
                //   :%!sort
                // yes, this does contain some redundant stuff, don't really care
+               BADPREFIX("bot_ai_");
                BADCVAR("bot_config_file");
                BADCVAR("bot_number");
                BADCVAR("bot_prefix");
@@ -822,7 +823,7 @@ spawnfunc(worldspawn)
        // character set: ASCII 33-126 without the following characters: : ; ' " \ $
        if(autocvar_sv_eventlog)
        {
-               string s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
+               string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
                matchid = strzone(s);
 
                GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
@@ -1071,7 +1072,8 @@ bool MapHasRightSize(string map)
        // open map size restriction file
        string opensize_msg = strcat("opensize ", map);
        float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
-       int pcount = player_count;
+       int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
+       int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
        if(!autocvar_g_maplist_sizes_count_bots)
                pcount -= currentbots;
        if(fh >= 0)
@@ -1104,7 +1106,7 @@ string Map_Filename(float position)
 
 void Map_MarkAsRecent(string m)
 {
-       cvar_set("g_maplist_mostrecent", strwords(strcat(m, " ", autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
+       cvar_set("g_maplist_mostrecent", strwords(cons(m, autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
 }
 
 float Map_IsRecent(string m)
@@ -1705,13 +1707,9 @@ void ShuffleMaplist()
        cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
 }
 
-float leaderscore;
-float secondscore;
 int fragsleft_last;
 float WinningCondition_Scores(float limit, float leadlimit)
 {
-       float limitreached;
-
        // TODO make everything use THIS winning condition (except LMS)
        WinningConditionHelper(NULL);
 
@@ -1741,66 +1739,43 @@ float WinningCondition_Scores(float limit, float leadlimit)
                leadlimit = 0; // not supported in this mode
 
        if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
-       // these modes always score in increments of 1, thus this makes sense
        {
-               if (leaderscore != WinningConditionHelper_topscore ||
-                       secondscore != WinningConditionHelper_secondscore)
-               {
-                       int fragsleft = 0, leadingfragsleft = 0;
-
-                       leaderscore = WinningConditionHelper_topscore;
-                       secondscore = WinningConditionHelper_secondscore;
+               float fragsleft = FLOAT_MAX, leadingfragsleft = FLOAT_MAX;
+               if (limit)
+                       fragsleft = limit - WinningConditionHelper_topscore;
+               if (leadlimit)
+                       leadingfragsleft = WinningConditionHelper_secondscore + leadlimit - WinningConditionHelper_topscore;
 
-                       if (limit)
-                               fragsleft = limit - leaderscore;
-                       if (leadlimit)
-                               leadingfragsleft = secondscore + leadlimit - leaderscore;
-
-                       if (autocvar_leadlimit_and_fraglimit && leadlimit)
-                       {
-                               if (limit)
-                                       fragsleft = max(leadingfragsleft, fragsleft);
-                       }
-                       else if (leadlimit)
-                       {
-                               if (limit)
-                                       fragsleft = min(fragsleft, leadingfragsleft);
-                               else
-                                       fragsleft = leadingfragsleft;
-                       }
+               if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+                       fragsleft = max(fragsleft, leadingfragsleft);
+               else
+                       fragsleft = min(fragsleft, leadingfragsleft);
 
-                       if (fragsleft_last != fragsleft) // do not announce same remaining frags multiple times
-                       {
-                               if (fragsleft == 1)
-                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
-                               else if (fragsleft == 2)
-                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
-                               else if (fragsleft == 3)
-                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
-
-                               fragsleft_last = fragsleft;
-                       }
+               if (fragsleft_last != fragsleft) // do not announce same remaining frags multiple times
+               {
+                       if (fragsleft == 1)
+                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
+                       else if (fragsleft == 2)
+                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
+                       else if (fragsleft == 3)
+                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
+
+                       fragsleft_last = fragsleft;
                }
        }
 
-       limitreached = false;
-       if (limit && WinningConditionHelper_topscore >= limit)
-               limitreached = true;
-       if(leadlimit)
-       {
-               float leadlimitreached;
-               leadlimitreached = (WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
-               if(autocvar_leadlimit_and_fraglimit)
-                       limitreached = (limitreached && leadlimitreached);
-               else
-                       limitreached = (limitreached || leadlimitreached);
-       }
+       bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
+       bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
 
-       if(limit)
-               game_completion_ratio = max(game_completion_ratio, bound(0, WinningConditionHelper_topscore / limit, 1));
+       bool limit_reached;
+       // only respect leadlimit_and_fraglimit when both limits are set or the game will never end
+       if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+               limit_reached = (fraglimit_reached && leadlimit_reached);
+       else
+               limit_reached = (fraglimit_reached || leadlimit_reached);
 
        return GetWinningCode(
-               WinningConditionHelper_topscore && limitreached,
+               WinningConditionHelper_topscore && limit_reached,
                WinningConditionHelper_equality
        );
 }
@@ -1891,10 +1866,6 @@ Exit deathmatch games upon conditions
 */
 void CheckRules_World()
 {
-       float timelimit;
-       float fraglimit;
-       float leadlimit;
-
        VoteThink();
        MapVote_Think();
 
@@ -1909,9 +1880,10 @@ void CheckRules_World()
                return;
        }
 
-       timelimit = autocvar_timelimit * 60;
-       fraglimit = autocvar_fraglimit;
-       leadlimit = autocvar_leadlimit;
+       float timelimit = autocvar_timelimit * 60;
+       float fraglimit = autocvar_fraglimit;
+       float leadlimit = autocvar_leadlimit;
+       if (leadlimit < 0) leadlimit = 0;
 
        if(warmup_stage || time <= game_starttime) // NOTE: this is <= to prevent problems in the very tic where the game starts
        {
@@ -1936,11 +1908,6 @@ void CheckRules_World()
        float wantovertime;
        wantovertime = 0;
 
-       if(timelimit > game_starttime)
-               game_completion_ratio = (time - game_starttime) / (timelimit - game_starttime);
-       else
-               game_completion_ratio = 0;
-
        if(checkrules_suddendeathend)
        {
                if(!checkrules_suddendeathwarning)
index 4e2113f53fe3baf148c7c7308c371c51efc45c87..9dd468c2d74982c15a6e83691debb4b4c9254bcb 100644 (file)
@@ -856,9 +856,14 @@ void readplayerstartcvars()
 
 void precache_playermodel(string m)
 {
-       float globhandle, i, n;
+       int globhandle, i, n;
        string f;
 
+       // remove :<skinnumber> suffix
+       int j = strstrofs(m, ":", 0);
+       if(j >= 0)
+               m = substring(m, 0, j);
+
        if(substring(m, -9, 5) == "_lod1")
                return;
        if(substring(m, -9, 5) == "_lod2")
index 9bf3f7c60283db691cbfa8430aeba0ad4a504aec..e5a8f47f90f859908e0ba951776cbd71a3bbf854 100644 (file)
@@ -468,6 +468,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
                        float realdmg = damage - excess;
                        if (this != attacker && realdmg)
+                       if (!(round_handler_IsActive() && !round_handler_IsRoundStarted()) && time >= game_starttime)
                        {
                                if (IS_PLAYER(attacker) && DIFF_TEAM(attacker, this)) {
                                        GameRules_scoring_add(attacker, DMG, realdmg);
@@ -490,6 +491,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        bool valid_damage_for_weaponstats = false;
        Weapon awep = WEP_Null;
 
+       if (!(round_handler_IsActive() && !round_handler_IsRoundStarted()) && time >= game_starttime)
        if(vbot || IS_REAL_CLIENT(this))
        if(abot || IS_REAL_CLIENT(attacker))
        if(attacker && this != attacker)
index af2f4b574f43a57f0c098d19c47b5fe2754428ac..69b18ba2a206d8685dd1ef33bf18604007a971fb 100644 (file)
@@ -5,6 +5,7 @@
 #include <server/g_world.qh>
 #include <server/miscfunctions.qh>
 #include <server/mutators/_mod.qh>
+#include <server/round_handler.qh>
 #include <common/net_linked.qh>
 #include "../common/playerstats.qh"
 #include "../common/teams.qh"
@@ -107,8 +108,11 @@ float TeamScore_AddToTeam(int t, float scorefield, float score)
 {
        entity s;
 
-       if(game_stopped)
+       if(game_stopped || time < game_starttime
+               || (round_handler_IsActive() && !round_handler_IsRoundStarted()))
+       {
                score = 0;
+       }
 
        if(!scores_initialized) return 0; // FIXME remove this when everything uses this system
        if(t <= 0 || t >= 16)
@@ -334,9 +338,11 @@ float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score)
        bool mutator_returnvalue = MUTATOR_CALLHOOK(AddPlayerScore, scorefield, score, player);
        score = M_ARGV(1, float);
 
-       if(game_stopped)
-       if(!mutator_returnvalue)
+       if((!mutator_returnvalue && game_stopped) || time < game_starttime
+               || (round_handler_IsActive() && !round_handler_IsRoundStarted()))
+       {
                score = 0;
+       }
 
        if(!scores_initialized) return 0; // FIXME remove this when everything uses this system
        entity s = CS(player).scorekeeper;
index 5aa81a2a73b0e9ad3fae1304237f863e71c9a2ed..e2c5ab307aa7743dedc878cc89f0b2254f4ae8bc 100644 (file)
@@ -65,10 +65,16 @@ void spawnpoint_use(entity this, entity actor, entity trigger)
        {
                this.team = actor.team;
                some_spawn_has_been_used = true;
+               this.SendFlags |= 1; // update team on the client side
        }
        //LOG_INFO("spawnpoint was used!\n");
 }
 
+void spawnpoint_reset(entity this)
+{
+       this.SendFlags |= 1; // update team since it was restored during reset
+}
+
 void relocate_spawnpoint(entity this)
 {
     // nudge off the floor
@@ -106,6 +112,7 @@ void relocate_spawnpoint(entity this)
     this.use = spawnpoint_use;
     setthink(this, spawnpoint_think);
     this.nextthink = time + 0.5 + random() * 2; // shouldn't need it for a little second
+    this.reset2 = spawnpoint_reset; // restores team, allows re-sending the spawnpoint
     this.team_saved = this.team;
     IL_PUSH(g_saved_team, this);
     if (!this.cnt)
index 367cc99b7a64f3f45f25a2242b8ec0c350ba1219..531a1537bf14a6efa183f66fc82a60bbe84cc5a4 100644 (file)
@@ -46,7 +46,14 @@ void CreatureFrame_hotliquids(entity this)
        }
        else
        {
-               if (this.watertype == CONTENT_LAVA)
+               if (STAT(FROZEN, this))
+               {
+                       if (this.watertype == CONTENT_LAVA)
+                               Damage(this, NULL, NULL, 10000, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                       else if (this.watertype == CONTENT_SLIME)
+                               Damage(this, NULL, NULL, 10000, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+               }
+               else if (this.watertype == CONTENT_LAVA)
                {
                        if (this.watersound_finished < time)
                        {
@@ -89,7 +96,6 @@ void CreatureFrame_Liquids(entity this)
                        this.flags &= ~FL_INWATER;
                        this.dmgtime = 0;
                }
-               this.air_finished = time + autocvar_g_balance_contents_drowndelay;
        }
 }
 
index 7e8a061f049b1ebc552308c796219c1b716eedbd..ba039fc1055baf6655a3bc91724635df4d69281f 100644 (file)
@@ -67,15 +67,15 @@ float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector
                        });
                        if(superweapons <= 1)
                        {
-                               wep.superweapons_finished = own.superweapons_finished;
-                               own.superweapons_finished = 0;
+                               wep.superweapons_finished = STAT(SUPERWEAPONS_FINISHED, own);
+                               STAT(SUPERWEAPONS_FINISHED, own) = 0;
                        }
                        else
                        {
-                               float timeleft = own.superweapons_finished - time;
+                               float timeleft = STAT(SUPERWEAPONS_FINISHED, own) - time;
                                float weptimeleft = timeleft / superweapons;
                                wep.superweapons_finished = time + weptimeleft;
-                               own.superweapons_finished -= weptimeleft;
+                               STAT(SUPERWEAPONS_FINISHED, own) -= weptimeleft;
                        }
                }
        }
index da045a45c8524dbea21d069b402ad6b46ea20b37..e0e1a852c0e230e2c4e94df1393dd287003ad28e 100644 (file)
Binary files a/sound/weapons/hagar_fire.ogg and b/sound/weapons/hagar_fire.ogg differ
index f0d6b5fbffdd4aea4cbe8986a802b42162f9f5f7..7d6ad35f7bd3da4ede1394e723986a2850235dac 100644 (file)
Binary files a/sound/weapons/rocket_fire.ogg and b/sound/weapons/rocket_fire.ogg differ
diff --git a/testing.cfg b/testing.cfg
new file mode 100644 (file)
index 0000000..f000a08
--- /dev/null
@@ -0,0 +1,15 @@
+// https://forums.xonotic.org/showthread.php?tid=8190
+// https://gitlab.com/xonotic/xonotic-data.pk3dir/merge_requests/738
+alias test_blaster_switch "settemp g_balance_blaster_primary_animtime 0.1 ; settemp g_balance_blaster_switchdelay_drop 0.1 ; settemp g_balance_blaster_switchdelay_raise 0.1"
+
+alias test_crylink_sec_horizontal "settemp g_balance_crylink_secondary_linkexplode 0 ; settemp g_balance_crylink_secondary_other_fadetime 2 ; settemp g_balance_crylink_secondary_other_lifetime 2 ; settemp g_balance_crylink_secondary_speed 4000 ; settemp g_balance_crylink_secondary_spread 0.08 ; settemp g_balance_crylink_secondary_spreadtype 0"
+
+alias test_rocket_flying "settemp g_balance_devastator_remote_jump 1"
+
+// https://forums.xonotic.org/showthread.php?tid=8192
+// https://gitlab.com/xonotic/xonotic-data.pk3dir/merge_requests/736
+alias test_ctf_stalemate90 "settemp g_ctf_stalemate_time 90"
+alias test_ctf_stalemate120 "settemp g_ctf_stalemate_time 120"
+
+alias testing_enable "addvote test_blaster_switch ; addvote test_crylink_sec_horizontal ; addvote test_rocket_flying ; addvote test_ctf_stalemate90 ; addvote test_ctf_stalemate120"
+alias testing_disable "delvote test_blaster_switch ; delvote test_crylink_sec_horizontal ; delvote test_rocket_flying ; delvote test_ctf_stalemate90 ; delvote test_ctf_stalemate120"
diff --git a/textures/gib2_gloss.tga b/textures/gib2_gloss.tga
new file mode 100644 (file)
index 0000000..1e83337
Binary files /dev/null and b/textures/gib2_gloss.tga differ
diff --git a/textures/gib2_spec.tga b/textures/gib2_spec.tga
deleted file mode 100644 (file)
index 1e83337..0000000
Binary files a/textures/gib2_spec.tga and /dev/null differ
diff --git a/textures/gib3_gloss.tga b/textures/gib3_gloss.tga
new file mode 100644 (file)
index 0000000..1e81d9a
Binary files /dev/null and b/textures/gib3_gloss.tga differ
diff --git a/textures/gib3_spec.tga b/textures/gib3_spec.tga
deleted file mode 100644 (file)
index 1e81d9a..0000000
Binary files a/textures/gib3_spec.tga and /dev/null differ
diff --git a/textures/gib4_gloss.tga b/textures/gib4_gloss.tga
new file mode 100644 (file)
index 0000000..899b220
Binary files /dev/null and b/textures/gib4_gloss.tga differ
diff --git a/textures/gib4_spec.tga b/textures/gib4_spec.tga
deleted file mode 100644 (file)
index 899b220..0000000
Binary files a/textures/gib4_spec.tga and /dev/null differ
diff --git a/textures/hagar_gloss.tga b/textures/hagar_gloss.tga
new file mode 100644 (file)
index 0000000..e44d88b
Binary files /dev/null and b/textures/hagar_gloss.tga differ
diff --git a/textures/hagar_spec.tga b/textures/hagar_spec.tga
deleted file mode 100644 (file)
index e44d88b..0000000
Binary files a/textures/hagar_spec.tga and /dev/null differ
index f1335c9d29b185978c78baa09d773f5f74dd1043..389da6f74cb35b5340e0644530f2ce2291da9bcd 100644 (file)
@@ -228,7 +228,8 @@ seta cl_damageeffect_lifetime 0.1 "how much a damage effect lasts, based on dama
 seta cl_damageeffect_lifetime_min 3 "minimum lifetime a damage effect may have"
 seta cl_damageeffect_lifetime_max 6 "maximum lifetime a damage effect may have"
 
-set cl_deathglow 0.8 "number of seconds during which dead bodies glow out"
+set cl_deathglow 2 "number of seconds during which dead bodies glow out"
+set cl_deathglow_min 0.5 "glow out up to this glow factor"
 
 cl_movement 1
 cl_movement_track_canjump 0
index 4fd0ee0c1488965a1eae4bd06164ab018a710b4e..7a2c4611ad2ce287500b5cf3aa91827621f7c4ca 100644 (file)
@@ -144,6 +144,9 @@ seta snd_channel9volume 1 "QuakeC controlled ambient sound volume"
 snd_identicalsoundrandomization_time -0.1
 snd_identicalsoundrandomization_tics    1
 
+set debug_deglobalization_logging 0 "bitfield: 1 logs usage of the old functions which use globals implicitly, 2 logs usage of the new wrappers; support for this can be disabled at compile time for better performance"
+set debug_deglobalization_clear 0 "make the new wrappers set globals to NaN after use, this helps find bugs but can result in crashes; support for this can be disabled at compile time for better performance"
+
 // load console command aliases and settings
 exec commands.cfg
 
index 843a83d3d6132ec8356508eadd838d5cdb32f2c1..d4a97d7da54f872b631665fe9c0fad750faf00c2 100644 (file)
@@ -126,7 +126,8 @@ set bot_typefrag 0 "Allow bots to shoot players while they're typing"
 set bot_ai_thinkinterval 0.05 "Frame rate at which bots update their navigation and aiming, scales by skill"
 set bot_ai_strategyinterval 7 "How often a new objective is chosen"
 set bot_ai_strategyinterval_movingtarget 5.5 "How often a new objective is chosen when current objective can move"
-set bot_ai_enemydetectioninterval 2 "How often bots pick a new target"
+set bot_ai_enemydetectioninterval 2 "How often bots try to pick a new target if no suitable target is found"
+set bot_ai_enemydetectioninterval_stickingtoenemy 4 "How often bots try to pick a new target while targetting an enemy"
 set bot_ai_enemydetectionradius 10000 "How far bots can see enemies"
 set bot_ai_dodgeupdateinterval 0.2 "How often scan for items to dodge. Currently not in use."
 set bot_ai_chooseweaponinterval 0.5 "How often the best weapon according to the situation will be chosen"
@@ -152,9 +153,11 @@ set bot_ai_weapon_combo_threshold 0.4 "Try to make a combo N seconds after the l
 set bot_ai_friends_aware_pickup_radius "500" "Bots will not pickup items if a team mate is this distance near the item"
 set bot_ai_ignoregoal_timeout 3 "Ignore goals making bots to get stuck in front of a wall for N seconds"
 set bot_ai_bunnyhop_skilloffset 7 "Bots with skill equal or greater than this value will perform the \"bunnyhop\" technique"
-set bot_ai_bunnyhop_startdistance 200 "Run to goals located further than this distance"
-set bot_ai_bunnyhop_stopdistance 300 "Stop jumping after reaching this distance to the goal"
-set bot_ai_bunnyhop_firstjumpdelay 0.2 "Start running to the goal only if it was seen for more than N seconds"
+set bot_ai_bunnyhop_dir_deviation_max 20 "bunnyhop if speed - direction deviation is <= this amount"
+set bot_ai_bunnyhop_downward_pitch_max 30 "bunnyhop if downard pitch towards the next waypoint is <= this amount"
+set bot_ai_bunnyhop_turn_angle_max 80 "bunnyhop if next turn angle is <= this amount at walk speed (sv_maxspeed)"
+set bot_ai_bunnyhop_turn_angle_min 4 "bunnyhop regardless of speed if next turn angle is <= this amount"
+set bot_ai_bunnyhop_turn_angle_reduction 40 "linearly reduce max turn angle by this amount when speed increases by sv_maxspeed"
 set bot_god 0 "god mode for bots"
 set bot_ai_navigation_jetpack 0 "Enable bots to navigate maps using the jetpack"
 set bot_ai_navigation_jetpack_mindistance 3500 "Bots will try fly to objects located farther than this distance"
@@ -217,6 +220,7 @@ set g_maplist_selectrandom 0 "if 1, a random map will be chosen as next map - DE
 set g_maplist_shuffle 1 "new randomization method: like selectrandom, but avoid playing the same maps in short succession. This works by taking out the first element and inserting it into g_maplist with a bias to the end of the list"
 set g_maplist_check_waypoints 0 "when 1, maps are skipped if there currently are bots, but the map has no waypoints"
 set g_maplist_ignore_sizes 0 "when 1, all maps are shown in the map list regardless of player count"
+set g_maplist_sizes_count_maxplayers 1 "check the player limit when getting the player count so forced spectators don't affect the size restrictions"
 set g_maplist_sizes_count_bots 1 "include the number of bots currently in the server when counting the number of players for size restrictions"
 
 set g_items_mindist 4000 "starting distance for the fading of items"
@@ -530,7 +534,7 @@ alias g_forced_team_matchsetup "map $1; settemp g_forced_team_red \"$2\"; settem
 // frozen
 set g_frozen_revive_falldamage 0 "Enable reviving from this amount of fall damage"
 set g_frozen_revive_falldamage_health 40 "Amount of health player has if they revived from falling"
-set g_frozen_damage_trigger 1 "if 1, frozen players falling into the void will die instead of teleporting to spawn"
+set g_frozen_damage_trigger 1 "if 1, frozen players falling into the void/lava/slime will die instead of teleporting to spawn"
 set g_frozen_force 0.6 "How much to multiply the force on a frozen player with"
 
 // player statistics
@@ -550,7 +554,8 @@ set g_mod_balance "" "Current balance config name"
 set g_mod_config  "" "Current config mod name"
 
 // other config files
-exec balance-xonotic.cfg
+exec testing.cfg
+exec balance-xonotic.cfg // depends on testing.cfg
 exec physicsX.cfg
 exec turrets.cfg
 exec vehicles.cfg