]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'martin-t/tips' into 'master'
authorMario <mario.mario@y7mail.com>
Thu, 26 Sep 2019 10:58:27 +0000 (10:58 +0000)
committerMario <mario.mario@y7mail.com>
Thu, 26 Sep 2019 10:58:27 +0000 (10:58 +0000)
Improve tips

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

406 files changed:
.gitlab-ci.yml
.tx/merge-base
_hud_common.cfg
bal-wep-mario.cfg
bal-wep-nexuiz25.cfg
bal-wep-overkill-nerfed.cfg
bal-wep-samual.cfg
bal-wep-testing.cfg [new file with mode: 0644]
bal-wep-testingxpm.cfg [new file with mode: 0644]
bal-wep-xdf.cfg
bal-wep-xonotic.cfg
bal-wep-xpm.cfg
balance-overkill.cfg
balance-testing.cfg [new file with mode: 0644]
balance-testingxpm.cfg [new file with mode: 0644]
binds-xonotic.cfg
commands.cfg
common.fr.po
common.tr.po
common.zh_CN.po
crosshairs.cfg
gamemodes-server.cfg
models/monsters/zombie.dpm_0.sounds
mutators.cfg
physicsOverkill.cfg
qcsrc/client/autocvars.qh
qcsrc/client/commands/cl_cmd.qc
qcsrc/client/defs.qh
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/modicons.qh
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/view.qc
qcsrc/client/view.qh
qcsrc/common/constants.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/deathtypes/all.qh
qcsrc/common/effects/qc/casings.qc
qcsrc/common/effects/qc/damageeffects.qc
qcsrc/common/gamemodes/gamemode/assault/sv_assault.qc
qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc
qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh
qcsrc/common/gamemodes/gamemode/ctf/_mod.inc
qcsrc/common/gamemodes/gamemode/ctf/_mod.qh
qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/ctf/ctf.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qh
qcsrc/common/gamemodes/gamemode/domination/_mod.inc
qcsrc/common/gamemodes/gamemode/domination/_mod.qh
qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/domination/domination.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/domination/domination.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh
qcsrc/common/gamemodes/gamemode/keepaway/_mod.inc
qcsrc/common/gamemodes/gamemode/keepaway/_mod.qh
qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keyhunt/_mod.inc
qcsrc/common/gamemodes/gamemode/keyhunt/_mod.qh
qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc
qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh
qcsrc/common/gamemodes/gamemode/nexball/_mod.inc
qcsrc/common/gamemodes/gamemode/nexball/_mod.qh
qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qh
qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/weapon.qh
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/items/all.qh
qcsrc/common/items/inventory.qh
qcsrc/common/items/item.qh
qcsrc/common/items/item/ammo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/mapobjects/func/door.qc
qcsrc/common/mapobjects/misc/corner.qc
qcsrc/common/mapobjects/misc/dynlight.qc
qcsrc/common/mapobjects/misc/teleport_dest.qc
qcsrc/common/mapobjects/target/music.qc
qcsrc/common/mapobjects/teleporters.qc
qcsrc/common/mapobjects/trigger/counter.qc
qcsrc/common/mapobjects/trigger/heal.qc
qcsrc/common/mapobjects/trigger/jumppads.qc
qcsrc/common/mapobjects/trigger/magicear.qc
qcsrc/common/mapobjects/trigger/swamp.qc
qcsrc/common/mapobjects/trigger/swamp.qh
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/models/model.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/mage.qh
qcsrc/common/monsters/monster/spider.qh
qcsrc/common/monsters/monster/wyvern.qh
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/monsters/sv_spawner.qc
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/mutator/buffs/buffs.qh
qcsrc/common/mutators/mutator/buffs/cl_buffs.qh
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/dodging/_mod.inc
qcsrc/common/mutators/mutator/dodging/_mod.qh
qcsrc/common/mutators/mutator/dodging/cl_dodging.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/dodging/cl_dodging.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/dodging/dodging.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/dodging/dodging.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/itemstime/itemstime.qc
qcsrc/common/mutators/mutator/multijump/multijump.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nades/nades.qh
qcsrc/common/mutators/mutator/new_toys/sv_new_toys.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/overkill/_mod.inc
qcsrc/common/mutators/mutator/overkill/_mod.qh
qcsrc/common/mutators/mutator/overkill/okhmg.qc
qcsrc/common/mutators/mutator/overkill/okhmg.qh
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qh
qcsrc/common/mutators/mutator/overkill/oknex.qc
qcsrc/common/mutators/mutator/overkill/oknex.qh
qcsrc/common/mutators/mutator/overkill/okrpc.qh
qcsrc/common/mutators/mutator/overkill/okshotgun.qh
qcsrc/common/mutators/mutator/overkill/overkill.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/overkill.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qh
qcsrc/common/mutators/mutator/rocketflying/sv_rocketflying.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/_mod.inc
qcsrc/common/mutators/mutator/spawn_near_teammate/_mod.qh
qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
qcsrc/common/notifications/all.inc
qcsrc/common/notifications/all.qc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/movetypes/movetypes.qh
qcsrc/common/physics/movetypes/step.qc
qcsrc/common/physics/movetypes/walk.qc
qcsrc/common/physics/player.qc
qcsrc/common/playerstats.qc
qcsrc/common/sounds/all.inc
qcsrc/common/sounds/sound.qh
qcsrc/common/state.qc
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/common/turrets/checkpoint.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/turrets/sv_turrets.qh
qcsrc/common/turrets/turret/ewheel_weapon.qh
qcsrc/common/turrets/turret/flac_weapon.qh
qcsrc/common/turrets/turret/hellion_weapon.qh
qcsrc/common/turrets/turret/hk_weapon.qh
qcsrc/common/turrets/turret/machinegun_weapon.qh
qcsrc/common/turrets/turret/mlrs_weapon.qh
qcsrc/common/turrets/turret/phaser_weapon.qc
qcsrc/common/turrets/turret/phaser_weapon.qh
qcsrc/common/turrets/turret/plasma_dual.qh
qcsrc/common/turrets/turret/plasma_weapon.qh
qcsrc/common/turrets/turret/tesla_weapon.qh
qcsrc/common/turrets/turret/walker_weapon.qh
qcsrc/common/turrets/util.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle/racer_weapon.qh
qcsrc/common/vehicles/vehicle/raptor_weapons.qh
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/config.qc
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/blaster.qh
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/devastator.qh
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/hook.qh
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/machinegun.qh
qcsrc/common/weapons/weapon/mortar.qh
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/porto.qh
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shockwave.qh
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/tuba.qh
qcsrc/common/weapons/weapon/vaporizer.qh
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/common/weapons/weapon/vortex.qh
qcsrc/common/wepent.qc
qcsrc/common/wepent.qh
qcsrc/lib/counting.qh
qcsrc/lib/csqcmodel/cl_model.qc
qcsrc/lib/csqcmodel/cl_model.qh
qcsrc/lib/csqcmodel/sv_model.qc
qcsrc/lib/csqcmodel/sv_model.qh
qcsrc/lib/registry.qh
qcsrc/lib/replicate.qh
qcsrc/lib/spawnfunc.qh
qcsrc/lib/warpzone/client.qc
qcsrc/lib/warpzone/common.qc
qcsrc/menu/skin-customizables.inc
qcsrc/menu/xonotic/_mod.inc
qcsrc/menu/xonotic/_mod.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc
qcsrc/menu/xonotic/dialog_multiplayer_profile.qc
qcsrc/menu/xonotic/dialog_settings_game_view.qc
qcsrc/menu/xonotic/dialog_settings_game_weapons.qc
qcsrc/menu/xonotic/dialog_settings_misc.qc
qcsrc/menu/xonotic/dialog_settings_user.qc
qcsrc/menu/xonotic/dialog_singleplayer.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/statslist.qc
qcsrc/server/antilag.qc
qcsrc/server/antilag.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/api.qh
qcsrc/server/bot/default/bot.qc
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/havocbot/roles.qh
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/navigation.qh
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/default/waypoints.qh
qcsrc/server/bot/null/bot_null.qc
qcsrc/server/cheats.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/command/cmd.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/sv_cmd.qh
qcsrc/server/command/vote.qc
qcsrc/server/compat/quake3.qc
qcsrc/server/constants.qh
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_hook.qh
qcsrc/server/g_world.qc
qcsrc/server/impulse.qc
qcsrc/server/ipban.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
qcsrc/server/player.qc
qcsrc/server/race.qc
qcsrc/server/race.qh
qcsrc/server/spawnpoints.qc
qcsrc/server/steerlib.qc
qcsrc/server/sv_main.qc
qcsrc/server/sv_main.qh
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/tracing.qh
qcsrc/server/weapons/weaponsystem.qc
ruleset-XDF.cfg
ruleset-XPM.cfg
ruleset-overkill.cfg
sound/misc/armor1.ogg [new file with mode: 0644]
sound/misc/armor1.wav [deleted file]
sound/misc/armor10.ogg [new file with mode: 0644]
sound/misc/armor10.wav [deleted file]
sound/misc/armor17_5.ogg [new file with mode: 0644]
sound/misc/armor17_5.wav [deleted file]
sound/misc/armor25.ogg [new file with mode: 0644]
sound/misc/armor25.wav [deleted file]
sound/misc/armorimpact.ogg [new file with mode: 0644]
sound/misc/armorimpact.wav [deleted file]
sound/misc/footstep01.ogg [new file with mode: 0644]
sound/misc/footstep01.wav [deleted file]
sound/misc/footstep02.ogg [new file with mode: 0644]
sound/misc/footstep02.wav [deleted file]
sound/misc/footstep03.ogg [new file with mode: 0644]
sound/misc/footstep03.wav [deleted file]
sound/misc/footstep04.ogg [new file with mode: 0644]
sound/misc/footstep04.wav [deleted file]
sound/misc/footstep05.ogg [new file with mode: 0644]
sound/misc/footstep05.wav [deleted file]
sound/misc/footstep06.ogg [new file with mode: 0644]
sound/misc/footstep06.wav [deleted file]
sound/misc/gib.ogg [new file with mode: 0644]
sound/misc/gib.wav [deleted file]
sound/misc/gib_splat01.ogg [new file with mode: 0644]
sound/misc/gib_splat01.wav [deleted file]
sound/misc/gib_splat02.ogg [new file with mode: 0644]
sound/misc/gib_splat02.wav [deleted file]
sound/misc/gib_splat03.ogg [new file with mode: 0644]
sound/misc/gib_splat03.wav [deleted file]
sound/misc/gib_splat04.ogg [new file with mode: 0644]
sound/misc/gib_splat04.wav [deleted file]
sound/misc/hitground1.ogg
sound/misc/hitground2.ogg
sound/misc/hitground3.ogg
sound/misc/hitground4.ogg
sound/misc/itempickup.ogg
sound/misc/itemrespawn.ogg
sound/misc/mediumhealth.ogg
sound/misc/megahealth.ogg
sound/misc/metalhitground1.ogg
sound/misc/metalhitground2.ogg
sound/misc/metalhitground3.ogg
sound/misc/metalhitground4.ogg
sound/misc/minihealth.ogg
sound/misc/missile_fly.ogg [new file with mode: 0644]
sound/misc/missile_fly.wav [deleted file]
sound/misc/poweroff.ogg [new file with mode: 0644]
sound/misc/poweroff.wav [deleted file]
sound/misc/powerup.ogg
sound/misc/powerup_shield.ogg
sound/misc/shield_respawn.ogg [new file with mode: 0644]
sound/misc/shield_respawn.wav [deleted file]
sound/misc/spawn.ogg
sound/misc/strength_respawn.ogg [new file with mode: 0644]
sound/misc/strength_respawn.wav [deleted file]
sound/misc/teleport.ogg
sound/misc/typehit.ogg [new file with mode: 0644]
sound/misc/typehit.wav [deleted file]
sound/nexball/bounce.ogg
sound/nexball/drop.ogg
sound/weapons/crylink_fire.ogg
sound/weapons/crylink_fire2.ogg
sound/weapons/crylink_impact.ogg
sound/weapons/crylink_impact2.ogg
sound/weapons/electro_fire.ogg
sound/weapons/electro_fire2.ogg
sound/weapons/electro_impact_combo.ogg
sound/weapons/fireball_fire.ogg [new file with mode: 0644]
sound/weapons/fireball_fire.wav [deleted file]
sound/weapons/fireball_fire2.ogg [new file with mode: 0644]
sound/weapons/fireball_fire2.wav [deleted file]
sound/weapons/fireball_fly.ogg
sound/weapons/fireball_fly2.ogg
sound/weapons/fireball_impact2.ogg [new file with mode: 0644]
sound/weapons/fireball_impact2.wav [deleted file]
sound/weapons/fireball_prefire2.ogg [new file with mode: 0644]
sound/weapons/fireball_prefire2.wav [deleted file]
sound/weapons/grenade_impact.ogg
sound/weapons/hagar_fire.ogg
sound/weapons/hook_impact.ogg
sound/weapons/hookbomb_fire.ogg
sound/weapons/lasergun_fire.ogg
sound/weapons/minstanexfire.ogg
sound/weapons/missile_fly.ogg [new file with mode: 0644]
sound/weapons/nexfire.ogg
sound/weapons/neximpact.ogg
sound/weapons/nexwhoosh1.ogg
sound/weapons/nexwhoosh2.ogg
sound/weapons/nexwhoosh3.ogg
sound/weapons/reload.ogg
sound/weapons/rocket_fire.ogg
sound/weapons/rocket_impact.ogg
sound/weapons/rocket_mode.ogg
sound/weapons/shotgun_fire.ogg
sound/weapons/shotgun_melee.ogg
sound/weapons/strength_fire.ogg
sound/weapons/unavailable.ogg [new file with mode: 0644]
sound/weapons/unavailable.wav [deleted file]
sound/weapons/uzi_fire.ogg
sound/weapons/weapon_switch.ogg
sound/weapons/weaponpickup.ogg
textures/erebusfullbright.tga
textures/erebusfullbright_gloss.tga
textures/erebusfullbright_reflect.tga
textures/erebusfullbright_shirt.tga
textures/nyxfullbright.tga
textures/nyxfullbright_gloss.tga
textures/nyxfullbright_glow.tga
textures/nyxfullbright_reflect.tga
textures/nyxfullbright_shirt.tga
vehicles.cfg
wpeditor.txt [new file with mode: 0644]
xonotic-client.cfg
xonotic-common.cfg
xonotic-server.cfg

index 81af16137d5ca6d759caf2ff94c2c7830e6f8a2f..8724d06617940c0ed8cf76c67ad0fc94a25cb5a9 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=6e591fe90a6b90e62fdfd531636dd6eb
+    - EXPECT=892e447048e051e51f30cff2affc729a
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
@@ -56,6 +56,9 @@ test_sv_unit:
       done < <(${ENGINE} +developer 1 +map gitlab-ci +sv_cmd runtest +exit)
     - exit 1
 
+# NOTE: The generated docs are incomplete - they don't contain code behind SVQC CSQC MENUQC GAMEQC ifdefs.
+# With them added to PREDEFINED, it would take over half an hour to generate the docs and even then
+# they might not be complete. Doxygen doesn't handle #elif and might not understand some QC definitions.
 doxygen:  # rename to 'pages' when gitlab.com allows pages to exceed 100MiB
   stage: deploy
   script:
index c0a2b39ecd916bb1931cac412e76147f2a9c1cb0..67a023d4c8fb61a4e1b494e3b59c6d9a00a4f553 100644 (file)
@@ -1 +1 @@
-Mon Jul 15 07:24:31 CEST 2019
+Thu Sep 12 07:24:50 CEST 2019
index 9c29d18921f3d8862b2c4d79ad5a74ae7d23da51..c860be99cebd39ff846ded8cba3cdcbc790fb8b9 100644 (file)
@@ -117,7 +117,7 @@ seta hud_panel_scoreboard_minwidth 0.6 "minimum width of the scoreboard"
 
 seta hud_panel_scoreboard_accuracy_showdelay 2 "how long to delay displaying accuracy below the scoreboard if it's too far down"
 seta hud_panel_scoreboard_accuracy_showdelay_minpos 0.75 "delay displaying the accuracy panel only if its position is lower than this percentage of the screen height from the top"
-seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = do not show, 1 = left of scoreboard, 2 = right of scoreboard, and move team scores to the right)"
+seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = do not show, 1 = left of scoreboard, 2 = right of scoreboard), will move team scores to the other side if necessary"
 
 // hud panel aliases
 alias quickmenu "cl_cmd hud quickmenu ${* ?}"
index 45a75349be2cfba6658cd4199f6a25aba847350c..d3270acc83acd29cf991d547f282a43eaa3c0482 100644 (file)
@@ -2,9 +2,9 @@
 set g_balance_blaster_primary_animtime 0.2
 set g_balance_blaster_primary_damage 20
 set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 12.5
-set g_balance_blaster_primary_force 300
-set g_balance_blaster_primary_force_zscale 1.25
+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
@@ -16,8 +16,8 @@ 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 300
-set g_balance_blaster_secondary_force_zscale 1.2
+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
@@ -43,6 +43,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
@@ -56,8 +58,6 @@ 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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
 set g_balance_shotgun_switchdelay_drop 0.2
 set g_balance_shotgun_switchdelay_raise 0.2
 set g_balance_shotgun_weaponreplace ""
@@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #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_speed 0
+set g_balance_machinegun_burst_spread 0.02
 set g_balance_machinegun_first 1
 set g_balance_machinegun_first_ammo 1
 set g_balance_machinegun_first_damage 14
@@ -260,8 +260,8 @@ 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 10
-set g_balance_crylink_secondary_edgedamage 5
+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
@@ -278,7 +278,7 @@ set g_balance_crylink_secondary_other_lifetime 2
 set g_balance_crylink_secondary_radius 100
 set g_balance_crylink_secondary_refire 0.65
 set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_speed 7000
+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
@@ -290,6 +290,7 @@ set g_balance_crylink_weaponthrowable 1
 // }}}
 // {{{ #8: Vortex
 set g_balance_vortex_charge 0
+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
@@ -400,6 +401,7 @@ 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
@@ -447,7 +449,8 @@ 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 400
+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
@@ -678,7 +681,7 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
 set g_balance_shockwave_blast_animtime 0.3
 set g_balance_shockwave_blast_damage 40
 set g_balance_shockwave_blast_distance 1000
@@ -745,12 +748,7 @@ 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_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_beam_heat 0
-set g_balance_arc_burst_heat 5
 set g_balance_arc_beam_maxangle 10
 set g_balance_arc_beam_nonplayerdamage 80
 set g_balance_arc_beam_range 1500
@@ -773,6 +771,11 @@ 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 ""
@@ -780,12 +783,12 @@ set g_balance_arc_weaponstart 0
 set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #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 32
+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
@@ -796,7 +799,8 @@ 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 300
+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
@@ -811,79 +815,12 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
-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 300
-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
-// }}}
-// {{{ Overkill Shotgun
-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 300
-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
-// }}}
-// {{{ Overkill Machine Gun
+// {{{ #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 63
+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
@@ -893,7 +830,8 @@ 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 300
+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
@@ -908,7 +846,7 @@ set g_balance_okmachinegun_weaponstart 0
 set g_balance_okmachinegun_weaponstartoverride -1
 set g_balance_okmachinegun_weaponthrowable 1
 // }}}
-// {{{ Overkill Nex
+// {{{ #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
@@ -943,13 +881,14 @@ 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_force 300
-set g_balance_oknex_secondary_refire 0.7
-set g_balance_oknex_secondary_refire_type 1
 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
@@ -960,3 +899,72 @@ 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 b1a83000f6f41d18345045cfd9d7b44c9c41442f..c9d87fd0578f32daff8750b19727a8e76d2006dc 100644 (file)
@@ -43,6 +43,8 @@ set g_balance_shotgun_primary_spread 0.07
 set g_balance_shotgun_reload_ammo 0
 set g_balance_shotgun_reload_time 2
 set g_balance_shotgun_secondary 2
+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 80
 set g_balance_shotgun_secondary_force 200
@@ -56,8 +58,6 @@ 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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
 set g_balance_shotgun_switchdelay_drop 0.15
 set g_balance_shotgun_switchdelay_raise 0.15
 set g_balance_shotgun_weaponreplace ""
@@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
 set g_balance_machinegun_burst 0
 set g_balance_machinegun_burst_ammo 3
 set g_balance_machinegun_burst_animtime 0.75
 set g_balance_machinegun_burst_refire 0.05
 set g_balance_machinegun_burst_refire2 0.75
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0.04
 set g_balance_machinegun_first 1
 set g_balance_machinegun_first_ammo 1
 set g_balance_machinegun_first_damage 30
@@ -290,6 +290,7 @@ set g_balance_crylink_weaponthrowable 1
 // }}}
 // {{{ #8: Vortex
 set g_balance_vortex_charge 0
+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
@@ -345,7 +346,7 @@ set g_balance_hagar_primary_lifetime 30
 set g_balance_hagar_primary_radius 65
 set g_balance_hagar_primary_refire 0.15
 set g_balance_hagar_primary_speed 3000
-set g_balance_hagar_primary_spread 0.010
+set g_balance_hagar_primary_spread 0.01
 set g_balance_hagar_reload_ammo 0
 set g_balance_hagar_reload_time 2
 set g_balance_hagar_secondary 1
@@ -400,9 +401,10 @@ set g_balance_devastator_reload_time 2
 set g_balance_devastator_remote_damage 105
 set g_balance_devastator_remote_edgedamage 40
 set g_balance_devastator_remote_force 600
+set g_balance_devastator_remote_jump 0
 set g_balance_devastator_remote_jump_damage 70
 set g_balance_devastator_remote_jump_force 0
-set g_balance_devastator_remote_jump_radius 0
+set g_balance_devastator_remote_jump_radius 100
 set g_balance_devastator_remote_jump_velocity_z_add 400
 set g_balance_devastator_remote_jump_velocity_z_max 1500
 set g_balance_devastator_remote_jump_velocity_z_min 400
@@ -448,6 +450,7 @@ 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 400
+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
@@ -678,7 +681,7 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
 set g_balance_shockwave_blast_animtime 0.3
 set g_balance_shockwave_blast_damage 20
 set g_balance_shockwave_blast_distance 1000
@@ -745,12 +748,7 @@ set g_balance_arc_beam_healing_amax 100
 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_cooldown 2.5
-set g_balance_arc_cooldown_release 1
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
 set g_balance_arc_beam_heat 1
-set g_balance_arc_burst_heat 3
 set g_balance_arc_beam_maxangle 10
 set g_balance_arc_beam_nonplayerdamage 80
 set g_balance_arc_beam_range 1000
@@ -773,6 +771,11 @@ set g_balance_arc_burst_ammo 15
 set g_balance_arc_burst_damage 150
 set g_balance_arc_burst_healing_aps 100
 set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 3
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
 set g_balance_arc_switchdelay_drop 0.3
 set g_balance_arc_switchdelay_raise 0.3
 set g_balance_arc_weaponreplace ""
@@ -780,12 +783,12 @@ set g_balance_arc_weaponstart 0
 set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #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 32
+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
@@ -796,7 +799,8 @@ 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 300
+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
@@ -811,7 +815,91 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #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
@@ -832,7 +920,8 @@ 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 300
+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
@@ -847,3 +936,35 @@ 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 e4fb02236970cee908be2baa272f346c651711a5..74dd683c1d53be054daef7598fd9c2d60a2f42eb 100644 (file)
@@ -1,5 +1,6 @@
 // This config file is for overkill weapons that were nerfed to have the same
 // stats as vanilla weapons, secondary attack uses stats of vanilla blaster.
+// Secondary is actually inconsistent, see https://gitlab.com/xonotic/xonotic-data.pk3dir/issues/2258
 
 // {{{ Overkill Shotgun
 set g_balance_okshotgun_primary_ammo 1
@@ -18,6 +19,7 @@ set g_balance_okshotgun_secondary_damage 20
 set g_balance_okshotgun_secondary_delay 0
 set g_balance_okshotgun_secondary_edgedamage 10
 set g_balance_okshotgun_secondary_force 300
+set g_balance_okshotgun_secondary_force_zscale 1
 set g_balance_okshotgun_secondary_lifetime 5
 set g_balance_okshotgun_secondary_radius 60
 set g_balance_okshotgun_secondary_refire 0.7
@@ -48,6 +50,7 @@ set g_balance_okmachinegun_secondary_damage 20
 set g_balance_okmachinegun_secondary_delay 0
 set g_balance_okmachinegun_secondary_edgedamage 10
 set g_balance_okmachinegun_secondary_force 300
+set g_balance_okmachinegun_secondary_force_zscale 1
 set g_balance_okmachinegun_secondary_lifetime 5
 set g_balance_okmachinegun_secondary_radius 60
 set g_balance_okmachinegun_secondary_refire 0.7
@@ -98,6 +101,7 @@ 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_force 0
+set g_balance_oknex_secondary_force_zscale 1
 set g_balance_oknex_secondary_refire 0
 set g_balance_oknex_secondary_refire_type 0
 set g_balance_oknex_secondary_delay 0
index 1816f3f2e921ce4de93ceabcc2bad978861fcdd4..e32b54ff4b17e3851896ec7a40839484b1be136c 100644 (file)
@@ -4,6 +4,7 @@ set g_balance_blaster_primary_damage 25
 set g_balance_blaster_primary_delay 0
 set g_balance_blaster_primary_edgedamage 12.5
 set g_balance_blaster_primary_force 300
+set g_balance_blaster_primary_force_zscale 1
 set g_balance_blaster_primary_lifetime 5
 set g_balance_blaster_primary_radius 70
 set g_balance_blaster_primary_refire 0.7
@@ -16,6 +17,7 @@ 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 300
+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
@@ -29,64 +31,47 @@ set g_balance_blaster_weaponstart 1
 set g_balance_blaster_weaponstartoverride -1
 set g_balance_blaster_weaponthrowable 0
 // }}}
-// {{{ #2: Shockwave
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 20
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 200
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 2
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 300
-set g_balance_shockwave_blast_jump_force_velocitybias 0
-set g_balance_shockwave_blast_jump_force_zscale 1.25
-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.5
-set g_balance_shockwave_blast_multiplier_distance 0.5
-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 1
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_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 14
+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 80
+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 0
+set g_balance_shotgun_weaponstartoverride -1
+set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #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_speed 0
+set g_balance_machinegun_burst_spread 0.02
 set g_balance_machinegun_first 1
 set g_balance_machinegun_first_ammo 1
 set g_balance_machinegun_first_damage 14
@@ -243,58 +228,7 @@ set g_balance_electro_weaponstart 0
 set g_balance_electro_weaponstartoverride -1
 set g_balance_electro_weaponthrowable 1
 // }}}
-// {{{ #7: Arc
-set g_balance_arc_beam_ammo 0
-set g_balance_arc_beam_animtime 0.2
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 150
-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 2000
-set g_balance_arc_beam_healing_amax 200
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 200
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1000
-set g_balance_arc_beam_refire 0.5
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.5
-set g_balance_arc_bolt 0
-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 100
-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 2200
-set g_balance_arc_bolt_spread 0.03
-set g_balance_arc_burst_ammo 0
-set g_balance_arc_burst_damage 500
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 1
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
-set g_balance_arc_beam_heat 1
-set g_balance_arc_burst_heat 5
-set g_balance_arc_switchdelay_drop 0.3
-set g_balance_arc_switchdelay_raise 0.3
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
-// {{{ #8: Crylink
+// {{{ #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
@@ -354,8 +288,9 @@ set g_balance_crylink_weaponstart 0
 set g_balance_crylink_weaponstartoverride -1
 set g_balance_crylink_weaponthrowable 1
 // }}}
-// {{{ #9: Vortex
+// {{{ #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
@@ -400,7 +335,7 @@ set g_balance_vortex_weaponstart 0
 set g_balance_vortex_weaponstartoverride -1
 set g_balance_vortex_weaponthrowable 1
 // }}}
-// {{{ #10: Hagar
+// {{{ #9: Hagar
 set g_balance_hagar_primary_ammo 1
 set g_balance_hagar_primary_damage 25
 set g_balance_hagar_primary_damageforcescale 0
@@ -444,7 +379,7 @@ set g_balance_hagar_weaponstart 0
 set g_balance_hagar_weaponstartoverride -1
 set g_balance_hagar_weaponthrowable 1
 // }}}
-// {{{ #11: Devastator
+// {{{ #10: Devastator
 set g_balance_devastator_ammo 4
 set g_balance_devastator_animtime 0.4
 set g_balance_devastator_damage 70
@@ -466,6 +401,7 @@ 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 400
+set g_balance_devastator_remote_jump 0
 set g_balance_devastator_remote_jump_damage 40
 set g_balance_devastator_remote_jump_force 0
 set g_balance_devastator_remote_jump_radius 200
@@ -483,7 +419,7 @@ set g_balance_devastator_weaponstart 0
 set g_balance_devastator_weaponstartoverride -1
 set g_balance_devastator_weaponthrowable 1
 // }}}
-// {{{ #12: Port-O-Launch
+// {{{ #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
@@ -500,7 +436,7 @@ set g_balance_porto_weaponstart 0
 set g_balance_porto_weaponstartoverride -1
 set g_balance_porto_weaponthrowable 1
 // }}}
-// {{{ #13: Vaporizer
+// {{{ #12: Vaporizer
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
@@ -514,6 +450,7 @@ 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 400
+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
@@ -527,7 +464,7 @@ set g_balance_vaporizer_weaponstart 0
 set g_balance_vaporizer_weaponstartoverride -1
 set g_balance_vaporizer_weaponthrowable 0
 // }}}
-// {{{ #14: Grappling Hook
+// {{{ #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
@@ -554,7 +491,7 @@ set g_balance_hook_weaponstart 0
 set g_balance_hook_weaponstartoverride -1
 set g_balance_hook_weaponthrowable 1
 // }}}
-// {{{ #15: Heavy Laser Assault Cannon (MUTATOR WEAPON)
+// {{{ #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
@@ -590,7 +527,7 @@ set g_balance_hlac_weaponstart 0
 set g_balance_hlac_weaponstartoverride -1
 set g_balance_hlac_weaponthrowable 1
 // }}}
-// {{{ #16: @!#%'n Tuba
+// {{{ #15: @!#%'n Tuba
 set g_balance_tuba_animtime 0.05
 set g_balance_tuba_attenuation 0.5
 set g_balance_tuba_damage 5
@@ -608,7 +545,7 @@ set g_balance_tuba_weaponstart 0
 set g_balance_tuba_weaponstartoverride -1
 set g_balance_tuba_weaponthrowable 1
 // }}}
-// {{{ #17: Rifle (MUTATOR WEAPON)
+// {{{ #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
@@ -643,7 +580,7 @@ set g_balance_rifle_weaponstart 0
 set g_balance_rifle_weaponstartoverride -1
 set g_balance_rifle_weaponthrowable 1
 // }}}
-// {{{ #18: Fireball
+// {{{ #17: Fireball
 set g_balance_fireball_primary_animtime 0.2
 set g_balance_fireball_primary_bfgdamage 100
 set g_balance_fireball_primary_bfgforce 0
@@ -684,7 +621,7 @@ set g_balance_fireball_weaponstart 0
 set g_balance_fireball_weaponstartoverride -1
 set g_balance_fireball_weaponthrowable 0
 // }}}
-// {{{ #19: T.A.G. Seeker (MUTATOR WEAPON)
+// {{{ #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
@@ -744,46 +681,114 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #20: Shotgun (MUTATOR WEAPON)
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 14
-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_animtime 1.15
-set g_balance_shotgun_secondary_damage 80
-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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
-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 0
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
+// {{{ #19: Shockwave
+set g_balance_shockwave_blast_animtime 0.3
+set g_balance_shockwave_blast_damage 20
+set g_balance_shockwave_blast_distance 1000
+set g_balance_shockwave_blast_edgedamage 0
+set g_balance_shockwave_blast_force 200
+set g_balance_shockwave_blast_force_forwardbias 50
+set g_balance_shockwave_blast_force_zscale 2
+set g_balance_shockwave_blast_jump_damage 20
+set g_balance_shockwave_blast_jump_edgedamage 0
+set g_balance_shockwave_blast_jump_force 300
+set g_balance_shockwave_blast_jump_force_velocitybias 0
+set g_balance_shockwave_blast_jump_force_zscale 1.25
+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.5
+set g_balance_shockwave_blast_multiplier_distance 0.5
+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 1
+set g_balance_shockwave_weaponstartoverride -1
+set g_balance_shockwave_weaponthrowable 0
+// }}}
+// {{{ #20: Arc
+set g_balance_arc_beam_ammo 0
+set g_balance_arc_beam_animtime 0.2
+set g_balance_arc_beam_botaimlifetime 0
+set g_balance_arc_beam_botaimspeed 0
+set g_balance_arc_beam_damage 150
+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 2000
+set g_balance_arc_beam_healing_amax 200
+set g_balance_arc_beam_healing_aps 50
+set g_balance_arc_beam_healing_hmax 200
+set g_balance_arc_beam_healing_hps 50
+set g_balance_arc_beam_heat 1
+set g_balance_arc_beam_maxangle 10
+set g_balance_arc_beam_nonplayerdamage 80
+set g_balance_arc_beam_range 1000
+set g_balance_arc_beam_refire 0.5
+set g_balance_arc_beam_returnspeed 8
+set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+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 100
+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 2200
+set g_balance_arc_bolt_spread 0.03
+set g_balance_arc_burst_ammo 0
+set g_balance_arc_burst_damage 500
+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 1
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
+set g_balance_arc_switchdelay_drop 0.3
+set g_balance_arc_switchdelay_raise 0.3
+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
+// {{{ #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 32
+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
@@ -794,7 +799,8 @@ 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 300
+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
@@ -809,7 +815,91 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #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
@@ -830,7 +920,8 @@ 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 300
+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
@@ -845,3 +936,35 @@ 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
+// }}}
diff --git a/bal-wep-testing.cfg b/bal-wep-testing.cfg
new file mode 100644 (file)
index 0000000..c1cb576
--- /dev/null
@@ -0,0 +1,970 @@
+// {{{ #1: Blaster
+set g_balance_blaster_primary_animtime 0.2
+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.2
+set g_balance_blaster_switchdelay_raise 0.2
+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 63
+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_explode 1
+set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_radius 0
+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 0
+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 65
+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
+// }}}
diff --git a/bal-wep-testingxpm.cfg b/bal-wep-testingxpm.cfg
new file mode 100644 (file)
index 0000000..3bfe7a7
--- /dev/null
@@ -0,0 +1,970 @@
+// {{{ #1: Blaster
+set g_balance_blaster_primary_animtime 0.2
+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.2
+set g_balance_blaster_switchdelay_raise 0.2
+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 63
+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_explode 1
+set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_radius 0
+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 0
+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 65
+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 1000
+set g_balance_arc_beam_refire 0.25
+set g_balance_arc_beam_returnspeed 8
+set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+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 13bdc529a9f7364e36ce66ec85b596732e2b0f7b..1fe4044cab7f25ce1e1a624e1c895680224ed668 100644 (file)
@@ -3,8 +3,8 @@ set g_balance_blaster_primary_animtime 0.2
 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 300
-set g_balance_blaster_primary_force_zscale 1.25
+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
@@ -16,8 +16,8 @@ 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 300
-set g_balance_blaster_secondary_force_zscale 1.2
+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
@@ -43,6 +43,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
@@ -56,8 +58,6 @@ 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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
 set g_balance_shotgun_switchdelay_drop 0
 set g_balance_shotgun_switchdelay_raise 0
 set g_balance_shotgun_weaponreplace ""
@@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #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_speed 0
+set g_balance_machinegun_burst_spread 0.03
 set g_balance_machinegun_first 1
 set g_balance_machinegun_first_ammo 1
 set g_balance_machinegun_first_damage 14
@@ -290,6 +290,7 @@ set g_balance_crylink_weaponthrowable 1
 // }}}
 // {{{ #8: Vortex
 set g_balance_vortex_charge 0
+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
@@ -400,9 +401,10 @@ 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 350
+set g_balance_devastator_remote_jump 0
 set g_balance_devastator_remote_jump_damage 70
 set g_balance_devastator_remote_jump_force 450
-set g_balance_devastator_remote_jump_radius 0
+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
@@ -447,7 +449,8 @@ 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 400
+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
@@ -678,7 +681,7 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
 set g_balance_shockwave_blast_animtime 0.3
 set g_balance_shockwave_blast_damage 40
 set g_balance_shockwave_blast_distance 1000
@@ -745,12 +748,7 @@ 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_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_beam_heat 0
-set g_balance_arc_burst_heat 5
 set g_balance_arc_beam_maxangle 10
 set g_balance_arc_beam_nonplayerdamage 80
 set g_balance_arc_beam_range 1000
@@ -773,6 +771,11 @@ 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
 set g_balance_arc_switchdelay_raise 0
 set g_balance_arc_weaponreplace ""
@@ -780,12 +783,12 @@ set g_balance_arc_weaponstart 0
 set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #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 32
+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
@@ -796,7 +799,8 @@ 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 300
+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
@@ -811,7 +815,91 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #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
@@ -832,7 +920,8 @@ 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 300
+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
@@ -847,3 +936,35 @@ 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 5c6ace7abd7c6649f82b9998570e562154431a8e..52d63dfa2bbcd26332d1d551b05778f8a536cd67 100644 (file)
@@ -3,8 +3,8 @@ set g_balance_blaster_primary_animtime 0.2
 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 300
-set g_balance_blaster_primary_force_zscale 1.25
+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
@@ -16,8 +16,8 @@ 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 300
-set g_balance_blaster_secondary_force_zscale 1.2
+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
@@ -43,6 +43,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
@@ -56,8 +58,6 @@ 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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
 set g_balance_shotgun_switchdelay_drop 0.2
 set g_balance_shotgun_switchdelay_raise 0.2
 set g_balance_shotgun_weaponreplace ""
@@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #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_speed 0
+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
@@ -290,6 +290,7 @@ 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
@@ -400,9 +401,10 @@ 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 0
 set g_balance_devastator_remote_jump_damage 70
 set g_balance_devastator_remote_jump_force 450
-set g_balance_devastator_remote_jump_radius 0
+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
@@ -447,7 +449,8 @@ 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 400
+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
@@ -678,7 +681,7 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
 set g_balance_shockwave_blast_animtime 0.3
 set g_balance_shockwave_blast_damage 40
 set g_balance_shockwave_blast_distance 1000
@@ -745,12 +748,7 @@ 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_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_beam_heat 0
-set g_balance_arc_burst_heat 5
 set g_balance_arc_beam_maxangle 10
 set g_balance_arc_beam_nonplayerdamage 80
 set g_balance_arc_beam_range 1500
@@ -773,6 +771,11 @@ 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 ""
@@ -780,12 +783,12 @@ set g_balance_arc_weaponstart 0
 set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #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 32
+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
@@ -796,7 +799,8 @@ 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 300
+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
@@ -811,79 +815,12 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
-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 300
-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
-// }}}
-// {{{ Overkill Shotgun
-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 300
-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
-// }}}
-// {{{ Overkill Machine Gun
+// {{{ #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 63
+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
@@ -893,7 +830,8 @@ 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 300
+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
@@ -908,7 +846,7 @@ set g_balance_okmachinegun_weaponstart 0
 set g_balance_okmachinegun_weaponstartoverride -1
 set g_balance_okmachinegun_weaponthrowable 1
 // }}}
-// {{{ Overkill Nex
+// {{{ #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
@@ -943,13 +881,14 @@ 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_force 300
-set g_balance_oknex_secondary_refire 0.7
-set g_balance_oknex_secondary_refire_type 1
 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
@@ -960,3 +899,72 @@ 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 a5438d1b7c65a39ebe33f27da62dfb47e3c5e359..91743112acb1f23602f9dbcd05e79415f25e24d6 100644 (file)
@@ -3,8 +3,8 @@ set g_balance_blaster_primary_animtime 0.2
 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 300
-set g_balance_blaster_primary_force_zscale 1.25
+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
@@ -16,8 +16,8 @@ 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 300
-set g_balance_blaster_secondary_force_zscale 1.2
+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
@@ -43,6 +43,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
@@ -56,8 +58,6 @@ 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_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
 set g_balance_shotgun_switchdelay_drop 0.2
 set g_balance_shotgun_switchdelay_raise 0.2
 set g_balance_shotgun_weaponreplace ""
@@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
-// {{{ #3: Machine Gun
+// {{{ #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_speed 0
+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
@@ -290,6 +290,7 @@ 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
@@ -400,9 +401,10 @@ 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 0
 set g_balance_devastator_remote_jump_damage 70
 set g_balance_devastator_remote_jump_force 450
-set g_balance_devastator_remote_jump_radius 0
+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
@@ -447,7 +449,8 @@ 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 400
+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
@@ -678,7 +681,7 @@ set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 set g_balance_seeker_weaponthrowable 1
 // }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
 set g_balance_shockwave_blast_animtime 0.3
 set g_balance_shockwave_blast_damage 40
 set g_balance_shockwave_blast_distance 1000
@@ -745,12 +748,7 @@ 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_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_beam_heat 0
-set g_balance_arc_burst_heat 5
 set g_balance_arc_beam_maxangle 10
 set g_balance_arc_beam_nonplayerdamage 80
 set g_balance_arc_beam_range 1000
@@ -773,6 +771,11 @@ 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 ""
@@ -780,12 +783,12 @@ set g_balance_arc_weaponstart 0
 set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #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 32
+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
@@ -796,7 +799,8 @@ 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 300
+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
@@ -811,7 +815,91 @@ set g_balance_okhmg_weaponstart 0
 set g_balance_okhmg_weaponstartoverride 0
 set g_balance_okhmg_weaponthrowable 0
 // }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #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
@@ -832,7 +920,8 @@ 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 300
+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
@@ -847,3 +936,35 @@ 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 18d862d747808a987ea24b1946a8eb5b39c11096..0e929ee74009f8038dc864228374d0af17766eb5 100644 (file)
@@ -25,7 +25,7 @@ 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_armor 100
 set g_lms_start_ammo_shells 60
 set g_lms_start_ammo_nails 320
 set g_lms_start_ammo_rockets 160
@@ -131,7 +131,7 @@ set g_balance_pause_armor_rot 5
 set g_balance_pause_armor_rot_spawn 5
 set g_balance_armor_regenstable 100
 set g_balance_armor_rotstable 0
-set g_balance_armor_limit 200
+set g_balance_armor_limit 100
 set g_balance_armor_blockpercent 0.6
 set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
 set g_balance_fuel_regenlinear 0
diff --git a/balance-testing.cfg b/balance-testing.cfg
new file mode 100644 (file)
index 0000000..96426aa
--- /dev/null
@@ -0,0 +1,243 @@
+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_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
diff --git a/balance-testingxpm.cfg b/balance-testingxpm.cfg
new file mode 100644 (file)
index 0000000..7c2da46
--- /dev/null
@@ -0,0 +1,243 @@
+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_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-testingxpm.cfg
index 611f5da95a867d7be500d8caf38b8a84038f12e0..3bdf7909633a288625182623498ba8a4106bc8b7 100644 (file)
@@ -65,7 +65,6 @@ bind F10 menu_showquitdialog
 bind F11 disconnect
 bind F12 screenshot
 bind F4 ready
-bind ALT +showaccuracy
 
 // Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
 bind JOY1 "+crouch"
@@ -157,4 +156,4 @@ seta "userbind31_press" ""; seta "userbind31_release" ""; seta "userbind31_descr
 seta "userbind32_press" ""; seta "userbind32_release" ""; seta "userbind32_description" ""
 alias _userbind_call "${$1}"
 alias +userbind "_userbind_call userbind${1}_press"
-alias -userbind "_userbind_call userbind${1}_release"
\ No newline at end of file
+alias -userbind "_userbind_call userbind${1}_release"
index 798104a68c065d0d5dfd1c9265c02886f06c6237..88371f5e4c69e705f7211053ff967b2e603f09f2 100644 (file)
@@ -134,7 +134,7 @@ alias debugmodel           "qc_cmd_cl     debugmodel           ${* ?}" // Spawn
 alias hud                  "qc_cmd_cl     hud                  ${* ?}" // Commands regarding/controlling the HUD system
 alias localprint           "qc_cmd_cl     localprint           ${* ?}" // Create your own centerprint sent to yourself
 //alias mv_download        "qc_cmd_cl     mv_download          ${* ?}" // Retrieve mapshot picture from the server
-alias sendcvar             "qc_cmd_cl     sendcvar             ${* ?}" // Send a cvar to the server (like weaponpriority)
+alias sendcvar             "qc_cmd_cl     sendcvar             ${* ?}" // Send a cvar to the server (like cl_weaponpriority)
 alias weapon_find          "qc_cmd_cl     weapon_find          ${* ?}" // Show spawn locations of a weapon
 
 alias exit                 "quit"
@@ -146,9 +146,6 @@ alias radar "qc_cmd_cl hud radar ${* ?}"
 alias scoreboard_columns_help "qc_cmd_cl hud scoreboard_columns_help"
 alias scoreboard_columns_set "qc_cmd_cl hud scoreboard_columns_set ${* ?}"
 
-// changes a cvar and reports it to the server (for the client to notify the server about changes)
-alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\""
-
 
 // ========================================================
 //  cmd (client-to-server command) - server/command/cmd.qc
@@ -238,6 +235,8 @@ alias warp                 "qc_cmd_sv     warp                 ${* ?}" // Choose
 
 // other aliases for server commands
 alias endmatch "timelimit -1"
+alias bots "minplayers 4; minplayers_per_team 2"
+alias nobots "minplayers 0; minplayers_per_team 0"
 
 alias savedb "sv_cmd database save \"${1 ?}\""
 alias dumpdb "sv_cmd database dump \"${1 ?}\""
@@ -325,10 +324,10 @@ set sv_vote_command_help_gotomap "\nUsage:^3 vcall gotomap mapname\n^7  Where 'm
 // =================================
 set sv_vote_call 1 "Allow users to call a vote for the commands in sv_vote_commands"
 set sv_vote_change 1 "Allow voters to change their mind after already voting"
-set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams" "these commands can be voted"
+set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams bots nobots" "these commands can be voted"
 set sv_vote_only_commands ""
 set sv_vote_limit 160 "Maximum allowed length of a vote command"
-set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink movetospec " "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0)
+set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink movetospec" "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0)
 set sv_vote_master 0   "Allows the use of the vote master system"
 set sv_vote_master_callable 0 "When set, users can use \"vmaster\" to call a vote to become master of voting commands"
 set sv_vote_master_password "" "when set, users can use \"vlogin PASSWORD\" to log in as master"
@@ -375,4 +374,4 @@ alias vext "vcall extendmatchtime"
 //  rcon server commands
 // ======================
 rcon_secure 1
-set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoauto movetored movetoblue movetoyellow movetopink movetospec"
+set rcon_restricted_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams bots nobots movetored movetoblue movetoyellow movetopink movetospec kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\""
index 065db416ce5e8107fa5bd02ad91982deb1ec90d2..c1bc4112f28aae82580f9ce84c548f9307849c70 100644 (file)
@@ -18,7 +18,7 @@ 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-07-14 15:44+0000\n"
+"PO-Revision-Date: 2019-08-29 09:07+0000\n"
 "Last-Translator: Yannick Le Guen <leguen.yannick@gmail.com>\n"
 "Language-Team: French (http://www.transifex.com/team-xonotic/xonotic/"
 "language/fr/)\n"
@@ -143,7 +143,7 @@ msgstr "^1La partie a déjà commencé"
 
 #: qcsrc/client/hud/panel/infomessages.qc:128
 msgid "^1You have no more lives left"
-msgstr "^1Vous n'avez plus aucune vie"
+msgstr "^1Il ne vous reste plus aucune vie"
 
 #: qcsrc/client/hud/panel/infomessages.qc:130
 #: qcsrc/client/hud/panel/infomessages.qc:133
@@ -9289,7 +9289,7 @@ msgstr "Retourner la vue horizontalement"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:68
 msgid "Poor man's left handed mode"
-msgstr "Mode mirroir"
+msgstr "Mode miroir"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:71
 msgid "Anisotropy:"
index bb401e01bd103446cd117d76fffac92f371a5c5d..5ee89ac01adf346b3b72f99a1f2cff928f24b8b2 100644 (file)
@@ -5,13 +5,14 @@
 # Translators:
 # Çağlar Turalı <caglarturali@gmail.com>, 2018
 # Demiray Muhterem <mdemiray@msn.com>, 2018
+# ibra kap <ibrakap@gmail.com>, 2019
 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: 2019-09-11 17:17+0000\n"
+"Last-Translator: ibra kap <ibrakap@gmail.com>\n"
 "Language-Team: Turkish (http://www.transifex.com/team-xonotic/xonotic/"
 "language/tr/)\n"
 "Language: tr\n"
@@ -253,7 +254,7 @@ msgstr "Devam..."
 #: qcsrc/client/hud/panel/quickmenu.qc:781
 #: qcsrc/client/hud/panel/quickmenu.qc:788
 msgid "Chat"
-msgstr ""
+msgstr "Sohbet"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:782
 msgid "QMCMD^Send public message to"
@@ -488,7 +489,7 @@ msgstr ""
 
 #: qcsrc/client/hud/panel/quickmenu.qc:847
 msgid "QMCMD^Fullscreen"
-msgstr ""
+msgstr "Tam Ekran"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:850
 #: qcsrc/client/hud/panel/quickmenu.qc:860
index e7d502a567bca0b4ce816c5235f816af4038035f..5ba567a63fedb25c537293359e63654ae0a02e64 100644 (file)
@@ -18,8 +18,8 @@ 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-06-14 06:43+0000\n"
-"Last-Translator: Liang Liu <dxkliu@126.com>\n"
+"PO-Revision-Date: 2019-07-30 05:15+0000\n"
+"Last-Translator: 杜茂森 <dumaosen_main01@outlook.com>\n"
 "Language-Team: Chinese (China) (http://www.transifex.com/team-xonotic/"
 "xonotic/language/zh_CN/)\n"
 "Language: zh_CN\n"
@@ -394,11 +394,11 @@ msgstr "QMCMD^掉落武器, icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:806
 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
-msgstr ""
+msgstr "QMCMD^掉落武器 %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:807
 msgid "QMCMD^drop flag/key, icon"
-msgstr ""
+msgstr "QMCMD^掉落旗帜/钥匙, icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:807
 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
index 8e7bc9b4f74f414ac766859647221abbdf4ddd5b..47631f0fa6cb70b4a664e493ff5dd06bd300bfae 100644 (file)
@@ -34,7 +34,7 @@ seta crosshair_hitindication_speed 5
 set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)"
 seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur, _scale, and _showipact cvars"
 seta crosshair_hittest_blur 1 "blur the crosshair if the shot is obstructed"
-seta crosshair_hittest_scale 1.25 "enlarge crosshair if aiming at an enemy, shrink crosshair if shot is obstructed or aiming at a teammate"
+seta crosshair_hittest_scale 1.25 "shrink crosshair if shot is obstructed or aiming at a teammate"
 seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed"
 
 // change color based on special case
@@ -48,6 +48,10 @@ seta crosshair_per_weapon 1  "when 1, each gun will display a different crosshair
 // side-scrolling crosshair
 seta crosshair_2d 54 "selects crosshair to use in side-scrolling mode (\"\" uses regular crosshair and 0 is none)"
 
+// third person chase-camera crosshair
+seta crosshair_chase 1 "adjust the crosshair while in third person mode to where the shot will actually hit"
+seta crosshair_chase_playeralpha 0.25 "opacity of the player while they obstruct the view when crosshair_chase is enabled, can be a value between 0 and 1"
+
 
 // =========================
 //  Crosshair ring settings
index 57c9f7b7086f2c8ce25ff9f25cf475c2664c334c..60407396e37548aff421c8dbf804088890f51177 100644 (file)
@@ -74,19 +74,19 @@ alias sv_vote_gametype_hook_duel
 // this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
 set leadlimit 0
 set leadlimit_and_fraglimit 0 "if set, leadlimit is ANDed with fraglimit (otherwise ORed)"
-seta timelimit_override -1     "Time limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta fraglimit_override -1     "Frag limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta leadlimit_override -1     "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta capturelimit_override -1  "Capture limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta captureleadlimit_override -1      "Capture llead imit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_domination_point_limit -1       "Domination point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_domination_point_leadlimit -1   "Domination point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_keyhunt_point_limit -1  "Keyhunt point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_keyhunt_point_leadlimit -1      "Keyhunt point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_race_laps_limit -1      "Race laps limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_nexball_goallimit -1 "Nexball goal limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_nexball_goalleadlimit -1 "Nexball goal lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_invasion_point_limit -1 "Invasion point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set timelimit_override -1      "Time limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set fraglimit_override -1      "Frag limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set leadlimit_override -1      "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set capturelimit_override -1   "Capture limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set captureleadlimit_override -1       "Capture llead imit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_domination_point_limit -1        "Domination point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_domination_point_leadlimit -1    "Domination point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_keyhunt_point_limit -1   "Keyhunt point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_keyhunt_point_leadlimit -1       "Keyhunt point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_race_laps_limit -1       "Race laps limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_nexball_goallimit -1 "Nexball goal limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_nexball_goalleadlimit -1 "Nexball goal lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_invasion_point_limit -1 "Invasion point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 
 
 // =================================
@@ -217,15 +217,16 @@ set g_assault 0 "Assault: attack the enemy base as fast as you can, then defend
 //  clan arena
 // ============
 set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round"
-seta g_ca_point_limit -1 "Clan Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_ca_point_leadlimit -1 "Clan Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_ca_point_limit -1 "Clan Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_ca_point_leadlimit -1 "Clan Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 set g_ca_spectate_enemies 0 "Allow spectating enemy player by dead player during clan arena games"
 set g_ca_warmup 10 "how long the players will have time to run around the map before the round starts"
 set g_ca_damage2score_multiplier 0.01
 set g_ca_round_timelimit 180 "round time limit in seconds"
-seta g_ca_teams_override 0
+set g_ca_teams_override 0
 set g_ca_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
 set g_ca_teams 0
+set g_ca_weaponarena "most" "starting weapons - takes the same options as g_weaponarena"
 
 
 // ==================
@@ -238,7 +239,7 @@ set g_ctf_leaderboard 0 "show top capture times in the scoreboard"
 set g_ctf_flag_return 1 "auto return the flag to base when touched by a teammate"
 set g_ctf_flag_return_carrying 0 "(manual return mode) auto return the flag to base if touched by a flag carrier"
 set g_ctf_flag_return_carried_radius 100 "allow flags to be returned by carrier if base is within this radius"
-set g_ctf_flag_return_time 15 "automatically return the flag to base after this amount of time"
+set g_ctf_flag_return_time 30 "automatically return the flag to base after this amount of time"
 set g_ctf_flag_return_dropped 100 "automatically return the flag to base if dropped within this distance from base (in qu)"
 set g_ctf_flag_return_damage 0 "allow the flag to be damaged, reducing time needed to automatically return to base"
 set g_ctf_flag_return_damage_delay 0 "how much time the flag takes to automatically return to base if it falls into lava/slime/trigger hurt"
@@ -253,7 +254,7 @@ set g_ctf_stalemate 1 "show the enemy flagcarrier location after both teams have
 set g_ctf_stalemate_endcondition 1 "condition for stalemate mode to be finished: 1 = If ONE flag is no longer stale, 2 = If BOTH flags are no longer stale"
 set g_ctf_stalemate_time 60 "time for each flag until stalemate mode is activated"
 set g_ctf_flagcarrier_waypointforenemy_spotting 1 "show the enemy flagcarrier location if a team mate presses +use to spot them"
-set g_ctf_dropped_capture_delay 1 "dropped capture delay"
+set g_ctf_dropped_capture_delay 1.5 "autocapture delay when flag is thrown onto the base - counted from throw, not landing"
 set g_ctf_dropped_capture_radius 100 "allow dropped flags to be automatically captured by base flags if the dropped flag is within this radius of it"
 set g_ctf_flag_damageforcescale 2
 set g_ctf_portalteleport 0 "allow flag carriers to go through portals made in portal gun without dropping the flag"
@@ -307,7 +308,7 @@ set g_ctf_flag_glowtrails 1
 set g_ctf_fullbrightflags 0
 set g_ctf_dynamiclights 0
 
-seta g_ctf_ignore_frags 0      "1: regular frags give no points"
+set g_ctf_ignore_frags 0       "1: regular frags give no points"
 exec ctfscoring-samual.cfg
 
 
@@ -329,7 +330,7 @@ set g_tdm 0 "Team Deathmatch: the team who kills their opponents most often wins
 set g_tdm_on_dm_maps 0 "when this is set, all DM maps automatically support TDM"
 set g_tdm_teams 2 "how many teams are in team deathmatch (set by mapinfo)"
 set g_tdm_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
-seta g_tdm_teams_override 0    "how many teams are in team deathmatch"
+set g_tdm_teams_override 0     "how many teams are in team deathmatch"
 set g_tdm_point_limit -1 "TDM point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 set g_tdm_point_leadlimit -1 "TDM point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 
@@ -339,7 +340,7 @@ set g_tdm_point_leadlimit -1 "TDM point lead limit overriding the mapinfo specif
 // ============
 set g_domination                       0 "Domination: capture and hold control points to gain points"
 set g_domination_default_teams         2 "default number of teams for maps that aren't domination-specific"
-seta g_domination_teams_override               0 "use a specific number of teams in domination games (minimum 2), disables dom_team entities"
+set g_domination_teams_override                0 "use a specific number of teams in domination games (minimum 2), disables dom_team entities"
 set g_domination_disable_frags         0 "players can't get frags normally, only get points from kills"
 set g_domination_point_amt             0 "override: how many points to get per ping"
 set g_domination_point_fullbright      0 "domination point fullbright"
@@ -358,26 +359,27 @@ set g_domination_warmup 5
 // ===========
 set g_freezetag 0 "Freeze Tag: Freeze the opposing team(s) to win, unfreeze teammates by standing next to them"
 set g_freezetag_warmup 5 "Time players get to run around before the round starts"
-seta g_freezetag_point_limit -1        "Freeze Tag point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-seta g_freezetag_point_leadlimit -1    "Freeze Tag point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_freezetag_point_limit -1 "Freeze Tag point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_freezetag_point_leadlimit -1     "Freeze Tag point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 set g_freezetag_revive_speed 0.4 "Speed for reviving a frozen teammate"
 set g_freezetag_revive_clearspeed 1.6 "Speed at which reviving progress gets lost when out of range"
 set g_freezetag_revive_extra_size 100 "Distance in qu that you can stand from a frozen teammate to keep reviving him"
 set g_freezetag_revive_nade 1 "Enable reviving from own nade explosion"
 set g_freezetag_revive_nade_health 40 "Amount of health player has if they revived from their own nade explosion"
-set g_freezetag_round_timelimit 180 "round time limit in seconds"
+set g_freezetag_round_timelimit 360 "round time limit in seconds"
 set g_freezetag_frozen_maxtime 60 "frozen players will be automatically unfrozen after this time in seconds"
-seta g_freezetag_teams_override 0
+set g_freezetag_teams_override 0
 set g_freezetag_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
 set g_freezetag_teams 0
+set g_freezetag_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
 
 
 // ==========
 //  keepaway
 // ==========
 set g_keepaway 0 "game mode which focuses around a ball"
-set g_keepaway_score_bckill 1 "enable scoring points (y/n) for ball carrier kills (value is how many points to award)"
-set g_keepaway_score_killac 1 "amount of points to give when you kill someone while you have the ball"
+set g_keepaway_score_bckill 1 "points for killing the ball barrier (Ball Carrier Kill)"
+set g_keepaway_score_killac 1 "points for kills while holding the ball (Kill As Carrier)"
 set g_keepaway_score_timeinterval 1 "amount of time it takes between intervals for timepoints to be added to the score"
 set g_keepaway_score_timepoints 0 "points to add to score per timeinterval, 0 for no points"
 set g_keepaway_ballcarrier_effects 8 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
@@ -419,7 +421,7 @@ set g_balance_keyhunt_dropvelocity 300
 set g_balance_keyhunt_throwvelocity 400
 set g_balance_keyhunt_protecttime 0.8
 set g_balance_keyhunt_damageforcescale 1
-seta g_keyhunt_teams_override 0
+set g_keyhunt_teams_override 0
 set g_keyhunt_teams 0
 set g_keyhunt_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
 
@@ -433,6 +435,7 @@ set g_lms_extra_lives 0
 set g_lms_regenerate 0
 set g_lms_last_join 3  "if g_lms_join_anytime is false, new players can only join if the worst active player has more than (fraglimit - g_lms_last_join) lives"
 set g_lms_join_anytime 1       "if true, new players can join, but get same amount of lives as the worst player"
+set g_lms_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
 
 
 // =========
@@ -476,12 +479,12 @@ set g_nexball_football_trail    0  "1 to leave a trail"
 set g_nexball_trail_color     254  "1-256 for different colors (Quake palette, 254 is white)"
 set g_nexball_playerclip_collisions 1 "make the ball bounce off clips"
 set g_nexball_radar_showallplayers 1  "1: show every player and the ball on the radar  0: only show teammates and the ball on the radar"
-seta g_nexball_safepass_maxdist 5000 "Max distance to allow save fassping (0 to turn off safe passing)"
-seta g_nexball_safepass_turnrate 0.1 "How fast the safe-pass ball can habge direction"
-seta g_nexball_safepass_holdtime 0.75 "How long to remeber last teammate you pointed at"
-seta g_nexball_viewmodel_scale 0.25 "How large the ball for the carrier"
-seta g_nexball_viewmodel_offset "8 8 0" "Where the ball is located on carrier forward right up"
-seta g_nexball_tackling 1 "Allow ball theft?"
+set g_nexball_safepass_maxdist 5000 "Max distance to allow save fassping (0 to turn off safe passing)"
+set g_nexball_safepass_turnrate 0.1 "How fast the safe-pass ball can habge direction"
+set g_nexball_safepass_holdtime 0.75 "How long to remeber last teammate you pointed at"
+set g_nexball_viewmodel_scale 0.25 "How large the ball for the carrier"
+set g_nexball_viewmodel_offset "8 8 0" "Where the ball is located on carrier forward right up"
+set g_nexball_tackling 1 "Allow ball theft?"
 
 
 // ===========
@@ -542,3 +545,4 @@ set g_invasion_type 0 "type of invasion mode - 0: round-based, 1: hunting, 2: co
 set g_duel 0 "Duel: frag the opponent more in a one versus one arena battle"
 //set g_duel_warmup 180 "Have a short warmup period before beginning the actual duel"
 set g_duel_with_powerups 0 "Enable powerups to spawn in the duel gamemode"
+set g_duel_not_dm_maps 0 "when this is set, DM maps will NOT be listed in duel"
index 7a7cff67a422ee7d0eff9d109776cadcb5989896..dddb38ce094fbd87e21baf8c478484a8882e8723 100644 (file)
@@ -4,5 +4,5 @@ sight sound/monsters/zombie/sight 0
 //ranged sound/monsters/zombie/ranged 0
 //melee sound/monsters/zombie/melee 0
 //pain sound/monsters/zombie/pain 0
-spawn sound/monsters/zombie/spawn 0
+//spawn sound/monsters/zombie/spawn 0
 idle sound/monsters/zombie/idle 0
index 01e3a120a4285698382d3c408ef220b927bf87c8..0fcbed2f2e45e5e9b273b92f7b3e2175a5358907 100644 (file)
@@ -54,14 +54,14 @@ set g_instagib_friendlypush 1 "allow pushing teammates with the vaporizer primar
 // ==========
 //  overkill
 // ==========
-set g_overkill 0 "internal cvar, to enable overkill, use  `exec ruleset-overkill.cfg`"
+set g_overkill 0 "internal cvar, to enable overkill, use `exec ruleset-overkill.cfg`"
 set g_overkill_weapons 0 "Whether to enable overkill weapons outside of overkill ruleset."
 
-set g_overkill_powerups_replace 1
-set g_overkill_itemwaypoints 1
+set g_overkill_powerups_replace 1 "replace strength and shield with HMG and RPC"
+set g_overkill_itemwaypoints 1 "show waypoints with timer before health and armor spawns"
 set g_overkill_filter_healthmega 0
-set g_overkill_filter_armormedium 0
-set g_overkill_filter_armorbig 0
+set g_overkill_filter_armormedium 1
+set g_overkill_filter_armorbig 1
 set g_overkill_filter_armormega 0
 
 
@@ -111,6 +111,7 @@ set g_invincible_projectiles 0 "set to 1 to disable any damage to projectiles in
 //  rocket flying
 // ===============
 set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs"
+set g_rocket_flying_disabledelays 1 "disable detonation delays on rockets and mines"
 
 
 // =====================
@@ -302,8 +303,8 @@ set g_new_toys_use_pickupsound 0 "play the 'new toys, new toys!' roflsound when
 // =======
 //  buffs
 // =======
-set cl_buffs_autoreplace 1 "automatically drop current buff when picking up another"
-set g_buffs -1 "enable buffs (requires buff items or powerups)"
+seta cl_buffs_autoreplace 1 "automatically drop current buff when picking up another"
+set g_buffs -1 "enable buffs (requires buff items or powerups on the map)"
 set g_buffs_effects 1 "show particle effects from carried buffs"
 set g_buffs_waypoint_distance 1024 "maximum distance at which buff waypoint can be seen from item"
 set g_buffs_pickup_anyway 0 "instantly respawn the buff when it is picked up, instead of waiting for the player to drop it"
@@ -321,7 +322,7 @@ set g_buffs_ammo 1 "ammo buff: infinite ammunition"
 set g_buffs_ammo_time 60 "ammo buff carry time"
 set g_buffs_resistance 1 "resistance buff: greatly reduces damage taken"
 set g_buffs_resistance_time 60 "resistance buff time"
-set g_buffs_resistance_blockpercent 0.7 "damage reduction multiplier, higher values mean less damage"
+set g_buffs_resistance_blockpercent 0.5 "damage reduction multiplier, higher values mean less damage"
 set g_buffs_medic 1 "medic buff: increased regeneration speed, extra health, chance to survive a fatal attack"
 set g_buffs_medic_time 60 "medic buff carry time"
 set g_buffs_medic_survive_chance 0.6 "multiplier chance of player surviving a fatal hit"
@@ -334,7 +335,7 @@ set g_buffs_medic_heal_range 400 "furthest away players can be from carrier to g
 set g_buffs_medic_heal_delay 1 "delay between team healing"
 set g_buffs_vengeance 1 "vengeance buff: attackers also take damage"
 set g_buffs_vengeance_time 60 "vengeance buff carry time"
-set g_buffs_vengeance_damage_multiplier 0.6 "amount of damage dealt the attacker takes when hitting a target with vengeance"
+set g_buffs_vengeance_damage_multiplier 0.4 "amount of damage dealt the attacker takes when hitting a target with vengeance"
 set g_buffs_bash 1 "bash buff: increased knockback force and immunity to knockback"
 set g_buffs_bash_time 60 "bash buff carry time"
 set g_buffs_bash_force 2 "bash force multiplier"
@@ -354,7 +355,7 @@ set g_buffs_speed_damage_take 1.2 "damage taken multiplier, higher value means m
 set g_buffs_speed_regen 1.2 "regeneration speed multiplier, higher value means faster health regeneration while holding speed buff"
 set g_buffs_vampire 1 "vampire buff: attacks to players and monsters heal the carrier"
 set g_buffs_vampire_time 60 "vampire buff carry time"
-set g_buffs_vampire_damage_steal 0.6 "damage stolen multiplier while holding vampire buff"
+set g_buffs_vampire_damage_steal 0.4 "damage stolen multiplier while holding vampire buff"
 set g_buffs_jump 0 "jump buff: greatly increased jump height"
 set g_buffs_jump_time 60 "jump buff carry time"
 set g_buffs_jump_height 600 "jump height while holding jump buff"
@@ -378,7 +379,7 @@ set g_buffs_magnet_range_buff 100 "range around player that only buffs are picke
 set g_buffs_luck 1 "luck buff: randomly increased damage"
 set g_buffs_luck_time 60 "luck buff carry time"
 set g_buffs_luck_chance 0.15 "chance for 'critical' hit (multiplied damage) with luck buff"
-set g_buffs_luck_damagemultiplier 3 "luck damage multiplier"
+set g_buffs_luck_damagemultiplier 2 "luck damage multiplier"
 set g_buffs_flight 0 "flight buff: crouch jump to reverse your gravity!"
 set g_buffs_flight_time 60 "flight buff carry time"
 
index a6f36a77e8320a7f8d4719a4f57987b88553cc91..67d02a776690aa79e608a8e0680ae32440878412 100644 (file)
@@ -1,7 +1,7 @@
 g_mod_physics Overkill
 
 sv_gravity 800
-sv_maxspeed 400
+sv_maxspeed 360
 sv_maxairspeed 360
 
 sv_stopspeed 100
@@ -40,7 +40,7 @@ sv_aircontrol_penalty 180
 sv_aircontrol_power 2
 sv_aircontrol_backwards 0
 sv_aircontrol_sidewards 0
-sv_airspeedlimit_nonqw 900
+sv_airspeedlimit_nonqw 800
 sv_warsowbunny_turnaccel 0
 sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
index 9300293408650e62da25f95b5d63ce824e29b098..d31d12205cfa88357521cc5f6baa8baf3717cdfa 100644 (file)
@@ -25,7 +25,6 @@ float autocvar_cl_announcer_antispam = 2;
 float autocvar_cl_announcer_maptime = 3;
 bool autocvar_cl_autodemo_delete;
 bool autocvar_cl_autodemo_delete_keeprecords;
-bool autocvar_cl_casings;
 float autocvar_cl_casings_bronze_time;
 int autocvar_cl_casings_maxcount = 100;
 float autocvar_cl_casings_shell_time;
@@ -77,7 +76,7 @@ bool autocvar_cl_spawnzoom = 1;
 float autocvar_cl_spawnzoom_speed = 1;
 float autocvar_cl_spawnzoom_factor = 2;
 bool autocvar_cl_stripcolorcodes;
-bool autocvar_cl_vehicles_alarm = true;
+bool autocvar_cl_vehicles_alarm = false;
 bool autocvar_cl_vehicles_hud_tactical = true;
 float autocvar_cl_vehicles_hudscale = 0.5;
 float autocvar_cl_vehicles_notify_time = 15;
@@ -151,6 +150,8 @@ bool autocvar_crosshair_ring_reload;
 float autocvar_crosshair_ring_reload_alpha;
 float autocvar_crosshair_ring_reload_size;
 float autocvar_crosshair_size;
+bool autocvar_crosshair_chase = true;
+float crosshair_chase_playeralpha = 0.25;
 int autocvar_ekg;
 float autocvar_fov;
 bool autocvar_hud_cursormode = true;
@@ -268,7 +269,6 @@ bool autocvar_hud_panel_infomessages_flip;
 float autocvar_hud_panel_mapvote_highlight_border = 1;
 bool autocvar_hud_panel_modicons;
 int autocvar_hud_panel_modicons_ca_layout;
-int autocvar_hud_panel_modicons_dom_layout;
 int autocvar_hud_panel_modicons_freezetag_layout;
 bool autocvar_hud_panel_notify;
 float autocvar_hud_panel_notify_fadetime;
index 56709642026df191ce3c5c3eea00cb300d838ce5..f0c1e789ab9407037d383e651e6cfe27f0be6922 100644 (file)
@@ -434,7 +434,7 @@ void LocalCommand_sendcvar(int request, int argc)
                case CMD_REQUEST_USAGE:
                {
                        LOG_INFO("Usage:^3 cl_cmd sendcvar <cvar>");
-                       LOG_INFO("  Where 'cvar' is the cvar plus arguments to send to the server.");
+                       LOG_INFO("  Where 'cvar' is the cvar to send to the server.");
                        return;
                }
        }
@@ -477,7 +477,7 @@ CLIENT_COMMAND(handlevote, "System to handle selecting a vote or option") { Loca
 CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
 CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
 CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
-CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
+CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like cl_weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
 
 void LocalCommand_macro_help()
 {
index 1fa2fd42be0cff70f91729c08153f3858467972b..5ce4c3e60c3990a1f1492789ca47dee55cdc9bc6 100644 (file)
@@ -109,6 +109,68 @@ int w_deathtype;
 float w_issilent, w_random;
 vector w_org, w_backoff;
 
+float autoswitch;
+bool cvar_cl_allow_uid2name;
+bool cvar_cl_allow_uidranking;
+float cvar_cl_autoscreenshot;
+float cvar_cl_autotaunt;
+float cvar_cl_clippedspectating;
+int cvar_cl_gunalign;
+float cvar_cl_handicap;
+float cvar_cl_jetpack_jump;
+float cvar_cl_movement_track_canjump;
+float cvar_cl_noantilag;
+string cvar_cl_physics;
+float cvar_cl_voice_directional;
+float cvar_cl_voice_directional_taunt_attenuation;
+float cvar_cl_weaponimpulsemode;
+string cvar_g_xonoticversion;
+float cvar_cl_cts_noautoswitch;
+bool cvar_cl_weapon_switch_reload;
+bool cvar_cl_weapon_switch_fallback_to_impulse;
+
+REPLICATE(autoswitch, bool, "cl_autoswitch");
+REPLICATE(cvar_cl_allow_uid2name, bool, "cl_allow_uid2name");
+REPLICATE(cvar_cl_allow_uidranking, bool, "cl_allow_uidranking");
+REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
+REPLICATE(cvar_cl_autotaunt, float, "cl_autotaunt");
+REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
+REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
+REPLICATE(cvar_cl_handicap, float, "cl_handicap");
+REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
+REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
+REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag");
+REPLICATE(cvar_cl_physics, string, "cl_physics");
+REPLICATE(cvar_cl_voice_directional, int, "cl_voice_directional");
+REPLICATE(cvar_cl_voice_directional_taunt_attenuation, float, "cl_voice_directional_taunt_attenuation");
+REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
+REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
+REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
+REPLICATE(cvar_cl_weapon_switch_reload, bool, "cl_weapon_switch_reload");
+REPLICATE(cvar_cl_weapon_switch_fallback_to_impulse, bool, "cl_weapon_switch_fallback_to_impulse");
+/*
+// cvar cl_newusekeysupported doesn't exist
+float cvar_cl_newusekeysupported;
+REPLICATE(cvar_cl_newusekeysupported, bool, "cl_newusekeysupported");
+*/
+string cvar_cl_allow_uidtracking;
+REPLICATE(cvar_cl_allow_uidtracking, string, "cl_allow_uidtracking");
+
+string cvar_cl_weaponpriority;
+REPLICATE(cvar_cl_weaponpriority, string, "cl_weaponpriority");
+
+string cvar_cl_weaponpriorities[10];
+REPLICATE(cvar_cl_weaponpriorities[0], string, "cl_weaponpriority0");
+REPLICATE(cvar_cl_weaponpriorities[1], string, "cl_weaponpriority1");
+REPLICATE(cvar_cl_weaponpriorities[2], string, "cl_weaponpriority2");
+REPLICATE(cvar_cl_weaponpriorities[3], string, "cl_weaponpriority3");
+REPLICATE(cvar_cl_weaponpriorities[4], string, "cl_weaponpriority4");
+REPLICATE(cvar_cl_weaponpriorities[5], string, "cl_weaponpriority5");
+REPLICATE(cvar_cl_weaponpriorities[6], string, "cl_weaponpriority6");
+REPLICATE(cvar_cl_weaponpriorities[7], string, "cl_weaponpriority7");
+REPLICATE(cvar_cl_weaponpriorities[8], string, "cl_weaponpriority8");
+REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9");
+
 float bgmtime;
 
 string weaponorder_byimpulse;
index bd9aa1a21ca53afe3837d12bdf1fef3771ac4940..95ceced82c74d7ca6a39adc2084de9e950c85a2c 100644 (file)
@@ -177,7 +177,7 @@ void HUD_Ammo()
 
        Weapon wep = wepent.switchweapon;
        int i;
-       bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_WEAPON_AMMO);
+       bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_AMMO);
        row = column = 0;
        if(autocvar_hud_panel_ammo_onlycurrent)
        {
index 306bb6f8a316970d229561ad435398f4de58b458..18ec37d47e78f8df34789593c97cc8c4864d21dc 100644 (file)
@@ -9,8 +9,6 @@
 
 // Mod icons (#10)
 
-bool mod_active; // is there any active mod icon?
-
 void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
        TC(int, layout); TC(int, i);
@@ -84,405 +82,6 @@ void HUD_Mod_CA(vector myPos, vector mySize)
        }
 }
 
-// CTF HUD modicon section
-int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
-int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
-float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
-
-void HUD_Mod_CTF_Reset()
-{
-       redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
-       redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
-       redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
-}
-
-int autocvar__teams_available;
-void HUD_Mod_CTF(vector pos, vector mySize)
-{
-       vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
-       vector flag_size;
-       float f; // every function should have that
-
-       int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
-       float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
-       bool ctf_oneflag; // one-flag CTF mode enabled/disabled
-       bool ctf_stalemate; // currently in stalemate
-       int stat_items = STAT(CTF_FLAGSTATUS);
-       float fs, fs2, fs3, size1, size2;
-       vector e1, e2;
-
-       int nteams = autocvar__teams_available;
-
-       redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
-       blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
-       yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
-       pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
-       neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
-
-       ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
-
-       ctf_stalemate = (stat_items & CTF_STALEMATE);
-
-       mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
-
-       if (autocvar__hud_configure) {
-               redflag = 1;
-               blueflag = 2;
-               if (nteams & BIT(2))
-                       yellowflag = 2;
-               if (nteams & BIT(3))
-                       pinkflag = 3;
-               ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
-       }
-
-       // when status CHANGES, set old status into prevstatus and current status into status
-       #define X(team) MACRO_BEGIN \
-               if (team##flag != team##flag_prevframe) { \
-                       team##flag_statuschange_time = time; \
-                       team##flag_prevstatus = team##flag_prevframe; \
-                       team##flag_prevframe = team##flag; \
-               } \
-               team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
-       MACRO_END
-       X(red);
-       X(blue);
-       X(yellow);
-       X(pink);
-       X(neutral);
-       #undef X
-
-       const float BLINK_FACTOR = 0.15;
-       const float BLINK_BASE = 0.85;
-       // note:
-       //   RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
-       // thus
-       //   BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
-       // ensure RMS == 1
-       const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
-
-       #define X(team, cond) \
-       string team##_icon = string_null, team##_icon_prevstatus = string_null; \
-       int team##_alpha, team##_alpha_prevstatus; \
-       team##_alpha = team##_alpha_prevstatus = 1; \
-       MACRO_BEGIN \
-               switch (team##flag) { \
-                       case 1: team##_icon = "flag_" #team "_taken"; break; \
-                       case 2: team##_icon = "flag_" #team "_lost"; break; \
-                       case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
-                       default: \
-                               if ((stat_items & CTF_SHIELDED) && (cond)) { \
-                                       team##_icon = "flag_" #team "_shielded"; \
-                               } else { \
-                                       team##_icon = string_null; \
-                               } \
-                               break; \
-               } \
-               switch (team##flag_prevstatus) { \
-                       case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
-                       case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
-                       case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
-                       default: \
-                               if (team##flag == 3) { \
-                                       team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
-                               } else if((stat_items & CTF_SHIELDED) && (cond)) { \
-                                       team##_icon_prevstatus = "flag_" #team "_shielded"; \
-                               } else { \
-                                       team##_icon_prevstatus = string_null; \
-                               } \
-                               break; \
-               } \
-       MACRO_END
-       X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
-       X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
-       X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
-       X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
-       X(neutral, ctf_oneflag);
-       #undef X
-
-       int tcount = 2;
-       if(nteams & BIT(2))
-               tcount = 3;
-       if(nteams & BIT(3))
-               tcount = 4;
-
-       if (ctf_oneflag) {
-               // hacky, but these aren't needed
-               red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
-               fs = fs2 = fs3 = 1;
-       } else switch (tcount) {
-               default:
-               case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
-               case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
-               case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
-       }
-
-       if (mySize_x > mySize_y) {
-               size1 = mySize_x;
-               size2 = mySize_y;
-               e1 = eX;
-               e2 = eY;
-       } else {
-               size1 = mySize_y;
-               size2 = mySize_x;
-               e1 = eY;
-               e2 = eX;
-       }
-
-       switch (myteam) {
-               default:
-               case NUM_TEAM_1: {
-                       redflag_pos = pos;
-                       blueflag_pos = pos + eX * fs2 * size1;
-                       yellowflag_pos = pos - eX * fs2 * size1;
-                       pinkflag_pos = pos + eX * fs3 * size1;
-                       break;
-               }
-               case NUM_TEAM_2: {
-                       redflag_pos = pos + eX * fs2 * size1;
-                       blueflag_pos = pos;
-                       yellowflag_pos = pos - eX * fs2 * size1;
-                       pinkflag_pos = pos + eX * fs3 * size1;
-                       break;
-               }
-               case NUM_TEAM_3: {
-                       redflag_pos = pos + eX * fs3 * size1;
-                       blueflag_pos = pos - eX * fs2 * size1;
-                       yellowflag_pos = pos;
-                       pinkflag_pos = pos + eX * fs2 * size1;
-                       break;
-               }
-               case NUM_TEAM_4: {
-                       redflag_pos = pos - eX * fs2 * size1;
-                       blueflag_pos = pos + eX * fs3 * size1;
-                       yellowflag_pos = pos + eX * fs2 * size1;
-                       pinkflag_pos = pos;
-                       break;
-               }
-       }
-       neutralflag_pos = pos;
-       flag_size = e1 * fs * size1 + e2 * size2;
-
-       #define X(team) MACRO_BEGIN \
-               f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
-               if (team##_icon && ctf_stalemate) \
-                       drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
-               if (team##_icon_prevstatus && f < 1) \
-                       drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
-               if (team##_icon) \
-                       drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
-       MACRO_END
-       X(red);
-       X(blue);
-       X(yellow);
-       X(pink);
-       X(neutral);
-       #undef X
-}
-
-// Keyhunt HUD modicon section
-vector KH_SLOTS[4];
-
-void HUD_Mod_KH(vector pos, vector mySize)
-{
-       mod_active = 1; // keyhunt should never hide the mod icons panel
-
-       // Read current state
-       int state = STAT(KH_KEYS);
-       if(!state) return;
-
-       int i, key_state;
-       int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
-       all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
-
-       for(i = 0; i < 4; ++i)
-       {
-               key_state = (bitshift(state, i * -5) & 31) - 1;
-
-               if(key_state == -1)
-                       continue;
-
-               if(key_state == 30)
-               {
-                       ++carrying_keys;
-                       key_state = myteam;
-               }
-
-               switch(key_state)
-               {
-                       case NUM_TEAM_1: ++team1_keys; break;
-                       case NUM_TEAM_2: ++team2_keys; break;
-                       case NUM_TEAM_3: ++team3_keys; break;
-                       case NUM_TEAM_4: ++team4_keys; break;
-                       case 29: ++dropped_keys; break;
-               }
-
-               ++all_keys;
-       }
-
-       // Calculate slot measurements
-       vector slot_size;
-       if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
-       {
-               // Quadratic arrangement
-               slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
-               KH_SLOTS[0] = pos;
-               KH_SLOTS[1] = pos + eX * slot_size.x;
-               KH_SLOTS[2] = pos + eY * slot_size.y;
-               KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
-       }
-       else
-       {
-               if(mySize.x > mySize.y)
-               {
-                       // Horizontal arrangement
-                       slot_size = vec2(mySize.x / all_keys, mySize.y);
-                       for(i = 0; i < all_keys; ++i)
-                               KH_SLOTS[i] = pos + eX * slot_size.x * i;
-               }
-               else
-               {
-                       // Vertical arrangement
-                       slot_size = vec2(mySize.x, mySize.y / all_keys);
-                       for(i = 0; i < all_keys; ++i)
-                               KH_SLOTS[i] = pos + eY * slot_size.y * i;
-               }
-       }
-
-       // Make icons blink in case of RUN HERE
-
-       float alpha = 1;
-       if(carrying_keys)
-       {
-               float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
-               switch(myteam)
-               {
-                       case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
-                       case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
-                       case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
-                       case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
-               }
-       }
-
-       // Draw icons
-
-       i = 0;
-
-       while(team1_keys--)
-               if(myteam == NUM_TEAM_1 && carrying_keys)
-               {
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-                       --carrying_keys;
-               }
-               else
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
-       while(team2_keys--)
-               if(myteam == NUM_TEAM_2 && carrying_keys)
-               {
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-                       --carrying_keys;
-               }
-               else
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
-       while(team3_keys--)
-               if(myteam == NUM_TEAM_3 && carrying_keys)
-               {
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-                       --carrying_keys;
-               }
-               else
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
-       while(team4_keys--)
-               if(myteam == NUM_TEAM_4 && carrying_keys)
-               {
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-                       --carrying_keys;
-               }
-               else
-                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
-       while(dropped_keys--)
-               drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-}
-
-// Keepaway HUD mod icon
-int kaball_prevstatus; // last remembered status
-float kaball_statuschange_time; // time when the status changed
-
-// we don't need to reset for keepaway since it immediately
-// autocorrects prevstatus as to if the player has the ball or not
-
-void HUD_Mod_Keepaway(vector pos, vector mySize)
-{
-       mod_active = 1; // keepaway should always show the mod HUD
-
-       float BLINK_FACTOR = 0.15;
-       float BLINK_BASE = 0.85;
-       float BLINK_FREQ = 5;
-       float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-
-       int stat_items = STAT(ITEMS);
-       int kaball = (stat_items/IT_KEY1) & 1;
-
-       if(kaball != kaball_prevstatus)
-       {
-               kaball_statuschange_time = time;
-               kaball_prevstatus = kaball;
-       }
-
-       vector kaball_pos, kaball_size;
-
-       if(mySize.x > mySize.y) {
-               kaball_pos = pos + eX * 0.25 * mySize.x;
-               kaball_size = vec2(0.5 * mySize.x, mySize.y);
-       } else {
-               kaball_pos = pos + eY * 0.25 * mySize.y;
-               kaball_size = vec2(mySize.x, 0.5 * mySize.y);
-       }
-
-       float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
-       float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
-
-       if(kaball_prevstatus && f < 1)
-               drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
-
-       if(kaball)
-               drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
-}
-
-
-// Nexball HUD mod icon
-void HUD_Mod_NexBall(vector pos, vector mySize)
-{
-       float nb_pb_starttime, dt, p;
-       int stat_items;
-
-       stat_items = STAT(ITEMS);
-       nb_pb_starttime = STAT(NB_METERSTART);
-
-       if (stat_items & IT_KEY1)
-               mod_active = 1;
-       else
-               mod_active = 0;
-
-       //Manage the progress bar if any
-       if (nb_pb_starttime > 0)
-       {
-               dt = (time - nb_pb_starttime) % nb_pb_period;
-               // one period of positive triangle
-               p = 2 * dt / nb_pb_period;
-               if (p > 1)
-                       p = 2 - p;
-
-               HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize.x <= mySize.y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-       }
-
-       if (stat_items & IT_KEY1)
-               drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-}
-
 // Race/CTS HUD mod icons
 float crecordtime_prev; // last remembered crecordtime
 float crecordtime_change_time; // time when crecordtime last changed
@@ -629,87 +228,6 @@ void HUD_Mod_Race(vector pos, vector mySize)
        }
 }
 
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
-{
-       TC(int, layout); TC(int, i);
-       float stat = -1;
-       string pic = "";
-       vector color = '0 0 0';
-       switch(i)
-       {
-               case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
-               case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
-               case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
-               default:
-               case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
-       }
-       float pps_ratio = 0;
-       if(STAT(DOM_TOTAL_PPS))
-               pps_ratio = stat / STAT(DOM_TOTAL_PPS);
-
-       if(mySize.x/mySize.y > aspect_ratio)
-       {
-               i = aspect_ratio * mySize.y;
-               myPos.x = myPos.x + (mySize.x - i) / 2;
-               mySize.x = i;
-       }
-       else
-       {
-               i = 1/aspect_ratio * mySize.x;
-               myPos.y = myPos.y + (mySize.y - i) / 2;
-               mySize.y = i;
-       }
-
-       if (layout) // show text too
-       {
-               //draw the text
-               color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
-               if (layout == 2) // average pps
-                       drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
-               else // percentage of average pps
-                       drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
-       }
-
-       //draw the icon
-       drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-       if (stat > 0)
-       {
-               drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
-               drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-               drawresetcliparea();
-       }
-}
-
-void HUD_Mod_Dom(vector myPos, vector mySize)
-{
-       mod_active = 1; // required in each mod function that always shows something
-
-       int layout = autocvar_hud_panel_modicons_dom_layout;
-       int rows, columns;
-       float aspect_ratio;
-       aspect_ratio = (layout) ? 3 : 1;
-       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
-       columns = ceil(team_count/rows);
-
-       int i;
-       float row = 0, column = 0;
-       vector pos, itemSize;
-       itemSize = vec2(mySize.x / columns, mySize.y / rows);
-       for(i=0; i<team_count; ++i)
-       {
-               pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
-
-               DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
-
-               ++row;
-               if(row >= rows)
-               {
-                       row = 0;
-                       ++column;
-               }
-       }
-}
-
 void HUD_ModIcons_SetFunc()
 {
        HUD_ModIcons_GameType = gametype.m_modicons;
index 6db88c68b39ee50fce1f8acce9c778465a3223ae..c90c0991f57282ebde7f30d1e4da9d927b0c627d 100644 (file)
@@ -1,2 +1,4 @@
 #pragma once
 #include "../panel.qh"
+
+bool mod_active; // is there any active mod icon?
index 93162f6bcca059030ae1efae4b57cb98e56e7e79..e11a134558519acaa873875f8da9922b390b1786 100644 (file)
@@ -1167,7 +1167,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                }
                if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
                {
-                       if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)))
+                       if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK))
                                ++nHidden;
                        else
                                ++disownedcnt;
index 3f67787020693ad72e46cde40f0d824dbbdb6b2d..fef3eec09e74d7a487c48bcabe702021256cb50b 100644 (file)
@@ -30,7 +30,7 @@ int weaponorder_cmp(int i, int j, entity pass)
        int nHidden = 0; \
        FOREACH(Weapons, it != WEP_Null, { \
                if (weapons_stat & WepSet_FromWeapon(it)) continue; \
-               if ((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) nHidden += 1; \
+               if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)) nHidden += 1; \
        }); \
        vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, panel_size, aspect); \
        columns = table_size.x; \
@@ -63,7 +63,7 @@ void HUD_Weapons()
        float when = max(1, autocvar_hud_panel_weapons_complainbubble_time);
        float fadetime = max(0, autocvar_hud_panel_weapons_complainbubble_fadetime);
 
-       bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_WEAPON_AMMO);
+       bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_AMMO);
 
        vector weapon_pos, weapon_size = '0 0 0';
        vector color;
@@ -123,7 +123,7 @@ void HUD_Weapons()
                {
                        int j = 0;
                        FOREACH(Weapons, it != WEP_Null && it.impulse >= 0 && (it.impulse % 3 != 0) && j < 6, {
-                               if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
+                               if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_SPECIALATTACK))
                                {
                                        if(!panel_switchweapon || j < 4)
                                                panel_switchweapon = it;
@@ -418,8 +418,11 @@ void HUD_Weapons()
                }
                else
                {
-                       if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) && !(weapons_stat & WepSet_FromWeapon(it)))
+                       if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)
+                               && !(weapons_stat & WepSet_FromWeapon(it)))
+                       {
                                continue;
+                       }
                }
 
                // figure out the drawing position of weapon
index 04cafebbd3a341786d40a29acc313c9b321620c0..b61f425aa6da44b8d9d4f073a7929275f54a5685 100644 (file)
@@ -143,6 +143,8 @@ void CSQC_Init()
        registercvar("cl_weapon_switch_reload", "1");
        registercvar("cl_weapon_switch_fallback_to_impulse", "1");
 
+       registercvar("cl_allow_uidranking", "1");
+
        if(autocvar_cl_lockview)
                cvar_set("cl_lockview", "0");
 
@@ -230,6 +232,8 @@ void Shutdown()
 
        deactivate_minigame();
        HUD_MinigameMenu_Close(NULL, NULL, NULL);
+
+       ReplicateVars(true); // destroy
 }
 
 .float has_team;
index f0f8f1d4bea5ad62563c20df43bc0ce6ad2c9f29..87951ff894ba0e689101e7eb847879908a95c8e4 100644 (file)
@@ -45,20 +45,24 @@ entity teamslots[17];    // 17 teams (including "spectator team")
 .bool ready;
 .bool eliminated;
 
-.void(entity) draw;
 IntrusiveList g_drawables;
-STATIC_INIT(g_drawables) { g_drawables = IL_NEW(); }
-.void(entity) draw2d;
 IntrusiveList g_drawables_2d;
-STATIC_INIT(g_drawables_2d) { g_drawables_2d = IL_NEW(); }
+IntrusiveList g_radarlinks;
+IntrusiveList g_radaricons;
+STATIC_INIT(main)
+{
+       g_drawables = IL_NEW();
+       g_drawables_2d = IL_NEW();
+       g_radarlinks = IL_NEW();
+       g_radaricons = IL_NEW();
+}
+
+.void(entity) draw;
+.void(entity) draw2d;
 .void(entity) entremove;
 float drawframetime;
 vector view_origin, view_forward, view_right, view_up;
 
-IntrusiveList g_radarlinks;
-STATIC_INIT(g_radarlinks) { g_radarlinks = IL_NEW(); }
-IntrusiveList g_radaricons;
-STATIC_INIT(g_radaricons) { g_radaricons = IL_NEW(); }
 
 bool button_zoom;
 bool spectatorbutton_zoom;
index 322abb87e005a628660c3abd916a8746b452ab9a..5ae7d50056a64ba22ec96656873ba25eef86e5a6 100644 (file)
@@ -291,6 +291,7 @@ void viewmodel_draw(entity this)
                return;
        int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
        float a = ((autocvar_cl_viewmodel_alpha) ? bound(-1, autocvar_cl_viewmodel_alpha, this.m_alpha) : this.m_alpha);
+       int wepskin = this.m_skin;
        bool invehicle = player_localentnum > maxclients;
        if (invehicle) a = -1;
        Weapon wep = this.activeweapon;
@@ -304,6 +305,7 @@ void viewmodel_draw(entity this)
        {
                e.drawmask = mask;
                e.alpha = a;
+               e.skin = wepskin;
                e.colormap = 256 + c;  // colormap == 0 is black, c == 0 is white
                e.glowmod = g;
                e.csqcmodel_effects = fx;
@@ -392,86 +394,6 @@ STATIC_INIT(fpscounter_init)
        showfps_prevfps_time = currentTime; // we must initialize it to avoid an instant low frame sending
 }
 
-STATIC_INIT(Porto)
-{
-       entity e = new_pure(porto);
-       e.draw = Porto_Draw;
-       IL_PUSH(g_drawables, e);
-       e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
-}
-
-const int polyline_length = 16;
-.vector polyline[polyline_length];
-void Porto_Draw(entity this)
-{
-       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       {
-               entity wepent = viewmodels[slot];
-
-               if (wepent.activeweapon != WEP_PORTO) continue;
-               if (spectatee_status) continue;
-               if (WEP_CVAR(porto, secondary)) continue;
-               if (intermission == 1) continue;
-               if (intermission == 2) continue;
-               if (STAT(HEALTH) <= 0) continue;
-
-               vector pos = view_origin;
-               vector dir = view_forward;
-               makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
-               pos += v_right * -wepent.movedir.y
-                       +  v_up * wepent.movedir.z;
-
-               if (wepent.angles_held_status)
-               {
-                       makevectors(wepent.angles_held);
-                       dir = v_forward;
-               }
-
-               wepent.polyline[0] = pos;
-
-               int portal_number = 0, portal1_idx = 1, portal_max = 2;
-               int n = 1 + 2;  // 2 lines == 3 points
-               for (int idx = 0; idx < n && idx < polyline_length - 1; )
-               {
-                       traceline(pos, pos + 65536 * dir, true, this);
-                       dir = reflect(dir, trace_plane_normal);
-                       pos = trace_endpos;
-                       wepent.polyline[++idx] = pos;
-                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
-                       {
-                               n += 1;
-                               continue;
-                       }
-                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-                       {
-                               n = max(2, idx);
-                               break;
-                       }
-                       // check size
-                       {
-                               vector ang = vectoangles2(trace_plane_normal, dir);
-                               ang.x = -ang.x;
-                               makevectors(ang);
-                               if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
-                               {
-                                       n = max(2, idx);
-                                       break;
-                               }
-                       }
-                       portal_number += 1;
-                       if (portal_number >= portal_max) break;
-                       if (portal_number == 1) portal1_idx = idx;
-               }
-               for (int idx = 0; idx < n - 1; ++idx)
-               {
-                       vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
-                       if (idx == 0) p -= view_up * 16;  // line from player
-                       vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
-                       Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
-               }
-       }
-}
-
 float drawtime;
 float avgspeed;
 vector GetCurrentFov(float fov)
@@ -679,6 +601,9 @@ float EnemyHitCheck()
 
 float TrueAimCheck(entity wepent)
 {
+       if(wepent.activeweapon.spawnflags & WEP_FLAG_NOTRUEAIM)
+               return SHOTTYPE_HITWORLD;
+
        float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
        vector vecs, trueaimpoint, w_shotorg;
        vector mi, ma, dv;
@@ -692,12 +617,6 @@ float TrueAimCheck(entity wepent)
 
        switch(wepent.activeweapon) // WEAPONTODO
        {
-               case WEP_TUBA: // no aim
-               case WEP_PORTO: // shoots from eye
-               case WEP_NEXBALL: // shoots from eye
-               case WEP_HOOK: // no trueaim
-               case WEP_MORTAR: // toss curve
-                       return SHOTTYPE_HITWORLD;
                case WEP_VORTEX:
                case WEP_OVERKILL_NEX:
                case WEP_VAPORIZER:
@@ -795,7 +714,7 @@ vector liquidcolor_prev;
 
 float eventchase_current_distance;
 float eventchase_running;
-int WantEventchase(entity this)
+int WantEventchase(entity this, bool want_vehiclechase)
 {
        if(autocvar_cl_orthoview)
                return 0;
@@ -805,7 +724,7 @@ int WantEventchase(entity this)
                return 1;
        if(spectatee_status >= 0)
        {
-               if(hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0))
+               if(want_vehiclechase)
                        return 1;
                if(MUTATOR_CALLHOOK(WantEventchase, this))
                        return 1;
@@ -1055,6 +974,21 @@ void HUD_Crosshair(entity this)
                // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
                if(csqcplayer.viewloc && (csqcplayer.viewloc.spawnflags & VIEWLOC_FREEAIM))
                        wcross_origin = viewloc_mousepos;
+               else if(autocvar_chase_active > 0 && autocvar_crosshair_chase)
+               {
+                       vector player_org = ((csqcplayer) ? csqcplayer.origin + csqcplayer.view_ofs : view_origin);
+                       if(csqcplayer && crosshair_chase_playeralpha && crosshair_chase_playeralpha < 1)
+                       {
+                               traceline(view_origin, view_origin + max_shot_distance * view_forward, MOVE_NORMAL, NULL);
+                               float myalpha = (!csqcplayer.m_alpha) ? 1 : csqcplayer.m_alpha;
+                               if(trace_ent == csqcplayer && STAT(HEALTH) > 0)
+                                       csqcplayer.alpha = min(crosshair_chase_playeralpha, myalpha);
+                               else
+                                       csqcplayer.alpha = csqcplayer.m_alpha;
+                       }
+                       traceline(player_org, player_org + max_shot_distance * view_forward, MOVE_WORLDONLY, NULL);
+                       wcross_origin = project_3d_to_2d(trace_endpos);
+               }
                else
                        wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward);
                wcross_origin.z = 0;
@@ -1160,8 +1094,10 @@ void HUD_Crosshair(entity this)
                        wcross_color.z += sin(hitindication_crosshair_size) * hitindication_color.z;
                }
 
-               if(shottype == SHOTTYPE_HITENEMY)
-                       wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
+               // no effects needed for targeting enemies, this can't possibly span all valid targets!
+               // just show for teammates to give a sign that they're an invalid target
+               //if(shottype == SHOTTYPE_HITENEMY)
+                       //wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
                if(shottype == SHOTTYPE_HITTEAM)
                        wcross_scale /= autocvar_crosshair_hittest; // is not queried if hittest is 0
 
@@ -1645,6 +1581,10 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        lasthud = hud;
 
+       ReplicateVars(false);
+       if (ReplicateVars_NOT_SENDING())
+               ReplicateVars_DELAY(0.8 + random() * 0.4); // no need to check cvars every frame
+
        HUD_Scale_Disable();
 
        if(autocvar__hud_showbinds_reload) // menu can set this one
@@ -1734,7 +1674,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                else if(autocvar_chase_active == -2)
                        cvar_set("chase_active", "0");
 
-               float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
+               bool vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
 
                float vehicle_viewdist = 0;
                vector vehicle_viewofs = '0 0 0';
@@ -1746,10 +1686,14 @@ void CSQC_UpdateView(entity this, float w, float h)
                                Vehicle info = Vehicles_from(hud);
                                vehicle_viewdist = info.height;
                                vehicle_viewofs = info.view_ofs;
+                               if(vehicle_viewdist < 0) // when set below 0, this vehicle doesn't use third person view (gunner slots)
+                                       vehicle_chase = false;
                        }
+                       else
+                               vehicle_chase = false;
                }
 
-               int eventchase = WantEventchase(this);
+               int eventchase = WantEventchase(this, vehicle_chase);
                if (eventchase)
                {
                        vector current_view_origin_override = '0 0 0';
index 12fd6eb614c5e8040e0a24995d35ad7f520107c6..f3c1f4139fff3543ca272c7a750a3cd3328422b5 100644 (file)
@@ -6,8 +6,6 @@ vector crosshair_getcolor(entity this, float health_stat);
 
 void calc_followmodel_ofs(entity view);
 
-void Porto_Draw(entity this);
-
 void CSQC_Demo_Camera();
 
 void TrueAim_Init();
index 15c1366ea10bda6d03cc2cda162e8cddbf4fddec..a7e7da546e0b05337766b8247b2832be94c7438c 100644 (file)
@@ -50,6 +50,8 @@ const int SERVERFLAG_PLAYERSTATS = 4;
 // a bit more constant
 const vector PL_MAX_CONST = '16 16 45';
 const vector PL_MIN_CONST = '-16 -16 -24';
+const vector PL_CROUCH_MAX_CONST = '16 16 25';
+const vector PL_CROUCH_MIN_CONST = '-16 -16 -24';
 
 // gametype vote flags
 const int GTV_FORBIDDEN = 0; // Cannot be voted
index 7c5a218b21f15e34ba6ba43ee0d13b4a2b0a801f..96836a38e23c635d00c5c731a3478a6d46d3afb3 100644 (file)
 # define TAG_VIEWLOC_NAME tag_networkviewloc
 # define TAG_VIEWLOC_TYPE int
 .float tag_networkviewloc;
+
+# define ALPHA m_alpha
+.float m_alpha;
 #else
 # define TAG_ENTITY_NAME tag_entity
 # define TAG_ENTITY_TYPE entity
 
 # define TAG_VIEWLOC_NAME viewloc
 # define TAG_VIEWLOC_TYPE entity
+
+# define ALPHA alpha
 #endif
 
 // add properties you want networked to CSQC here
@@ -31,7 +36,7 @@
        CSQCMODEL_PROPERTY(BIT(0), int, ReadShort, WriteShort, colormap) \
        CSQCMODEL_PROPERTY(BIT(1), int, ReadInt24_t, WriteInt24_t, effects) \
        CSQCMODEL_PROPERTY(BIT(2), int, ReadByte, WriteByte, modelflags) \
-       CSQCMODEL_PROPERTY_SCALED(BIT(3), float, ReadByte, WriteByte, alpha, 254, -1, 254) \
+       CSQCMODEL_PROPERTY_SCALED(BIT(3), float, ReadByte, WriteByte, ALPHA, 254, -1, 254) \
        CSQCMODEL_PROPERTY(BIT(4), int, ReadByte, WriteByte, skin) \
        CSQCMODEL_PROPERTY(BIT(5), float, ReadApproxPastTime, WriteApproxPastTime, death_time) \
        CSQCMODEL_PROPERTY(BIT(6), float, ReadByte, WriteByte, solid) \
index beb8e3e912221911705429fe210042762ed51cb0..2169c8bd762bd3abe5e708e1f24e1b8b99333740 100644 (file)
@@ -26,9 +26,8 @@ const int HITTYPE_SECONDARY = BITS(1) << 8;
 const int HITTYPE_SPLASH = BITS(1) << 9;
 const int HITTYPE_BOUNCE = BITS(1) << 10;
 const int HITTYPE_ARMORPIERCE = BITS(1) << 11;
-// unused yet
-const int HITTYPE_RESERVED = BITS(1) << 12;
-const int DEATH_HITTYPEMASK = HITTYPE_SECONDARY | HITTYPE_SPLASH | HITTYPE_BOUNCE | HITTYPE_ARMORPIERCE | HITTYPE_RESERVED;
+const int HITTYPE_SOUND = BITS(1) << 12;
+const int DEATH_HITTYPEMASK = HITTYPE_SECONDARY | HITTYPE_SPLASH | HITTYPE_BOUNCE | HITTYPE_ARMORPIERCE | HITTYPE_SOUND;
 // normal deaths begin
 const int DT_FIRST = BIT(13);
 
index d225b337bc70bfd46d5dd55445d2ba6668b3bd7e..589e343c8df91ae795a94c1375903c429ae17296 100644 (file)
@@ -9,9 +9,19 @@
 
 REGISTER_NET_TEMP(casings)
 
+#if defined(SVQC)
+.bool cvar_cl_casings;
+#elif defined(CSQC)
+bool cvar_cl_casings;
+#endif
+REPLICATE(cvar_cl_casings, bool, "cl_casings");
+
 #ifdef SVQC
 void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner, .entity weaponentity)
 {
+       if (!(CS(casingowner).cvar_cl_casings))
+               return;
+
     entity wep = casingowner.(weaponentity);
     vector org = casingowner.origin + casingowner.view_ofs + wep.spawnorigin.x * v_forward - wep.spawnorigin.y * v_right + wep.spawnorigin.z * v_up;
 
@@ -129,8 +139,6 @@ NET_HANDLE(casings, bool isNew)
     ang_z = ReadByte() * 360 / 256;
     return = true;
 
-    if (!autocvar_cl_casings) return;
-
     Casing casing = RubbleNew("casing");
     casing.silent = (_state & 0x80);
     casing.state = (_state & 0x7F);
index 5dd3e4c8271555ca0993333c7682d5ae3f6054aa..17f48136a6c0a4126f1ae96bf172c89fc63b9d4d 100644 (file)
@@ -392,7 +392,7 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
                w_random = prandom();
 
                traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, NULL);
-               if(trace_fraction < 1 && hitwep != WEP_VORTEX && hitwep != WEP_VAPORIZER)
+               if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN))
                        w_backoff = trace_plane_normal;
                else
                        w_backoff = -1 * normalize(force);
index 835073d07d7e655f896f635de6ff560bdff34e35..9a9a654de9c928d3ae5112a69c8308ebaaab4016 100644 (file)
@@ -1,5 +1,7 @@
 #include "sv_assault.qh"
 
+#include <common/mapobjects/func/breakable.qh>
+
 .entity sprite;
 #define AS_ROUND_DELAY 5
 
@@ -347,7 +349,6 @@ bool destructible_heal(entity targ, entity inflictor, float amount, float limit)
        return true;
 }
 
-spawnfunc(func_breakable);
 spawnfunc(func_assault_destructible)
 {
        if (!g_assault) { delete(this); return; }
index 4105f7ce8c53cc14eb544a5c7df59cedb484f4fe..408a14e0d87fbac00a3dfcc11bd6292997149fe3 100644 (file)
@@ -333,7 +333,7 @@ MUTATOR_HOOKFUNCTION(ca, GiveFragsForKill, CBC_ORDER_FIRST)
 
 MUTATOR_HOOKFUNCTION(ca, SetStartItems)
 {
-       start_items       &= ~IT_UNLIMITED_AMMO;
+       start_items       &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
        start_health       = warmup_start_health       = cvar("g_lms_start_health");
        start_armorvalue   = warmup_start_armorvalue   = cvar("g_lms_start_armor");
        start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_lms_start_ammo_shells");
@@ -483,11 +483,6 @@ MUTATOR_HOOKFUNCTION(ca, ClientCommand_Spectate)
        return MUT_SPECCMD_CONTINUE;
 }
 
-MUTATOR_HOOKFUNCTION(ca, WantWeapon)
-{
-       M_ARGV(2, bool) = true; // all weapons
-}
-
 MUTATOR_HOOKFUNCTION(ca, HideTeamNagger)
 {
        return true; // doesn't work well with the whole spectator as player thing
@@ -502,6 +497,14 @@ MUTATOR_HOOKFUNCTION(ca, GetPlayerStatus)
 
 MUTATOR_HOOKFUNCTION(ca, SetWeaponArena)
 {
-       // most weapons arena
-       if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") M_ARGV(0, string) = "most";
+       if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "")
+               M_ARGV(0, string) = autocvar_g_ca_weaponarena;
+}
+
+MUTATOR_HOOKFUNCTION(ca, SV_ParseServerCommand)
+{
+       string cmd_name = M_ARGV(0, string);
+       if (cmd_name == "shuffleteams")
+               shuffleteams_on_reset_map = !allowed_to_spawn;
+       return false;
 }
index c4755feee9a32e9560a27321698fb0fdf0e6a99d..f6420b85261b7efaa9435db2ae1e8b90e091e0e8 100644 (file)
@@ -3,6 +3,7 @@
 #include <common/mutators/base.qh>
 #include <server/round_handler.qh>
 #include <server/miscfunctions.qh>
+#include <server/command/sv_cmd.qh>
 
 int autocvar_g_ca_point_limit;
 int autocvar_g_ca_point_leadlimit;
@@ -11,6 +12,7 @@ bool autocvar_g_ca_team_spawns;
 //int autocvar_g_ca_teams;
 int autocvar_g_ca_teams_override;
 float autocvar_g_ca_warmup;
+string autocvar_g_ca_weaponarena = "most";
 
 
 int ca_teams;
index 7bc5a9679c2a56a6c9d4278e648ed70c8647b408..663a5f829a9273ce3b507754a36994316e683c16 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/ctf/ctf.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/ctf/cl_ctf.qc>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/ctf/sv_ctf.qc>
 #endif
index e7fcea7bcf0fed7cd4ac697f5368da35d848e3ee..9a1d1811935d27179b591974bfffe1c667af9609 100644 (file)
@@ -1,5 +1,8 @@
 // generated file; do not modify
 #include <common/gamemodes/gamemode/ctf/ctf.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/ctf/cl_ctf.qh>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
 #endif
diff --git a/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc
new file mode 100644 (file)
index 0000000..c82e0bc
--- /dev/null
@@ -0,0 +1,198 @@
+#include "cl_ctf.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// CTF HUD modicon section
+int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
+int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
+float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
+
+void HUD_Mod_CTF_Reset()
+{
+    redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
+    redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
+    redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
+}
+
+int autocvar__teams_available;
+void HUD_Mod_CTF(vector pos, vector mySize)
+{
+    vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
+    vector flag_size;
+    float f; // every function should have that
+
+    int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
+    float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
+    bool ctf_oneflag; // one-flag CTF mode enabled/disabled
+    bool ctf_stalemate; // currently in stalemate
+    int stat_items = STAT(CTF_FLAGSTATUS);
+    float fs, fs2, fs3, size1, size2;
+    vector e1, e2;
+
+    int nteams = autocvar__teams_available;
+
+    redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
+    blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
+    yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
+    pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
+    neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
+
+    ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
+
+    ctf_stalemate = (stat_items & CTF_STALEMATE);
+
+    mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
+
+    if (autocvar__hud_configure) {
+        redflag = 1;
+        blueflag = 2;
+        if (nteams & BIT(2))
+            yellowflag = 2;
+        if (nteams & BIT(3))
+            pinkflag = 3;
+        ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
+    }
+
+    // when status CHANGES, set old status into prevstatus and current status into status
+    #define X(team) MACRO_BEGIN \
+        if (team##flag != team##flag_prevframe) { \
+            team##flag_statuschange_time = time; \
+            team##flag_prevstatus = team##flag_prevframe; \
+            team##flag_prevframe = team##flag; \
+        } \
+        team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
+    MACRO_END
+    X(red);
+    X(blue);
+    X(yellow);
+    X(pink);
+    X(neutral);
+    #undef X
+
+    const float BLINK_FACTOR = 0.15;
+    const float BLINK_BASE = 0.85;
+    // note:
+    //   RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
+    // thus
+    //   BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
+    // ensure RMS == 1
+    const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
+
+    #define X(team, cond) \
+    string team##_icon = string_null, team##_icon_prevstatus = string_null; \
+    int team##_alpha, team##_alpha_prevstatus; \
+    team##_alpha = team##_alpha_prevstatus = 1; \
+    MACRO_BEGIN \
+        switch (team##flag) { \
+            case 1: team##_icon = "flag_" #team "_taken"; break; \
+            case 2: team##_icon = "flag_" #team "_lost"; break; \
+            case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+            default: \
+                if ((stat_items & CTF_SHIELDED) && (cond)) { \
+                    team##_icon = "flag_" #team "_shielded"; \
+                } else { \
+                    team##_icon = string_null; \
+                } \
+                break; \
+        } \
+        switch (team##flag_prevstatus) { \
+            case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
+            case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
+            case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+            default: \
+                if (team##flag == 3) { \
+                    team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
+                } else if((stat_items & CTF_SHIELDED) && (cond)) { \
+                    team##_icon_prevstatus = "flag_" #team "_shielded"; \
+                } else { \
+                    team##_icon_prevstatus = string_null; \
+                } \
+                break; \
+        } \
+    MACRO_END
+    X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
+    X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
+    X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
+    X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
+    X(neutral, ctf_oneflag);
+    #undef X
+
+    int tcount = 2;
+    if(nteams & BIT(2))
+        tcount = 3;
+    if(nteams & BIT(3))
+        tcount = 4;
+
+    if (ctf_oneflag) {
+        // hacky, but these aren't needed
+        red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
+        fs = fs2 = fs3 = 1;
+    } else switch (tcount) {
+        default:
+        case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
+        case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
+        case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
+    }
+
+    if (mySize_x > mySize_y) {
+        size1 = mySize_x;
+        size2 = mySize_y;
+        e1 = eX;
+        e2 = eY;
+    } else {
+        size1 = mySize_y;
+        size2 = mySize_x;
+        e1 = eY;
+        e2 = eX;
+    }
+
+    switch (myteam) {
+        default:
+        case NUM_TEAM_1: {
+            redflag_pos = pos;
+            blueflag_pos = pos + eX * fs2 * size1;
+            yellowflag_pos = pos - eX * fs2 * size1;
+            pinkflag_pos = pos + eX * fs3 * size1;
+            break;
+        }
+        case NUM_TEAM_2: {
+            redflag_pos = pos + eX * fs2 * size1;
+            blueflag_pos = pos;
+            yellowflag_pos = pos - eX * fs2 * size1;
+            pinkflag_pos = pos + eX * fs3 * size1;
+            break;
+        }
+        case NUM_TEAM_3: {
+            redflag_pos = pos + eX * fs3 * size1;
+            blueflag_pos = pos - eX * fs2 * size1;
+            yellowflag_pos = pos;
+            pinkflag_pos = pos + eX * fs2 * size1;
+            break;
+        }
+        case NUM_TEAM_4: {
+            redflag_pos = pos - eX * fs2 * size1;
+            blueflag_pos = pos + eX * fs3 * size1;
+            yellowflag_pos = pos + eX * fs2 * size1;
+            pinkflag_pos = pos;
+            break;
+        }
+    }
+    neutralflag_pos = pos;
+    flag_size = e1 * fs * size1 + e2 * size2;
+
+    #define X(team) MACRO_BEGIN \
+        f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
+        if (team##_icon && ctf_stalemate) \
+            drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
+        if (team##_icon_prevstatus && f < 1) \
+            drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
+        if (team##_icon) \
+            drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
+    MACRO_END
+    X(red);
+    X(blue);
+    X(yellow);
+    X(pink);
+    X(neutral);
+    #undef X
+}
diff --git a/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh
new file mode 100644 (file)
index 0000000..1cf4bcf
--- /dev/null
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "ctf.qh"
+
+void HUD_Mod_CTF_Reset();
+void HUD_Mod_CTF(vector pos, vector mySize);
diff --git a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc
new file mode 100644 (file)
index 0000000..a6157c5
--- /dev/null
@@ -0,0 +1 @@
+#include "ctf.qh"
index 2484240a26d1c83c62b9487bdcf85ff7d984b6ff..03b2ec9d1d428a3c7dfce3b0d3cbcb2d5fe05bd1 100644 (file)
@@ -440,7 +440,8 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype)
 
        // reset the flag
        setattachment(flag, NULL, "");
-       setorigin(flag, player.origin + FLAG_DROP_OFFSET);
+       tracebox(player.origin - FLAG_DROP_OFFSET, flag.m_mins, flag.m_maxs, player.origin + FLAG_DROP_OFFSET, MOVE_NOMONSTERS, flag);
+       setorigin(flag, trace_endpos);
        flag.owner.flagcarried = NULL;
        GameRules_scoring_vip(flag.owner, false);
        flag.owner = NULL;
@@ -2593,6 +2594,13 @@ MUTATOR_HOOKFUNCTION(ctf, DropSpecialItems)
                ctf_Handle_Throw(frag_target, NULL, DROP_THROW);
 }
 
+MUTATOR_HOOKFUNCTION(ctf, LogDeath_AppendItemCodes)
+{
+       entity player = M_ARGV(0, entity);
+       if(player.flagcarried)
+               M_ARGV(1, string) = strcat(M_ARGV(1, string), "F"); // item codes
+}
+
 
 // ==========
 // Spawnfuncs
index 679dd850257a3286db8a56d1ecf76bc67971be31..b1518bd4fc1825df24868ce50597f31cb1368d4c 100644 (file)
@@ -28,7 +28,8 @@ CLASS(Flag, Pickup)
     ATTRIB(Flag, m_mins, vector, (PL_MIN_CONST + '0 0 -13') * 1.4); // scaling be damned
     ATTRIB(Flag, m_maxs, vector, (PL_MAX_CONST + '0 0 -13') * 1.4);
 ENDCLASS(Flag)
-Flag CTF_FLAG; STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); }
+Flag CTF_FLAG;
+STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); }
 void ctf_FlagTouch(entity this, entity toucher) { ITEM_HANDLE(Pickup, CTF_FLAG, this, toucher); }
 
 // flag constants // for most of these, there is just one question to be asked: WHYYYYY?
index ff9bc11f881d0afb4031fd3dd0937f37f2093f93..a35415a8f3da75cda808a45ea231447ecd936170 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/domination/domination.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/domination/cl_domination.qc>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/domination/sv_domination.qc>
 #endif
index 0c5e8412146e62d3970d3452f98d25c5f60af386..869273e850a516a22fcbca3603d8ab77ddb91f32 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/domination/domination.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/domination/cl_domination.qh>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/domination/sv_domination.qh>
 #endif
diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc
new file mode 100644 (file)
index 0000000..418a843
--- /dev/null
@@ -0,0 +1,86 @@
+#include "cl_domination.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+int autocvar_hud_panel_modicons_dom_layout;
+
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
+{
+       TC(int, layout); TC(int, i);
+       float stat = -1;
+       string pic = "";
+       vector color = '0 0 0';
+       switch(i)
+       {
+               case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
+               case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
+               case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
+               default:
+               case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
+       }
+       float pps_ratio = 0;
+       if(STAT(DOM_TOTAL_PPS))
+               pps_ratio = stat / STAT(DOM_TOTAL_PPS);
+
+       if(mySize.x/mySize.y > aspect_ratio)
+       {
+               i = aspect_ratio * mySize.y;
+               myPos.x = myPos.x + (mySize.x - i) / 2;
+               mySize.x = i;
+       }
+       else
+       {
+               i = 1/aspect_ratio * mySize.x;
+               myPos.y = myPos.y + (mySize.y - i) / 2;
+               mySize.y = i;
+       }
+
+       if (layout) // show text too
+       {
+               //draw the text
+               color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
+               if (layout == 2) // average pps
+                       drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
+               else // percentage of average pps
+                       drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+
+       //draw the icon
+       drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       if (stat > 0)
+       {
+               drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
+               drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawresetcliparea();
+       }
+}
+
+void HUD_Mod_Dom(vector myPos, vector mySize)
+{
+       mod_active = 1; // required in each mod function that always shows something
+
+       int layout = autocvar_hud_panel_modicons_dom_layout;
+       int rows, columns;
+       float aspect_ratio;
+       aspect_ratio = (layout) ? 3 : 1;
+       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
+       columns = ceil(team_count/rows);
+
+       int i;
+       float row = 0, column = 0;
+       vector pos, itemSize;
+       itemSize = vec2(mySize.x / columns, mySize.y / rows);
+       for(i=0; i<team_count; ++i)
+       {
+               pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
+
+               DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
+
+               ++row;
+               if(row >= rows)
+               {
+                       row = 0;
+                       ++column;
+               }
+       }
+}
diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh
new file mode 100644 (file)
index 0000000..11ab3da
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void HUD_Mod_Dom(vector myPos, vector mySize);
diff --git a/qcsrc/common/gamemodes/gamemode/domination/domination.qc b/qcsrc/common/gamemodes/gamemode/domination/domination.qc
new file mode 100644 (file)
index 0000000..3e5beba
--- /dev/null
@@ -0,0 +1 @@
+#include "domination.qh"
diff --git a/qcsrc/common/gamemodes/gamemode/domination/domination.qh b/qcsrc/common/gamemodes/gamemode/domination/domination.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index c42c7443ba252a997d778f9c731132a292bc3857..54f6268e36da53d537e2effef2c5c72c62afadbf 100644 (file)
@@ -361,7 +361,9 @@ MUTATOR_HOOKFUNCTION(ft, PlayerDies)
                if (STAT(FROZEN, frag_target) == FROZEN_NORMAL)
                        Unfreeze(frag_target, true);
                freezetag_count_alive_players();
-               return true; // let the player die so that he can respawn whenever he wants
+               frag_target.respawn_time = time;
+               frag_target.respawn_flags |= RESPAWN_FORCE;
+               return true;
        }
 
        // Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
@@ -547,7 +549,7 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
 
 MUTATOR_HOOKFUNCTION(ft, SetStartItems)
 {
-       start_items &= ~IT_UNLIMITED_AMMO;
+       start_items &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
        //start_health       = warmup_start_health       = cvar("g_lms_start_health");
        //start_armorvalue   = warmup_start_armorvalue   = cvar("g_lms_start_armor");
        start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_lms_start_ammo_shells");
@@ -585,9 +587,8 @@ MUTATOR_HOOKFUNCTION(ft, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 
 MUTATOR_HOOKFUNCTION(ft, SetWeaponArena)
 {
-       // most weapons arena
        if(M_ARGV(0, string) == "0" || M_ARGV(0, string) == "")
-               M_ARGV(0, string) = "most";
+               M_ARGV(0, string) = autocvar_g_freezetag_weaponarena;
 }
 
 MUTATOR_HOOKFUNCTION(ft, FragCenterMessage)
@@ -608,6 +609,14 @@ MUTATOR_HOOKFUNCTION(ft, FragCenterMessage)
        return true;
 }
 
+MUTATOR_HOOKFUNCTION(ft, SV_ParseServerCommand)
+{
+       string cmd_name = M_ARGV(0, string);
+       if (cmd_name == "shuffleteams")
+               shuffleteams_on_reset_map = !(round_handler_IsActive() && !round_handler_IsRoundStarted());
+       return false;
+}
+
 void freezetag_Initialize()
 {
        freezetag_teams = autocvar_g_freezetag_teams_override;
index d637ae46f6a52f934f2d806adc5c1cdb49334098..3eb753020b35a857da4cde61e2b9b95879727c47 100644 (file)
@@ -1,9 +1,13 @@
 #pragma once
 
 #include <common/mutators/base.qh>
+#include <server/command/sv_cmd.qh>
+
 int autocvar_g_freezetag_point_limit;
 int autocvar_g_freezetag_point_leadlimit;
 bool autocvar_g_freezetag_team_spawns;
+string autocvar_g_freezetag_weaponarena = "most_available";
+
 void freezetag_Initialize();
 
 REGISTER_MUTATOR(ft, false)
index 420f7af78aa2c29c635e28e9b8113210230f2629..42fb4b0e24b2bd831385ba1c8c545866cb2dee4c 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/keepaway/keepaway.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/keepaway/cl_keepaway.qc>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/keepaway/sv_keepaway.qc>
 #endif
index 145ca49f0a06878ab0ca96d381dc0f020c32f896..93eaf396c755e0f01ccf258c712b8ec5cbb341be 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/keepaway/keepaway.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/keepaway/cl_keepaway.qh>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/keepaway/sv_keepaway.qh>
 #endif
diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc
new file mode 100644 (file)
index 0000000..b2d0874
--- /dev/null
@@ -0,0 +1,48 @@
+#include "cl_keepaway.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Keepaway HUD mod icon
+int kaball_prevstatus; // last remembered status
+float kaball_statuschange_time; // time when the status changed
+
+// we don't need to reset for keepaway since it immediately
+// autocorrects prevstatus as to if the player has the ball or not
+
+void HUD_Mod_Keepaway(vector pos, vector mySize)
+{
+       mod_active = 1; // keepaway should always show the mod HUD
+
+       float BLINK_FACTOR = 0.15;
+       float BLINK_BASE = 0.85;
+       float BLINK_FREQ = 5;
+       float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
+
+       int stat_items = STAT(ITEMS);
+       int kaball = (stat_items/IT_KEY1) & 1;
+
+       if(kaball != kaball_prevstatus)
+       {
+               kaball_statuschange_time = time;
+               kaball_prevstatus = kaball;
+       }
+
+       vector kaball_pos, kaball_size;
+
+       if(mySize.x > mySize.y) {
+               kaball_pos = pos + eX * 0.25 * mySize.x;
+               kaball_size = vec2(0.5 * mySize.x, mySize.y);
+       } else {
+               kaball_pos = pos + eY * 0.25 * mySize.y;
+               kaball_size = vec2(mySize.x, 0.5 * mySize.y);
+       }
+
+       float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
+       float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
+
+       if(kaball_prevstatus && f < 1)
+               drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
+
+       if(kaball)
+               drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
+}
diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh
new file mode 100644 (file)
index 0000000..7bcc289
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void HUD_Mod_Keepaway(vector pos, vector mySize);
diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qc b/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qc
new file mode 100644 (file)
index 0000000..fe03dc9
--- /dev/null
@@ -0,0 +1 @@
+#include "keepaway.qh"
diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh b/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index 4f44840c41c7ba592ac0679917fd767aa379adbf..52b5f0df8f38f9a6b25dd485e2d1ccbe3b3e39b3 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/keyhunt/keyhunt.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc>
 #endif
index e4143fc84cd91165519803a90f145f7977a841fe..46f35788ed794f73c631421f9defa77871347bbd 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/gamemodes/gamemode/keyhunt/keyhunt.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh>
+#endif
 #ifdef SVQC
     #include <common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh>
 #endif
diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc
new file mode 100644 (file)
index 0000000..e95275e
--- /dev/null
@@ -0,0 +1,131 @@
+#include "cl_keyhunt.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Keyhunt HUD modicon section
+vector KH_SLOTS[4];
+
+void HUD_Mod_KH(vector pos, vector mySize)
+{
+       mod_active = 1; // keyhunt should never hide the mod icons panel
+
+       // Read current state
+       int state = STAT(KH_KEYS);
+       if(!state) return;
+
+       int i, key_state;
+       int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+       all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
+
+       for(i = 0; i < 4; ++i)
+       {
+               key_state = (bitshift(state, i * -5) & 31) - 1;
+
+               if(key_state == -1)
+                       continue;
+
+               if(key_state == 30)
+               {
+                       ++carrying_keys;
+                       key_state = myteam;
+               }
+
+               switch(key_state)
+               {
+                       case NUM_TEAM_1: ++team1_keys; break;
+                       case NUM_TEAM_2: ++team2_keys; break;
+                       case NUM_TEAM_3: ++team3_keys; break;
+                       case NUM_TEAM_4: ++team4_keys; break;
+                       case 29: ++dropped_keys; break;
+               }
+
+               ++all_keys;
+       }
+
+       // Calculate slot measurements
+       vector slot_size;
+       if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
+       {
+               // Quadratic arrangement
+               slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
+               KH_SLOTS[0] = pos;
+               KH_SLOTS[1] = pos + eX * slot_size.x;
+               KH_SLOTS[2] = pos + eY * slot_size.y;
+               KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
+       }
+       else
+       {
+               if(mySize.x > mySize.y)
+               {
+                       // Horizontal arrangement
+                       slot_size = vec2(mySize.x / all_keys, mySize.y);
+                       for(i = 0; i < all_keys; ++i)
+                               KH_SLOTS[i] = pos + eX * slot_size.x * i;
+               }
+               else
+               {
+                       // Vertical arrangement
+                       slot_size = vec2(mySize.x, mySize.y / all_keys);
+                       for(i = 0; i < all_keys; ++i)
+                               KH_SLOTS[i] = pos + eY * slot_size.y * i;
+               }
+       }
+
+       // Make icons blink in case of RUN HERE
+
+       float alpha = 1;
+       if(carrying_keys)
+       {
+               float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
+               switch(myteam)
+               {
+                       case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
+               }
+       }
+
+       // Draw icons
+
+       i = 0;
+
+       while(team1_keys--)
+               if(myteam == NUM_TEAM_1 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team2_keys--)
+               if(myteam == NUM_TEAM_2 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team3_keys--)
+               if(myteam == NUM_TEAM_3 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team4_keys--)
+               if(myteam == NUM_TEAM_4 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(dropped_keys--)
+               drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+}
diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh
new file mode 100644 (file)
index 0000000..8d650f1
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void HUD_Mod_KH(vector pos, vector mySize);
diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc
new file mode 100644 (file)
index 0000000..724a0e6
--- /dev/null
@@ -0,0 +1 @@
+#include "keyhunt.qh"
diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index d33696ad3772a88fca49f0620dbb693eb0f4b792..21d9208bf96b74746cbb7f35c074b2a5f228ad27 100644 (file)
@@ -23,6 +23,7 @@ float autocvar_g_balance_keyhunt_throwvelocity;
 int autocvar_g_keyhunt_teams_override;
 
 // #define KH_PLAYER_USE_ATTACHMENT
+// TODO? no model exists for this
 // #define KH_PLAYER_USE_CARRIEDMODEL
 
 #ifdef KH_PLAYER_USE_ATTACHMENT
@@ -61,8 +62,6 @@ int kh_Team_ByID(int t)
        return 0;
 }
 
-//entity kh_worldkeylist;
-.entity kh_worldkeynext;
 entity kh_controller;
 //bool kh_tracking_enabled;
 int kh_teams;
@@ -1293,6 +1292,13 @@ MUTATOR_HOOKFUNCTION(kh, HavocBot_ChooseRole)
        return true;
 }
 
+MUTATOR_HOOKFUNCTION(kh, LogDeath_AppendItemCodes)
+{
+       entity player = M_ARGV(0, entity);
+       if(player.kh_next)
+               M_ARGV(1, string) = strcat(M_ARGV(1, string), "K"); // item codes
+}
+
 MUTATOR_HOOKFUNCTION(kh, DropSpecialItems)
 {
        entity frag_target = M_ARGV(0, entity);
index 345a3d166e0a6f7a0ab65f31e42770716a955b4c..66321c3d9d17f81917d886ce51c8cb1feb749c7a 100644 (file)
@@ -21,6 +21,9 @@ REGISTER_MUTATOR(kh, false)
        return 0;
 }
 
+entity kh_worldkeylist;
+.entity kh_worldkeynext;
+
 #define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
 
 // ALL OF THESE should be removed in the future, as other code should not have to care
index 6d420c7a95b82dd0701977e3608613360172408d..aceb66e0310db714e640c16250b7bcd8d4a547c5 100644 (file)
@@ -323,7 +323,7 @@ MUTATOR_HOOKFUNCTION(lms, GiveFragsForKill)
 
 MUTATOR_HOOKFUNCTION(lms, SetStartItems)
 {
-       start_items &= ~IT_UNLIMITED_AMMO;
+       start_items &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
        start_health       = warmup_start_health       = cvar("g_lms_start_health");
        start_armorvalue   = warmup_start_armorvalue   = cvar("g_lms_start_armor");
        start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_lms_start_ammo_shells");
@@ -429,9 +429,10 @@ MUTATOR_HOOKFUNCTION(lms, CheckRules_World)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(lms, WantWeapon)
+MUTATOR_HOOKFUNCTION(lms, SetWeaponArena)
 {
-       M_ARGV(2, bool) = true; // all weapons
+       if(M_ARGV(0, string) == "0" || M_ARGV(0, string) == "")
+               M_ARGV(0, string) = autocvar_g_lms_weaponarena;
 }
 
 MUTATOR_HOOKFUNCTION(lms, GetPlayerStatus)
index 256620a454bf7f80ad97a095a84b92b6dc094fc8..996d371fe05b84e736283ccc042251aaa60e8a3a 100644 (file)
@@ -2,8 +2,12 @@
 
 #include <common/mutators/base.qh>
 #include <common/scores.qh>
+
 .float lms_spectate_warning;
+
 #define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
+string autocvar_g_lms_weaponarena = "most_available";
+
 void lms_Initialize();
 
 REGISTER_MUTATOR(lms, false)
index 78727675637493289d22309c4d98da3a1a7649cb..4e9fd6b10369b1b482326eb7d4b71a26e5004cfd 100644 (file)
@@ -1,5 +1,11 @@
 // generated file; do not modify
 #include <common/gamemodes/gamemode/nexball/nexball.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/nexball/cl_nexball.qc>
+#endif
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/nexball/sv_nexball.qc>
+#endif
 #include <common/gamemodes/gamemode/nexball/weapon.qc>
 #ifdef SVQC
     #include <common/gamemodes/gamemode/nexball/sv_weapon.qc>
index a1cf54437108efae947d84ea02e8e9a9488f3926..657280e6a59dcdd48ec85813a1fac3504eab1d52 100644 (file)
@@ -1,5 +1,11 @@
 // generated file; do not modify
 #include <common/gamemodes/gamemode/nexball/nexball.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/nexball/cl_nexball.qh>
+#endif
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/nexball/sv_nexball.qh>
+#endif
 #include <common/gamemodes/gamemode/nexball/weapon.qh>
 #ifdef SVQC
     #include <common/gamemodes/gamemode/nexball/sv_weapon.qh>
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc
new file mode 100644 (file)
index 0000000..5a6b42d
--- /dev/null
@@ -0,0 +1,44 @@
+#include "cl_nexball.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Nexball HUD mod icon
+void HUD_Mod_NexBall(vector pos, vector mySize)
+{
+       float nb_pb_starttime, dt, p;
+       int stat_items;
+
+       stat_items = STAT(ITEMS);
+       nb_pb_starttime = STAT(NB_METERSTART);
+
+       if (stat_items & IT_KEY1)
+               mod_active = 1;
+       else
+               mod_active = 0;
+
+       //Manage the progress bar if any
+       if (nb_pb_starttime > 0)
+       {
+               dt = (time - nb_pb_starttime) % nb_pb_period;
+               // one period of positive triangle
+               p = 2 * dt / nb_pb_period;
+               if (p > 1)
+                       p = 2 - p;
+
+               HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize.x <= mySize.y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+
+       if (stat_items & IT_KEY1)
+               drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+int autocvar_cl_eventchase_nexball = 1;
+
+REGISTER_MUTATOR(cl_nb, true);
+
+MUTATOR_HOOKFUNCTION(cl_nb, WantEventchase)
+{
+       if(autocvar_cl_eventchase_nexball && ISGAMETYPE(NEXBALL) && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
+               return true;
+       return false;
+}
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh
new file mode 100644 (file)
index 0000000..d0b3731
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void HUD_Mod_NexBall(vector pos, vector mySize);
index c841079fb775016d7828964bc25c0142261f76f0..4b49dba3ed8b829b7cf6298477c0bc267e0f0789 100644 (file)
@@ -1,984 +1 @@
 #include "nexball.qh"
-
-#ifdef CSQC
-int autocvar_cl_eventchase_nexball = 1;
-
-REGISTER_MUTATOR(cl_nb, true);
-
-MUTATOR_HOOKFUNCTION(cl_nb, WantEventchase)
-{
-       if(autocvar_cl_eventchase_nexball && ISGAMETYPE(NEXBALL) && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
-               return true;
-       return false;
-}
-#endif
-#ifdef SVQC
-.entity ballcarried;
-
-int autocvar_g_nexball_goalleadlimit;
-#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
-
-bool autocvar_g_nexball_basketball_jumppad = true;
-float autocvar_g_nexball_basketball_bouncefactor;
-float autocvar_g_nexball_basketball_bouncestop;
-float autocvar_g_nexball_basketball_carrier_highspeed;
-bool autocvar_g_nexball_basketball_meter;
-float autocvar_g_nexball_basketball_meter_maxpower;
-float autocvar_g_nexball_basketball_meter_minpower;
-float autocvar_g_nexball_delay_collect;
-float autocvar_g_nexball_delay_goal;
-float autocvar_g_nexball_delay_start;
-bool autocvar_g_nexball_football_jumppad = true;
-float autocvar_g_nexball_football_bouncefactor;
-float autocvar_g_nexball_football_bouncestop;
-bool autocvar_g_nexball_radar_showallplayers;
-bool autocvar_g_nexball_sound_bounce;
-int autocvar_g_nexball_trail_color;
-bool autocvar_g_nexball_playerclip_collisions = true;
-
-float autocvar_g_nexball_safepass_turnrate;
-float autocvar_g_nexball_safepass_maxdist;
-float autocvar_g_nexball_safepass_holdtime;
-float autocvar_g_nexball_viewmodel_scale;
-float autocvar_g_nexball_tackling;
-vector autocvar_g_nexball_viewmodel_offset;
-
-float autocvar_g_balance_nexball_primary_animtime;
-float autocvar_g_balance_nexball_primary_refire;
-float autocvar_g_balance_nexball_primary_speed;
-float autocvar_g_balance_nexball_secondary_animtime;
-float autocvar_g_balance_nexball_secondary_force;
-float autocvar_g_balance_nexball_secondary_lifetime;
-float autocvar_g_balance_nexball_secondary_refire;
-float autocvar_g_balance_nexball_secondary_speed;
-
-void basketball_touch(entity this, entity toucher);
-void football_touch(entity this, entity toucher);
-void ResetBall(entity this);
-const int NBM_NONE = 0;
-const int NBM_FOOTBALL = 2;
-const int NBM_BASKETBALL = 4;
-float nexball_mode;
-
-float OtherTeam(float t)  //works only if there are two teams on the map!
-{
-       entity e;
-       e = find(NULL, classname, "nexball_team");
-       if(e.team == t)
-               e = find(e, classname, "nexball_team");
-       return e.team;
-}
-
-const int ST_NEXBALL_GOALS = 1;
-void nb_ScoreRules(int teams)
-{
-    GameRules_scoring(teams, 0, 0, {
-        field_team(ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
-        field(SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
-        field(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
-    });
-}
-
-void LogNB(string mode, entity actor)
-{
-       string s;
-       if(!autocvar_sv_eventlog)
-               return;
-       s = strcat(":nexball:", mode);
-       if(actor != NULL)
-               s = strcat(s, ":", ftos(actor.playerid));
-       GameLogEcho(s);
-}
-
-void ball_restart(entity this)
-{
-       if(this.owner)
-               DropBall(this, this.owner.origin, '0 0 0');
-       ResetBall(this);
-}
-
-void nexball_setstatus(entity this)
-{
-       this.items &= ~IT_KEY1;
-       if(this.ballcarried)
-       {
-               if(this.ballcarried.teamtime && (this.ballcarried.teamtime < time))
-               {
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
-                       entity e = this.ballcarried;
-                       DropBall(this.ballcarried, this.ballcarried.owner.origin, '0 0 0');
-                       ResetBall(e);
-               }
-               else
-                       this.items |= IT_KEY1;
-       }
-}
-
-void relocate_nexball(entity this)
-{
-       tracebox(this.origin, BALL_MINS, BALL_MAXS, this.origin, true, this);
-       if(trace_startsolid)
-       {
-               vector o = this.origin;
-               if (!move_out_of_solid(this)) {
-                       objerror(this, "could not get out of solid at all!");
-        }
-        LOG_INFOF(
-            "^1NOTE: this map needs FIXING. %s at %s needs to be moved out of solid, e.g. by %s",
-            this.classname,
-            vtos(o - '0 0 1'),
-            vtos(this.origin - o)
-        );
-               this.origin = o;
-       }
-}
-
-void DropOwner(entity this)
-{
-       entity ownr;
-       ownr = this.owner;
-       DropBall(this, ownr.origin, ownr.velocity);
-       makevectors(ownr.v_angle.y * '0 1 0');
-       ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
-       UNSET_ONGROUND(ownr);
-}
-
-void GiveBall(entity plyr, entity ball)
-{
-       .entity weaponentity = weaponentities[0]; // TODO: find ballstealer
-       entity ownr = ball.owner;
-       if(ownr)
-       {
-               ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
-               ownr.ballcarried = NULL;
-               GameRules_scoring_vip(ownr, false);
-               if(STAT(NB_METERSTART, ownr))
-               {
-                       STAT(NB_METERSTART, ownr) = 0;
-                       ownr.(weaponentity).state = WS_READY;
-               }
-               WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
-       }
-       else
-       {
-               WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
-       }
-
-       //setattachment(ball, plyr, "");
-       setorigin(ball, plyr.origin + plyr.view_ofs);
-
-       if(ball.team != plyr.team)
-               ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
-
-       ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
-       ball.weaponentity_fld = weaponentity;
-       ball.team = plyr.team;
-       plyr.ballcarried = ball;
-       GameRules_scoring_vip(plyr, true);
-       ball.nb_dropper = plyr;
-
-       plyr.effects |= autocvar_g_nexball_basketball_effects_default;
-       ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
-       ball.velocity = '0 0 0';
-       set_movetype(ball, MOVETYPE_NONE);
-       settouch(ball, func_null);
-       ball.effects |= EF_NOSHADOW;
-       ball.scale = 1; // scale down.
-
-       WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
-       WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
-       if(autocvar_g_nexball_basketball_delay_hold)
-       {
-               setthink(ball, DropOwner);
-               ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
-       }
-
-       STAT(WEAPONS, plyr.(weaponentity)) = STAT(WEAPONS, plyr);
-       plyr.m_switchweapon = plyr.(weaponentity).m_weapon;
-       STAT(WEAPONS, plyr) = WEPSET(NEXBALL);
-       Weapon w = WEP_NEXBALL;
-       w.wr_resetplayer(w, plyr);
-       plyr.(weaponentity).m_switchweapon = WEP_NEXBALL;
-       W_SwitchWeapon(plyr, WEP_NEXBALL, weaponentity);
-}
-
-void DropBall(entity ball, vector org, vector vel)
-{
-       ball.effects |= autocvar_g_nexball_basketball_effects_default;
-       ball.effects &= ~EF_NOSHADOW;
-       ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
-       setattachment(ball, NULL, "");
-       setorigin(ball, org);
-       set_movetype(ball, MOVETYPE_BOUNCE);
-       UNSET_ONGROUND(ball);
-       ball.scale = ball_scale;
-       ball.velocity = vel;
-       ball.nb_droptime = time;
-       settouch(ball, basketball_touch);
-       setthink(ball, ResetBall);
-       ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
-
-       if(STAT(NB_METERSTART, ball.owner))
-       {
-               STAT(NB_METERSTART, ball.owner) = 0;
-               .entity weaponentity = ball.weaponentity_fld;
-               ball.owner.(weaponentity).state = WS_READY;
-       }
-
-       WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
-       WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
-       WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
-       entity e = ball.owner; ball.owner = NULL;
-       e.ballcarried = NULL;
-       GameRules_scoring_vip(e, false);
-}
-
-void InitBall(entity this)
-{
-       if(game_stopped) return;
-       UNSET_ONGROUND(this);
-       set_movetype(this, MOVETYPE_BOUNCE);
-       if(this.classname == "nexball_basketball")
-               settouch(this, basketball_touch);
-       else if(this.classname == "nexball_football")
-               settouch(this, football_touch);
-       this.cnt = 0;
-       setthink(this, ResetBall);
-       this.nextthink = time + autocvar_g_nexball_delay_idle + 3;
-       this.teamtime = 0;
-       this.pusher = NULL;
-       this.team = false;
-       _sound(this, CH_TRIGGER, this.noise1, VOL_BASE, ATTEN_NORM);
-       WaypointSprite_Ping(this.waypointsprite_attachedforcarrier);
-       LogNB("init", NULL);
-}
-
-void ResetBall(entity this)
-{
-       if(this.cnt < 2)        // step 1
-       {
-               if(time == this.teamtime)
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
-
-               settouch(this, func_null);
-               set_movetype(this, MOVETYPE_NOCLIP);
-               this.velocity = '0 0 0'; // just in case?
-               if(!this.cnt)
-                       LogNB("resetidle", NULL);
-               this.cnt = 2;
-               this.nextthink = time;
-       }
-       else if(this.cnt < 4)     // step 2 and 3
-       {
-//             dprint("Step ", ftos(this.cnt), ": Calculated velocity: ", vtos(this.spawnorigin - this.origin), ", time: ", ftos(time), "\n");
-               this.velocity = (this.spawnorigin - this.origin) * (this.cnt - 1); // 1 or 0.5 second movement
-               this.nextthink = time + 0.5;
-               this.cnt += 1;
-       }
-       else     // step 4
-       {
-//             dprint("Step 4: time: ", ftos(time), "\n");
-               if(vdist(this.origin - this.spawnorigin, >, 10)) // should not happen anymore
-                       LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
-                                  vtos(this.origin - this.spawnorigin), " Velocity: ", vtos(this.velocity), "\n");
-               this.velocity = '0 0 0';
-               setorigin(this, this.spawnorigin); // make sure it's positioned correctly anyway
-               set_movetype(this, MOVETYPE_NONE);
-               setthink(this, InitBall);
-               this.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
-       }
-}
-
-void football_touch(entity this, entity toucher)
-{
-       if(toucher.solid == SOLID_BSP)
-       {
-               if(time > this.lastground + 0.1)
-               {
-                       _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
-                       this.lastground = time;
-               }
-               if(this.velocity && !this.cnt)
-                       this.nextthink = time + autocvar_g_nexball_delay_idle;
-               return;
-       }
-       if (!IS_PLAYER(toucher) && !IS_VEHICLE(toucher))
-               return;
-       if(GetResource(toucher, RES_HEALTH) < 1)
-               return;
-       if(!this.cnt)
-               this.nextthink = time + autocvar_g_nexball_delay_idle;
-
-       this.pusher = toucher;
-       this.team = toucher.team;
-
-       if(autocvar_g_nexball_football_physics == -1)   // MrBougo try 1, before decompiling Rev's original
-       {
-               if(toucher.velocity)
-                       this.velocity = toucher.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
-       }
-       else if(autocvar_g_nexball_football_physics == 1)         // MrBougo's modded Rev style: partially independant of the height of the aiming point
-       {
-               makevectors(toucher.v_angle);
-               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
-       }
-       else if(autocvar_g_nexball_football_physics == 2)         // 2nd mod try: totally independant. Really playable!
-       {
-               makevectors(toucher.v_angle.y * '0 1 0');
-               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
-       }
-       else     // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
-       {
-               makevectors(toucher.v_angle);
-               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
-       }
-       this.avelocity = -250 * v_forward;  // maybe there is a way to make it look better?
-}
-
-void basketball_touch(entity this, entity toucher)
-{
-       if(toucher.ballcarried)
-       {
-               football_touch(this, toucher);
-               return;
-       }
-       if(!this.cnt && IS_PLAYER(toucher) && !STAT(FROZEN, toucher) && !IS_DEAD(toucher) && (toucher != this.nb_dropper || time > this.nb_droptime + autocvar_g_nexball_delay_collect))
-       {
-               if(GetResource(toucher, RES_HEALTH) < 1)
-                       return;
-               LogNB("caught", toucher);
-               GiveBall(toucher, this);
-       }
-       else if(toucher.solid == SOLID_BSP)
-       {
-               _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
-               if(this.velocity && !this.cnt)
-                       this.nextthink = min(time + autocvar_g_nexball_delay_idle, this.teamtime);
-       }
-}
-
-void GoalTouch(entity this, entity toucher)
-{
-       entity ball;
-       float isclient, pscore, otherteam;
-       string pname;
-
-       if(game_stopped) return;
-       if((this.spawnflags & GOAL_TOUCHPLAYER) && toucher.ballcarried)
-               ball = toucher.ballcarried;
-       else
-               ball = toucher;
-       if(ball.classname != "nexball_basketball")
-               if(ball.classname != "nexball_football")
-                       return;
-       if((!ball.pusher && this.team != GOAL_OUT) || ball.cnt)
-               return;
-       EXACTTRIGGER_TOUCH(this, toucher);
-
-
-       if(NumTeams(nb_teams) == 2)
-               otherteam = OtherTeam(ball.team);
-       else
-               otherteam = 0;
-
-       if((isclient = IS_CLIENT(ball.pusher)))
-               pname = ball.pusher.netname;
-       else
-               pname = "Someone (?)";
-
-       if(ball.team == this.team)               //owngoal (regular goals)
-       {
-               LogNB("owngoal", ball.pusher);
-               bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
-               pscore = -1;
-       }
-       else if(this.team == GOAL_FAULT)
-       {
-               LogNB("fault", ball.pusher);
-               if(NumTeams(nb_teams) == 2)
-                       bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
-               else
-                       bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
-               pscore = -1;
-       }
-       else if(this.team == GOAL_OUT)
-       {
-               LogNB("out", ball.pusher);
-               if((this.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
-                       bprint(pname, "^7 went out of bounds.\n");
-               else
-                       bprint("The ball was returned.\n");
-               pscore = 0;
-       }
-       else                                                       //score
-       {
-               LogNB(strcat("goal:", ftos(this.team)), ball.pusher);
-               bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
-               pscore = 1;
-       }
-
-       _sound(ball, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NONE);
-
-       if(ball.team && pscore)
-       {
-               if(NumTeams(nb_teams) == 2 && pscore < 0)
-                       TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
-               else
-                       TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
-       }
-       if(isclient)
-       {
-               if(pscore > 0)
-                       GameRules_scoring_add(ball.pusher, NEXBALL_GOALS, pscore);
-               else if(pscore < 0)
-                       GameRules_scoring_add(ball.pusher, NEXBALL_FAULTS, -pscore);
-       }
-
-       if(ball.owner)  // Happens on spawnflag GOAL_TOUCHPLAYER
-               DropBall(ball, ball.owner.origin, ball.owner.velocity);
-
-       WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
-
-       ball.cnt = 1;
-       setthink(ball, ResetBall);
-       if(ball.classname == "nexball_basketball")
-               settouch(ball, football_touch); // better than func_null: football control until the ball gets reset
-       ball.nextthink = time + autocvar_g_nexball_delay_goal * (this.team != GOAL_OUT);
-}
-
-//=======================//
-//        team ents       //
-//=======================//
-spawnfunc(nexball_team)
-{
-       if(!g_nexball)
-       {
-               delete(this);
-               return;
-       }
-       this.team = this.cnt + 1;
-}
-
-void nb_spawnteam(string teamname, float teamcolor)
-{
-       LOG_TRACE("^2spawned team ", teamname);
-       entity e = new(nexball_team);
-       e.netname = teamname;
-       e.cnt = teamcolor;
-       e.team = e.cnt + 1;
-       //nb_teams += 1;
-}
-
-void nb_spawnteams()
-{
-       bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
-       entity e;
-       for(e = NULL; (e = find(e, classname, "nexball_goal"));)
-       {
-               switch(e.team)
-               {
-               case NUM_TEAM_1:
-                       if(!t_red)
-                       {
-                               nb_spawnteam("Red", e.team-1)   ;
-                               nb_teams |= BIT(0);
-                               t_red = true;
-                       }
-                       break;
-               case NUM_TEAM_2:
-                       if(!t_blue)
-                       {
-                               nb_spawnteam("Blue", e.team-1)  ;
-                               t_blue = true;
-                               nb_teams |= BIT(1);
-                       }
-                       break;
-               case NUM_TEAM_3:
-                       if(!t_yellow)
-                       {
-                               nb_spawnteam("Yellow", e.team-1);
-                               t_yellow = true;
-                               nb_teams |= BIT(2);
-                       }
-                       break;
-               case NUM_TEAM_4:
-                       if(!t_pink)
-                       {
-                               nb_spawnteam("Pink", e.team-1)  ;
-                               t_pink = true;
-                               nb_teams |= BIT(3);
-                       }
-                       break;
-               }
-       }
-}
-
-void nb_delayedinit(entity this)
-{
-       if(find(NULL, classname, "nexball_team") == NULL)
-               nb_spawnteams();
-       nb_ScoreRules(nb_teams);
-}
-
-
-//=======================//
-//       spawnfuncs       //
-//=======================//
-
-void SpawnBall(entity this)
-{
-       if(!g_nexball) { delete(this); return; }
-
-//     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
-
-       if(this.model == "")
-       {
-               this.model = "models/nexball/ball.md3";
-               this.scale = 1.3;
-       }
-
-       precache_model(this.model);
-       _setmodel(this, this.model);
-       setsize(this, BALL_MINS, BALL_MAXS);
-       ball_scale = this.scale;
-
-       relocate_nexball(this);
-       this.spawnorigin = this.origin;
-
-       this.effects = this.effects | EF_LOWPRECISION;
-
-       if(cvar(strcat("g_", this.classname, "_trail")))  //nexball_basketball :p
-       {
-               this.glow_color = autocvar_g_nexball_trail_color;
-               this.glow_trail = true;
-       }
-
-       set_movetype(this, MOVETYPE_FLY);
-
-       if(autocvar_g_nexball_playerclip_collisions)
-               this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
-
-       if(!autocvar_g_nexball_sound_bounce)
-               this.noise = "";
-       else if(this.noise == "")
-               this.noise = strzone(SND(NB_BOUNCE));
-       //bounce sound placeholder (FIXME)
-       if(this.noise1 == "")
-               this.noise1 = strzone(SND(NB_DROP));
-       //ball drop sound placeholder (FIXME)
-       if(this.noise2 == "")
-               this.noise2 = strzone(SND(NB_STEAL));
-       //stealing sound placeholder (FIXME)
-       if(this.noise) precache_sound(this.noise);
-       precache_sound(this.noise1);
-       precache_sound(this.noise2);
-
-       WaypointSprite_AttachCarrier(WP_NbBall, this, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
-
-       this.reset = ball_restart;
-       setthink(this, InitBall);
-       this.nextthink = game_starttime + autocvar_g_nexball_delay_start;
-}
-
-spawnfunc(nexball_basketball)
-{
-       nexball_mode |= NBM_BASKETBALL;
-       this.classname = "nexball_basketball";
-       if (!(balls & BALL_BASKET))
-       {
-               /*
-               CVTOV(g_nexball_basketball_effects_default);
-               CVTOV(g_nexball_basketball_delay_hold);
-               CVTOV(g_nexball_basketball_delay_hold_forteam);
-               CVTOV(g_nexball_basketball_teamsteal);
-               */
-               autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
-       }
-       if(!this.effects)
-               this.effects = autocvar_g_nexball_basketball_effects_default;
-       this.solid = SOLID_TRIGGER;
-       this.pushable = autocvar_g_nexball_basketball_jumppad;
-       balls |= BALL_BASKET;
-       this.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
-       this.bouncestop = autocvar_g_nexball_basketball_bouncestop;
-       SpawnBall(this);
-}
-
-spawnfunc(nexball_football)
-{
-       nexball_mode |= NBM_FOOTBALL;
-       this.classname = "nexball_football";
-       this.solid = SOLID_TRIGGER;
-       balls |= BALL_FOOT;
-       this.pushable = autocvar_g_nexball_football_jumppad;
-       this.bouncefactor = autocvar_g_nexball_football_bouncefactor;
-       this.bouncestop = autocvar_g_nexball_football_bouncestop;
-       SpawnBall(this);
-}
-
-bool nb_Goal_Customize(entity this, entity client)
-{
-       entity e = WaypointSprite_getviewentity(client);
-       entity wp_owner = this.owner;
-       if(SAME_TEAM(e, wp_owner)) { return false; }
-
-       return true;
-}
-
-void SpawnGoal(entity this)
-{
-       if(!g_nexball) { delete(this); return; }
-
-       EXACTTRIGGER_INIT;
-
-       if(this.team != GOAL_OUT && Team_IsValidTeam(this.team))
-       {
-               entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE);
-               wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0');
-               setcefc(this.sprite, nb_Goal_Customize);
-       }
-
-       this.classname = "nexball_goal";
-       if(this.noise == "")
-               this.noise = "ctf/respawn.wav";
-       precache_sound(this.noise);
-       settouch(this, GoalTouch);
-}
-
-spawnfunc(nexball_redgoal)
-{
-       this.team = NUM_TEAM_1;
-       SpawnGoal(this);
-}
-spawnfunc(nexball_bluegoal)
-{
-       this.team = NUM_TEAM_2;
-       SpawnGoal(this);
-}
-spawnfunc(nexball_yellowgoal)
-{
-       this.team = NUM_TEAM_3;
-       SpawnGoal(this);
-}
-spawnfunc(nexball_pinkgoal)
-{
-       this.team = NUM_TEAM_4;
-       SpawnGoal(this);
-}
-
-spawnfunc(nexball_fault)
-{
-       this.team = GOAL_FAULT;
-       if(this.noise == "")
-               this.noise = strzone(SND(TYPEHIT));
-       SpawnGoal(this);
-}
-
-spawnfunc(nexball_out)
-{
-       this.team = GOAL_OUT;
-       if(this.noise == "")
-               this.noise = strzone(SND(TYPEHIT));
-       SpawnGoal(this);
-}
-
-//
-//Spawnfuncs preserved for compatibility
-//
-
-spawnfunc(ball)
-{
-       spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_football)
-{
-       spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_basketball)
-{
-       spawnfunc_nexball_basketball(this);
-}
-// The "red goal" is defended by blue team. A ball in there counts as a point for red.
-spawnfunc(ball_redgoal)
-{
-       spawnfunc_nexball_bluegoal(this);       // I blame Revenant
-}
-spawnfunc(ball_bluegoal)
-{
-       spawnfunc_nexball_redgoal(this);        // but he didn't mean to cause trouble :p
-}
-spawnfunc(ball_fault)
-{
-       spawnfunc_nexball_fault(this);
-}
-spawnfunc(ball_bound)
-{
-       spawnfunc_nexball_out(this);
-}
-
-bool ball_customize(entity this, entity client)
-{
-       if(!this.owner)
-       {
-               this.effects &= ~EF_FLAME;
-               this.scale = 1;
-               setcefc(this, func_null);
-               return true;
-       }
-
-       if(client == this.owner)
-       {
-               this.scale = autocvar_g_nexball_viewmodel_scale;
-               if(this.enemy)
-                       this.effects |= EF_FLAME;
-               else
-                       this.effects &= ~EF_FLAME;
-       }
-       else
-       {
-               this.effects &= ~EF_FLAME;
-               this.scale = 1;
-       }
-
-       return true;
-}
-
-void nb_DropBall(entity player)
-{
-       if(player.ballcarried && g_nexball)
-               DropBall(player.ballcarried, player.origin, player.velocity);
-}
-
-MUTATOR_HOOKFUNCTION(nb, ClientDisconnect)
-{
-       entity player = M_ARGV(0, entity);
-
-       nb_DropBall(player);
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerDies)
-{
-       entity frag_target = M_ARGV(2, entity);
-
-       nb_DropBall(frag_target);
-}
-
-MUTATOR_HOOKFUNCTION(nb, MakePlayerObserver)
-{
-       entity player = M_ARGV(0, entity);
-
-       nb_DropBall(player);
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
-{
-       entity player = M_ARGV(0, entity);
-
-       makevectors(player.v_angle);
-       if(nexball_mode & NBM_BASKETBALL)
-       {
-               if(player.ballcarried)
-               {
-                       // 'view ball'
-                       player.ballcarried.velocity = player.velocity;
-                       setcefc(player.ballcarried, ball_customize);
-
-                       vector org = player.origin + player.view_ofs +
-                                         v_forward * autocvar_g_nexball_viewmodel_offset.x +
-                                         v_right * autocvar_g_nexball_viewmodel_offset.y +
-                                         v_up * autocvar_g_nexball_viewmodel_offset.z;
-                       setorigin(player.ballcarried, org);
-
-                       // 'safe passing'
-                       if(autocvar_g_nexball_safepass_maxdist)
-                       {
-                               if(player.ballcarried.wait < time && player.ballcarried.enemy)
-                               {
-                                       //centerprint(player, sprintf("Lost lock on %s", player.ballcarried.enemy.netname));
-                                       player.ballcarried.enemy = NULL;
-                               }
-
-
-                               //tracebox(player.origin + player.view_ofs, '-2 -2 -2', '2 2 2', player.origin + player.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
-                               crosshair_trace(player);
-                               if( trace_ent &&
-                                       IS_CLIENT(trace_ent) &&
-                                       !IS_DEAD(trace_ent) &&
-                                       trace_ent.team == player.team &&
-                                       vdist(trace_ent.origin - player.origin, <=, autocvar_g_nexball_safepass_maxdist) )
-                               {
-
-                                       //if(player.ballcarried.enemy != trace_ent)
-                                       //      centerprint(player, sprintf("Locked to %s", trace_ent.netname));
-                                       player.ballcarried.enemy = trace_ent;
-                                       player.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
-
-
-                               }
-                       }
-               }
-               else
-               {
-                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-                       {
-                               .entity weaponentity = weaponentities[slot];
-
-                               if(STAT(WEAPONS, player.(weaponentity)))
-                               {
-                                       STAT(WEAPONS, player) = STAT(WEAPONS, player.(weaponentity));
-                                       Weapon w = WEP_NEXBALL;
-                                       w.wr_resetplayer(w, player);
-                                       player.(weaponentity).m_switchweapon = player.m_switchweapon;
-                                       W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
-
-                                       STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
-                               }
-                       }
-               }
-
-       }
-
-       nexball_setstatus(player);
-}
-
-MUTATOR_HOOKFUNCTION(nb, SpectateCopy)
-{
-       entity spectatee = M_ARGV(0, entity);
-       entity client = M_ARGV(1, entity);
-
-       STAT(NB_METERSTART, client) = STAT(NB_METERSTART, spectatee);
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerSpawn)
-{
-       entity player = M_ARGV(0, entity);
-
-       STAT(NB_METERSTART, player) = 0;
-       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       {
-               .entity weaponentity = weaponentities[slot];
-               STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
-       }
-
-       if (nexball_mode & NBM_BASKETBALL)
-               STAT(WEAPONS, player) |= WEPSET(NEXBALL);
-       else
-               STAT(WEAPONS, player) = '0 0 0';
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerPhysics_UpdateStats)
-{
-       entity player = M_ARGV(0, entity);
-       // these automatically reset, no need to worry
-
-       if(player.ballcarried)
-               STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_nexball_basketball_carrier_highspeed;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
-{
-       //entity player = M_ARGV(0, entity);
-       entity wepent = M_ARGV(1, entity);
-
-       return wepent.m_weapon == WEP_NEXBALL;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
-{
-       //entity player = M_ARGV(0, entity);
-       int wep = M_ARGV(1, int);
-
-       return wep == WEP_MORTAR.m_id; // TODO: what is this for?
-}
-
-MUTATOR_HOOKFUNCTION(nb, FilterItem)
-{
-       entity item = M_ARGV(0, entity);
-
-       if(Item_IsLoot(item))
-       if(item.weapon == WEP_NEXBALL.m_id)
-               return true;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ItemTouch)
-{
-       entity item = M_ARGV(0, entity);
-       entity toucher = M_ARGV(1, entity);
-
-       if(item.weapon && toucher.ballcarried)
-               return MUT_ITEMTOUCH_RETURN; // no new weapons for you, mister!
-
-       return MUT_ITEMTOUCH_CONTINUE;
-}
-
-MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
-{
-       M_ARGV(1, string) = "nexball_team";
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(nb, WantWeapon)
-{
-       M_ARGV(1, float) = 0; // weapon is set a few lines later, apparently
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(nb, DropSpecialItems)
-{
-       entity frag_target = M_ARGV(0, entity);
-
-       if(frag_target.ballcarried)
-               DropBall(frag_target.ballcarried, frag_target.origin, frag_target.velocity);
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, SendWaypoint)
-{
-       M_ARGV(2, int) &= ~0x80;
-}
-
-REGISTER_MUTATOR(nb, g_nexball)
-{
-    MUTATOR_STATIC();
-       MUTATOR_ONADD
-       {
-               g_nexball_meter_period = autocvar_g_nexball_meter_period;
-               if(g_nexball_meter_period <= 0)
-                       g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
-               g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
-
-               // General settings
-               /*
-               CVTOV(g_nexball_football_boost_forward);   //100
-               CVTOV(g_nexball_football_boost_up);             //200
-               CVTOV(g_nexball_delay_idle);                       //10
-               CVTOV(g_nexball_football_physics);               //0
-               */
-               radar_showennemies = autocvar_g_nexball_radar_showallplayers;
-
-               InitializeEntity(NULL, nb_delayedinit, INITPRIO_GAMETYPE);
-               WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
-
-               GameRules_teams(true);
-               GameRules_limit_score(autocvar_g_nexball_goallimit);
-               GameRules_limit_lead(autocvar_g_nexball_goalleadlimit);
-       }
-
-       MUTATOR_ONROLLBACK_OR_REMOVE
-       {
-               WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
-       }
-       return 0;
-}
-
-#endif
index 53797d2bc6d245dc7de9ee17abaa5143836a5e31..6f70f09beec2219624baeca92e2cd7deaa104fb4 100644 (file)
@@ -1,36 +1 @@
 #pragma once
-
-#ifdef SVQC
-//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
-const float BALL_EFFECTMASK = 1229;
-const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
-const vector BALL_MAXS = '16 16 16';
-const vector BALL_ATTACHORG = '3 0 16';
-const float BALL_FOOT = 1;
-const float BALL_BASKET = 2;
-//spawnflags
-const float GOAL_TOUCHPLAYER = 1;
-//goal types
-const float GOAL_FAULT = -1;
-const float GOAL_OUT = -2;
-
-void DropBall(entity ball, vector org, vector vel);
-float autocvar_g_nexball_football_boost_forward;
-float autocvar_g_nexball_football_boost_up;
-float autocvar_g_nexball_football_physics;
-float autocvar_g_nexball_delay_idle;
-float autocvar_g_nexball_basketball_delay_hold;
-float autocvar_g_nexball_basketball_delay_hold_forteam;
-float autocvar_g_nexball_basketball_effects_default;
-float autocvar_g_nexball_basketball_teamsteal;
-float autocvar_g_nexball_meter_period;
-
-float balls;
-float ball_scale;
-float nb_teams;
-
-.entity nb_dropper;
-.float nb_droptime;
-
-.float teamtime;
-#endif
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc
new file mode 100644 (file)
index 0000000..38b7a7f
--- /dev/null
@@ -0,0 +1,969 @@
+#include "sv_nexball.qh"
+
+.entity ballcarried;
+
+int autocvar_g_nexball_goalleadlimit;
+#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
+
+bool autocvar_g_nexball_basketball_jumppad = true;
+float autocvar_g_nexball_basketball_bouncefactor;
+float autocvar_g_nexball_basketball_bouncestop;
+float autocvar_g_nexball_basketball_carrier_highspeed;
+bool autocvar_g_nexball_basketball_meter;
+float autocvar_g_nexball_basketball_meter_maxpower;
+float autocvar_g_nexball_basketball_meter_minpower;
+float autocvar_g_nexball_delay_collect;
+float autocvar_g_nexball_delay_goal;
+float autocvar_g_nexball_delay_start;
+bool autocvar_g_nexball_football_jumppad = true;
+float autocvar_g_nexball_football_bouncefactor;
+float autocvar_g_nexball_football_bouncestop;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
+bool autocvar_g_nexball_playerclip_collisions = true;
+
+float autocvar_g_nexball_safepass_turnrate;
+float autocvar_g_nexball_safepass_maxdist;
+float autocvar_g_nexball_safepass_holdtime;
+float autocvar_g_nexball_viewmodel_scale;
+float autocvar_g_nexball_tackling;
+vector autocvar_g_nexball_viewmodel_offset;
+
+float autocvar_g_balance_nexball_primary_animtime;
+float autocvar_g_balance_nexball_primary_refire;
+float autocvar_g_balance_nexball_primary_speed;
+float autocvar_g_balance_nexball_secondary_animtime;
+float autocvar_g_balance_nexball_secondary_force;
+float autocvar_g_balance_nexball_secondary_lifetime;
+float autocvar_g_balance_nexball_secondary_refire;
+float autocvar_g_balance_nexball_secondary_speed;
+
+void basketball_touch(entity this, entity toucher);
+void football_touch(entity this, entity toucher);
+void ResetBall(entity this);
+const int NBM_NONE = 0;
+const int NBM_FOOTBALL = 2;
+const int NBM_BASKETBALL = 4;
+float nexball_mode;
+
+float OtherTeam(float t)  //works only if there are two teams on the map!
+{
+       entity e;
+       e = find(NULL, classname, "nexball_team");
+       if(e.team == t)
+               e = find(e, classname, "nexball_team");
+       return e.team;
+}
+
+const int ST_NEXBALL_GOALS = 1;
+void nb_ScoreRules(int teams)
+{
+    GameRules_scoring(teams, 0, 0, {
+        field_team(ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+        field(SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+        field(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
+    });
+}
+
+void LogNB(string mode, entity actor)
+{
+       string s;
+       if(!autocvar_sv_eventlog)
+               return;
+       s = strcat(":nexball:", mode);
+       if(actor != NULL)
+               s = strcat(s, ":", ftos(actor.playerid));
+       GameLogEcho(s);
+}
+
+void ball_restart(entity this)
+{
+       if(this.owner)
+               DropBall(this, this.owner.origin, '0 0 0');
+       ResetBall(this);
+}
+
+void nexball_setstatus(entity this)
+{
+       this.items &= ~IT_KEY1;
+       if(this.ballcarried)
+       {
+               if(this.ballcarried.teamtime && (this.ballcarried.teamtime < time))
+               {
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
+                       entity e = this.ballcarried;
+                       DropBall(this.ballcarried, this.ballcarried.owner.origin, '0 0 0');
+                       ResetBall(e);
+               }
+               else
+                       this.items |= IT_KEY1;
+       }
+}
+
+void relocate_nexball(entity this)
+{
+       tracebox(this.origin, BALL_MINS, BALL_MAXS, this.origin, true, this);
+       if(trace_startsolid)
+       {
+               vector o = this.origin;
+               if (!move_out_of_solid(this)) {
+                       objerror(this, "could not get out of solid at all!");
+        }
+        LOG_INFOF(
+            "^1NOTE: this map needs FIXING. %s at %s needs to be moved out of solid, e.g. by %s",
+            this.classname,
+            vtos(o - '0 0 1'),
+            vtos(this.origin - o)
+        );
+               this.origin = o;
+       }
+}
+
+void DropOwner(entity this)
+{
+       entity ownr;
+       ownr = this.owner;
+       DropBall(this, ownr.origin, ownr.velocity);
+       makevectors(ownr.v_angle.y * '0 1 0');
+       ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
+       UNSET_ONGROUND(ownr);
+}
+
+void GiveBall(entity plyr, entity ball)
+{
+       .entity weaponentity = weaponentities[0]; // TODO: find ballstealer
+       entity ownr = ball.owner;
+       if(ownr)
+       {
+               ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
+               ownr.ballcarried = NULL;
+               GameRules_scoring_vip(ownr, false);
+               if(STAT(NB_METERSTART, ownr))
+               {
+                       STAT(NB_METERSTART, ownr) = 0;
+                       ownr.(weaponentity).state = WS_READY;
+               }
+               WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
+       }
+       else
+       {
+               WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
+       }
+
+       //setattachment(ball, plyr, "");
+       setorigin(ball, plyr.origin + plyr.view_ofs);
+
+       if(ball.team != plyr.team)
+               ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
+
+       ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
+       ball.weaponentity_fld = weaponentity;
+       ball.team = plyr.team;
+       plyr.ballcarried = ball;
+       GameRules_scoring_vip(plyr, true);
+       ball.nb_dropper = plyr;
+
+       plyr.effects |= autocvar_g_nexball_basketball_effects_default;
+       ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+       ball.velocity = '0 0 0';
+       set_movetype(ball, MOVETYPE_NONE);
+       settouch(ball, func_null);
+       ball.effects |= EF_NOSHADOW;
+       ball.scale = 1; // scale down.
+
+       WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
+       WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+       if(autocvar_g_nexball_basketball_delay_hold)
+       {
+               setthink(ball, DropOwner);
+               ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
+       }
+
+       STAT(WEAPONS, plyr.(weaponentity)) = STAT(WEAPONS, plyr);
+       plyr.m_switchweapon = plyr.(weaponentity).m_weapon;
+       STAT(WEAPONS, plyr) = WEPSET(NEXBALL);
+       Weapon w = WEP_NEXBALL;
+       w.wr_resetplayer(w, plyr);
+       plyr.(weaponentity).m_switchweapon = WEP_NEXBALL;
+       W_SwitchWeapon(plyr, WEP_NEXBALL, weaponentity);
+}
+
+void DropBall(entity ball, vector org, vector vel)
+{
+       ball.effects |= autocvar_g_nexball_basketball_effects_default;
+       ball.effects &= ~EF_NOSHADOW;
+       ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+       setattachment(ball, NULL, "");
+       setorigin(ball, org);
+       set_movetype(ball, MOVETYPE_BOUNCE);
+       UNSET_ONGROUND(ball);
+       ball.scale = ball_scale;
+       ball.velocity = vel;
+       ball.nb_droptime = time;
+       settouch(ball, basketball_touch);
+       setthink(ball, ResetBall);
+       ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
+
+       if(STAT(NB_METERSTART, ball.owner))
+       {
+               STAT(NB_METERSTART, ball.owner) = 0;
+               .entity weaponentity = ball.weaponentity_fld;
+               ball.owner.(weaponentity).state = WS_READY;
+       }
+
+       WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
+       WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
+       WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+       entity e = ball.owner; ball.owner = NULL;
+       e.ballcarried = NULL;
+       GameRules_scoring_vip(e, false);
+}
+
+void InitBall(entity this)
+{
+       if(game_stopped) return;
+       UNSET_ONGROUND(this);
+       set_movetype(this, MOVETYPE_BOUNCE);
+       if(this.classname == "nexball_basketball")
+               settouch(this, basketball_touch);
+       else if(this.classname == "nexball_football")
+               settouch(this, football_touch);
+       this.cnt = 0;
+       setthink(this, ResetBall);
+       this.nextthink = time + autocvar_g_nexball_delay_idle + 3;
+       this.teamtime = 0;
+       this.pusher = NULL;
+       this.team = false;
+       _sound(this, CH_TRIGGER, this.noise1, VOL_BASE, ATTEN_NORM);
+       WaypointSprite_Ping(this.waypointsprite_attachedforcarrier);
+       LogNB("init", NULL);
+}
+
+void ResetBall(entity this)
+{
+       if(this.cnt < 2)        // step 1
+       {
+               if(time == this.teamtime)
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
+
+               settouch(this, func_null);
+               set_movetype(this, MOVETYPE_NOCLIP);
+               this.velocity = '0 0 0'; // just in case?
+               if(!this.cnt)
+                       LogNB("resetidle", NULL);
+               this.cnt = 2;
+               this.nextthink = time;
+       }
+       else if(this.cnt < 4)     // step 2 and 3
+       {
+//             dprint("Step ", ftos(this.cnt), ": Calculated velocity: ", vtos(this.spawnorigin - this.origin), ", time: ", ftos(time), "\n");
+               this.velocity = (this.spawnorigin - this.origin) * (this.cnt - 1); // 1 or 0.5 second movement
+               this.nextthink = time + 0.5;
+               this.cnt += 1;
+       }
+       else     // step 4
+       {
+//             dprint("Step 4: time: ", ftos(time), "\n");
+               if(vdist(this.origin - this.spawnorigin, >, 10)) // should not happen anymore
+                       LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
+                                  vtos(this.origin - this.spawnorigin), " Velocity: ", vtos(this.velocity), "\n");
+               this.velocity = '0 0 0';
+               setorigin(this, this.spawnorigin); // make sure it's positioned correctly anyway
+               set_movetype(this, MOVETYPE_NONE);
+               setthink(this, InitBall);
+               this.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
+       }
+}
+
+void football_touch(entity this, entity toucher)
+{
+       if(toucher.solid == SOLID_BSP)
+       {
+               if(time > this.lastground + 0.1)
+               {
+                       _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+                       this.lastground = time;
+               }
+               if(this.velocity && !this.cnt)
+                       this.nextthink = time + autocvar_g_nexball_delay_idle;
+               return;
+       }
+       if (!IS_PLAYER(toucher) && !IS_VEHICLE(toucher))
+               return;
+       if(GetResource(toucher, RES_HEALTH) < 1)
+               return;
+       if(!this.cnt)
+               this.nextthink = time + autocvar_g_nexball_delay_idle;
+
+       this.pusher = toucher;
+       this.team = toucher.team;
+
+       if(autocvar_g_nexball_football_physics == -1)   // MrBougo try 1, before decompiling Rev's original
+       {
+               if(toucher.velocity)
+                       this.velocity = toucher.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
+       }
+       else if(autocvar_g_nexball_football_physics == 1)         // MrBougo's modded Rev style: partially independant of the height of the aiming point
+       {
+               makevectors(toucher.v_angle);
+               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
+       }
+       else if(autocvar_g_nexball_football_physics == 2)         // 2nd mod try: totally independant. Really playable!
+       {
+               makevectors(toucher.v_angle.y * '0 1 0');
+               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+       }
+       else     // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
+       {
+               makevectors(toucher.v_angle);
+               this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+       }
+       this.avelocity = -250 * v_forward;  // maybe there is a way to make it look better?
+}
+
+void basketball_touch(entity this, entity toucher)
+{
+       if(toucher.ballcarried)
+       {
+               football_touch(this, toucher);
+               return;
+       }
+       if(!this.cnt && IS_PLAYER(toucher) && !STAT(FROZEN, toucher) && !IS_DEAD(toucher) && (toucher != this.nb_dropper || time > this.nb_droptime + autocvar_g_nexball_delay_collect))
+       {
+               if(GetResource(toucher, RES_HEALTH) < 1)
+                       return;
+               LogNB("caught", toucher);
+               GiveBall(toucher, this);
+       }
+       else if(toucher.solid == SOLID_BSP)
+       {
+               _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+               if(this.velocity && !this.cnt)
+                       this.nextthink = min(time + autocvar_g_nexball_delay_idle, this.teamtime);
+       }
+}
+
+void GoalTouch(entity this, entity toucher)
+{
+       entity ball;
+       float isclient, pscore, otherteam;
+       string pname;
+
+       if(game_stopped) return;
+       if((this.spawnflags & GOAL_TOUCHPLAYER) && toucher.ballcarried)
+               ball = toucher.ballcarried;
+       else
+               ball = toucher;
+       if(ball.classname != "nexball_basketball")
+               if(ball.classname != "nexball_football")
+                       return;
+       if((!ball.pusher && this.team != GOAL_OUT) || ball.cnt)
+               return;
+       EXACTTRIGGER_TOUCH(this, toucher);
+
+
+       if(NumTeams(nb_teams) == 2)
+               otherteam = OtherTeam(ball.team);
+       else
+               otherteam = 0;
+
+       if((isclient = IS_CLIENT(ball.pusher)))
+               pname = ball.pusher.netname;
+       else
+               pname = "Someone (?)";
+
+       if(ball.team == this.team)               //owngoal (regular goals)
+       {
+               LogNB("owngoal", ball.pusher);
+               bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
+               pscore = -1;
+       }
+       else if(this.team == GOAL_FAULT)
+       {
+               LogNB("fault", ball.pusher);
+               if(NumTeams(nb_teams) == 2)
+                       bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
+               else
+                       bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
+               pscore = -1;
+       }
+       else if(this.team == GOAL_OUT)
+       {
+               LogNB("out", ball.pusher);
+               if((this.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
+                       bprint(pname, "^7 went out of bounds.\n");
+               else
+                       bprint("The ball was returned.\n");
+               pscore = 0;
+       }
+       else                                                       //score
+       {
+               LogNB(strcat("goal:", ftos(this.team)), ball.pusher);
+               bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
+               pscore = 1;
+       }
+
+       _sound(ball, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NONE);
+
+       if(ball.team && pscore)
+       {
+               if(NumTeams(nb_teams) == 2 && pscore < 0)
+                       TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
+               else
+                       TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
+       }
+       if(isclient)
+       {
+               if(pscore > 0)
+                       GameRules_scoring_add(ball.pusher, NEXBALL_GOALS, pscore);
+               else if(pscore < 0)
+                       GameRules_scoring_add(ball.pusher, NEXBALL_FAULTS, -pscore);
+       }
+
+       if(ball.owner)  // Happens on spawnflag GOAL_TOUCHPLAYER
+               DropBall(ball, ball.owner.origin, ball.owner.velocity);
+
+       WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
+
+       ball.cnt = 1;
+       setthink(ball, ResetBall);
+       if(ball.classname == "nexball_basketball")
+               settouch(ball, football_touch); // better than func_null: football control until the ball gets reset
+       ball.nextthink = time + autocvar_g_nexball_delay_goal * (this.team != GOAL_OUT);
+}
+
+//=======================//
+//        team ents       //
+//=======================//
+spawnfunc(nexball_team)
+{
+       if(!g_nexball)
+       {
+               delete(this);
+               return;
+       }
+       this.team = this.cnt + 1;
+}
+
+void nb_spawnteam(string teamname, float teamcolor)
+{
+       LOG_TRACE("^2spawned team ", teamname);
+       entity e = new(nexball_team);
+       e.netname = teamname;
+       e.cnt = teamcolor;
+       e.team = e.cnt + 1;
+       //nb_teams += 1;
+}
+
+void nb_spawnteams()
+{
+       bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
+       entity e;
+       for(e = NULL; (e = find(e, classname, "nexball_goal"));)
+       {
+               switch(e.team)
+               {
+               case NUM_TEAM_1:
+                       if(!t_red)
+                       {
+                               nb_spawnteam("Red", e.team-1)   ;
+                               nb_teams |= BIT(0);
+                               t_red = true;
+                       }
+                       break;
+               case NUM_TEAM_2:
+                       if(!t_blue)
+                       {
+                               nb_spawnteam("Blue", e.team-1)  ;
+                               t_blue = true;
+                               nb_teams |= BIT(1);
+                       }
+                       break;
+               case NUM_TEAM_3:
+                       if(!t_yellow)
+                       {
+                               nb_spawnteam("Yellow", e.team-1);
+                               t_yellow = true;
+                               nb_teams |= BIT(2);
+                       }
+                       break;
+               case NUM_TEAM_4:
+                       if(!t_pink)
+                       {
+                               nb_spawnteam("Pink", e.team-1)  ;
+                               t_pink = true;
+                               nb_teams |= BIT(3);
+                       }
+                       break;
+               }
+       }
+}
+
+void nb_delayedinit(entity this)
+{
+       if(find(NULL, classname, "nexball_team") == NULL)
+               nb_spawnteams();
+       nb_ScoreRules(nb_teams);
+}
+
+
+//=======================//
+//       spawnfuncs       //
+//=======================//
+
+void SpawnBall(entity this)
+{
+       if(!g_nexball) { delete(this); return; }
+
+//     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
+
+       if(this.model == "")
+       {
+               this.model = "models/nexball/ball.md3";
+               this.scale = 1.3;
+       }
+
+       precache_model(this.model);
+       _setmodel(this, this.model);
+       setsize(this, BALL_MINS, BALL_MAXS);
+       ball_scale = this.scale;
+
+       relocate_nexball(this);
+       this.spawnorigin = this.origin;
+
+       this.effects = this.effects | EF_LOWPRECISION;
+
+       if(cvar(strcat("g_", this.classname, "_trail")))  //nexball_basketball :p
+       {
+               this.glow_color = autocvar_g_nexball_trail_color;
+               this.glow_trail = true;
+       }
+
+       set_movetype(this, MOVETYPE_FLY);
+
+       if(autocvar_g_nexball_playerclip_collisions)
+               this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
+
+       if(!autocvar_g_nexball_sound_bounce)
+               this.noise = "";
+       else if(this.noise == "")
+               this.noise = strzone(SND(NB_BOUNCE));
+       //bounce sound placeholder (FIXME)
+       if(this.noise1 == "")
+               this.noise1 = strzone(SND(NB_DROP));
+       //ball drop sound placeholder (FIXME)
+       if(this.noise2 == "")
+               this.noise2 = strzone(SND(NB_STEAL));
+       //stealing sound placeholder (FIXME)
+       if(this.noise) precache_sound(this.noise);
+       precache_sound(this.noise1);
+       precache_sound(this.noise2);
+
+       WaypointSprite_AttachCarrier(WP_NbBall, this, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
+
+       this.reset = ball_restart;
+       setthink(this, InitBall);
+       this.nextthink = game_starttime + autocvar_g_nexball_delay_start;
+}
+
+spawnfunc(nexball_basketball)
+{
+       nexball_mode |= NBM_BASKETBALL;
+       this.classname = "nexball_basketball";
+       if (!(balls & BALL_BASKET))
+       {
+               /*
+               CVTOV(g_nexball_basketball_effects_default);
+               CVTOV(g_nexball_basketball_delay_hold);
+               CVTOV(g_nexball_basketball_delay_hold_forteam);
+               CVTOV(g_nexball_basketball_teamsteal);
+               */
+               autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
+       }
+       if(!this.effects)
+               this.effects = autocvar_g_nexball_basketball_effects_default;
+       this.solid = SOLID_TRIGGER;
+       this.pushable = autocvar_g_nexball_basketball_jumppad;
+       balls |= BALL_BASKET;
+       this.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
+       this.bouncestop = autocvar_g_nexball_basketball_bouncestop;
+       SpawnBall(this);
+}
+
+spawnfunc(nexball_football)
+{
+       nexball_mode |= NBM_FOOTBALL;
+       this.classname = "nexball_football";
+       this.solid = SOLID_TRIGGER;
+       balls |= BALL_FOOT;
+       this.pushable = autocvar_g_nexball_football_jumppad;
+       this.bouncefactor = autocvar_g_nexball_football_bouncefactor;
+       this.bouncestop = autocvar_g_nexball_football_bouncestop;
+       SpawnBall(this);
+}
+
+bool nb_Goal_Customize(entity this, entity client)
+{
+       entity e = WaypointSprite_getviewentity(client);
+       entity wp_owner = this.owner;
+       if(SAME_TEAM(e, wp_owner)) { return false; }
+
+       return true;
+}
+
+void SpawnGoal(entity this)
+{
+       if(!g_nexball) { delete(this); return; }
+
+       EXACTTRIGGER_INIT;
+
+       if(this.team != GOAL_OUT && Team_IsValidTeam(this.team))
+       {
+               entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE);
+               wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0');
+               setcefc(this.sprite, nb_Goal_Customize);
+       }
+
+       this.classname = "nexball_goal";
+       if(this.noise == "")
+               this.noise = "ctf/respawn.wav";
+       precache_sound(this.noise);
+       settouch(this, GoalTouch);
+}
+
+spawnfunc(nexball_redgoal)
+{
+       this.team = NUM_TEAM_1;
+       SpawnGoal(this);
+}
+spawnfunc(nexball_bluegoal)
+{
+       this.team = NUM_TEAM_2;
+       SpawnGoal(this);
+}
+spawnfunc(nexball_yellowgoal)
+{
+       this.team = NUM_TEAM_3;
+       SpawnGoal(this);
+}
+spawnfunc(nexball_pinkgoal)
+{
+       this.team = NUM_TEAM_4;
+       SpawnGoal(this);
+}
+
+spawnfunc(nexball_fault)
+{
+       this.team = GOAL_FAULT;
+       if(this.noise == "")
+               this.noise = strzone(SND(TYPEHIT));
+       SpawnGoal(this);
+}
+
+spawnfunc(nexball_out)
+{
+       this.team = GOAL_OUT;
+       if(this.noise == "")
+               this.noise = strzone(SND(TYPEHIT));
+       SpawnGoal(this);
+}
+
+//
+//Spawnfuncs preserved for compatibility
+//
+
+spawnfunc(ball)
+{
+       spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_football)
+{
+       spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_basketball)
+{
+       spawnfunc_nexball_basketball(this);
+}
+// The "red goal" is defended by blue team. A ball in there counts as a point for red.
+spawnfunc(ball_redgoal)
+{
+       spawnfunc_nexball_bluegoal(this);       // I blame Revenant
+}
+spawnfunc(ball_bluegoal)
+{
+       spawnfunc_nexball_redgoal(this);        // but he didn't mean to cause trouble :p
+}
+spawnfunc(ball_fault)
+{
+       spawnfunc_nexball_fault(this);
+}
+spawnfunc(ball_bound)
+{
+       spawnfunc_nexball_out(this);
+}
+
+bool ball_customize(entity this, entity client)
+{
+       if(!this.owner)
+       {
+               this.effects &= ~EF_FLAME;
+               this.scale = 1;
+               setcefc(this, func_null);
+               return true;
+       }
+
+       if(client == this.owner)
+       {
+               this.scale = autocvar_g_nexball_viewmodel_scale;
+               if(this.enemy)
+                       this.effects |= EF_FLAME;
+               else
+                       this.effects &= ~EF_FLAME;
+       }
+       else
+       {
+               this.effects &= ~EF_FLAME;
+               this.scale = 1;
+       }
+
+       return true;
+}
+
+void nb_DropBall(entity player)
+{
+       if(player.ballcarried && g_nexball)
+               DropBall(player.ballcarried, player.origin, player.velocity);
+}
+
+MUTATOR_HOOKFUNCTION(nb, ClientDisconnect)
+{
+       entity player = M_ARGV(0, entity);
+
+       nb_DropBall(player);
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerDies)
+{
+       entity frag_target = M_ARGV(2, entity);
+
+       nb_DropBall(frag_target);
+}
+
+MUTATOR_HOOKFUNCTION(nb, MakePlayerObserver)
+{
+       entity player = M_ARGV(0, entity);
+
+       nb_DropBall(player);
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
+{
+       entity player = M_ARGV(0, entity);
+
+       makevectors(player.v_angle);
+       if(nexball_mode & NBM_BASKETBALL)
+       {
+               if(player.ballcarried)
+               {
+                       // 'view ball'
+                       player.ballcarried.velocity = player.velocity;
+                       setcefc(player.ballcarried, ball_customize);
+
+                       vector org = player.origin + player.view_ofs +
+                                         v_forward * autocvar_g_nexball_viewmodel_offset.x +
+                                         v_right * autocvar_g_nexball_viewmodel_offset.y +
+                                         v_up * autocvar_g_nexball_viewmodel_offset.z;
+                       setorigin(player.ballcarried, org);
+
+                       // 'safe passing'
+                       if(autocvar_g_nexball_safepass_maxdist)
+                       {
+                               if(player.ballcarried.wait < time && player.ballcarried.enemy)
+                               {
+                                       //centerprint(player, sprintf("Lost lock on %s", player.ballcarried.enemy.netname));
+                                       player.ballcarried.enemy = NULL;
+                               }
+
+
+                               //tracebox(player.origin + player.view_ofs, '-2 -2 -2', '2 2 2', player.origin + player.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
+                               crosshair_trace(player);
+                               if( trace_ent &&
+                                       IS_CLIENT(trace_ent) &&
+                                       !IS_DEAD(trace_ent) &&
+                                       trace_ent.team == player.team &&
+                                       vdist(trace_ent.origin - player.origin, <=, autocvar_g_nexball_safepass_maxdist) )
+                               {
+
+                                       //if(player.ballcarried.enemy != trace_ent)
+                                       //      centerprint(player, sprintf("Locked to %s", trace_ent.netname));
+                                       player.ballcarried.enemy = trace_ent;
+                                       player.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
+
+
+                               }
+                       }
+               }
+               else
+               {
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+
+                               if(STAT(WEAPONS, player.(weaponentity)))
+                               {
+                                       STAT(WEAPONS, player) = STAT(WEAPONS, player.(weaponentity));
+                                       Weapon w = WEP_NEXBALL;
+                                       w.wr_resetplayer(w, player);
+                                       player.(weaponentity).m_switchweapon = player.m_switchweapon;
+                                       W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
+
+                                       STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
+                               }
+                       }
+               }
+
+       }
+
+       nexball_setstatus(player);
+}
+
+MUTATOR_HOOKFUNCTION(nb, SpectateCopy)
+{
+       entity spectatee = M_ARGV(0, entity);
+       entity client = M_ARGV(1, entity);
+
+       STAT(NB_METERSTART, client) = STAT(NB_METERSTART, spectatee);
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerSpawn)
+{
+       entity player = M_ARGV(0, entity);
+
+       STAT(NB_METERSTART, player) = 0;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
+       }
+
+       if (nexball_mode & NBM_BASKETBALL)
+               STAT(WEAPONS, player) |= WEPSET(NEXBALL);
+       else
+               STAT(WEAPONS, player) = '0 0 0';
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerPhysics_UpdateStats)
+{
+       entity player = M_ARGV(0, entity);
+       // these automatically reset, no need to worry
+
+       if(player.ballcarried)
+               STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_nexball_basketball_carrier_highspeed;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
+{
+       //entity player = M_ARGV(0, entity);
+       entity wepent = M_ARGV(1, entity);
+
+       return wepent.m_weapon == WEP_NEXBALL;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
+{
+       //entity player = M_ARGV(0, entity);
+       int wep = M_ARGV(1, int);
+
+       return wep == WEP_MORTAR.m_id; // TODO: what is this for?
+}
+
+MUTATOR_HOOKFUNCTION(nb, FilterItem)
+{
+       entity item = M_ARGV(0, entity);
+
+       if(Item_IsLoot(item))
+       if(item.weapon == WEP_NEXBALL.m_id)
+               return true;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ItemTouch)
+{
+       entity item = M_ARGV(0, entity);
+       entity toucher = M_ARGV(1, entity);
+
+       if(item.weapon && toucher.ballcarried)
+               return MUT_ITEMTOUCH_RETURN; // no new weapons for you, mister!
+
+       return MUT_ITEMTOUCH_CONTINUE;
+}
+
+MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
+{
+       M_ARGV(1, string) = "nexball_team";
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(nb, WantWeapon)
+{
+       M_ARGV(1, float) = 0; // weapon is set a few lines later, apparently
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(nb, DropSpecialItems)
+{
+       entity frag_target = M_ARGV(0, entity);
+
+       if(frag_target.ballcarried)
+               DropBall(frag_target.ballcarried, frag_target.origin, frag_target.velocity);
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, SendWaypoint)
+{
+       M_ARGV(2, int) &= ~0x80;
+}
+
+REGISTER_MUTATOR(nb, false)
+{
+    MUTATOR_STATIC();
+       MUTATOR_ONADD
+       {
+               g_nexball_meter_period = autocvar_g_nexball_meter_period;
+               if(g_nexball_meter_period <= 0)
+                       g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
+               g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
+
+               // General settings
+               /*
+               CVTOV(g_nexball_football_boost_forward);   //100
+               CVTOV(g_nexball_football_boost_up);             //200
+               CVTOV(g_nexball_delay_idle);                       //10
+               CVTOV(g_nexball_football_physics);               //0
+               */
+               radar_showennemies = autocvar_g_nexball_radar_showallplayers;
+
+               InitializeEntity(NULL, nb_delayedinit, INITPRIO_GAMETYPE);
+               WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+
+               GameRules_teams(true);
+               GameRules_limit_score(autocvar_g_nexball_goallimit);
+               GameRules_limit_lead(autocvar_g_nexball_goalleadlimit);
+       }
+
+       MUTATOR_ONROLLBACK_OR_REMOVE
+       {
+               WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+       }
+       return 0;
+}
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh
new file mode 100644 (file)
index 0000000..d7cde3a
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once
+
+//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
+const float BALL_EFFECTMASK = 1229;
+const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
+const vector BALL_MAXS = '16 16 16';
+const vector BALL_ATTACHORG = '3 0 16';
+const float BALL_FOOT = 1;
+const float BALL_BASKET = 2;
+//spawnflags
+const float GOAL_TOUCHPLAYER = 1;
+//goal types
+const float GOAL_FAULT = -1;
+const float GOAL_OUT = -2;
+
+void DropBall(entity ball, vector org, vector vel);
+float autocvar_g_nexball_football_boost_forward;
+float autocvar_g_nexball_football_boost_up;
+float autocvar_g_nexball_football_physics;
+float autocvar_g_nexball_delay_idle;
+float autocvar_g_nexball_basketball_delay_hold;
+float autocvar_g_nexball_basketball_delay_hold_forteam;
+float autocvar_g_nexball_basketball_effects_default;
+float autocvar_g_nexball_basketball_teamsteal;
+float autocvar_g_nexball_meter_period;
+
+float balls;
+float ball_scale;
+float nb_teams;
+
+.entity nb_dropper;
+.float nb_droptime;
+
+.float teamtime;
index 73b887260c10b785d4a60c013f6dd0ef87925625..ccabc47a518c502e9196af25e26a632032e23773 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(BallStealer, PortoLaunch)
-/* flags     */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NOTRUEAIM);
 /* impulse   */ ATTRIB(BallStealer, impulse, int, 0);
 /* refname   */ ATTRIB(BallStealer, netname, string, "ballstealer");
 /* wepname   */ ATTRIB(BallStealer, m_name, string, _("Ball Stealer"));
index d4303efbd97124579a115c916b86aee7a0a54056..3128bae26684ecace22264ff3ef5fba9c3bd5d2a 100644 (file)
@@ -988,7 +988,7 @@ void ons_GeneratorThink(entity this)
                {
                        Send_Notification(NOTIF_ONE, it, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
                        msg_entity = it;
-                       soundto(MSG_ONE, this, CHAN_AUTO, SND(KH_ALARM), VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
+                       soundto(MSG_ONE, this, CHAN_AUTO, SND(ONS_GENERATOR_ALARM), VOL_BASE, ATTEN_NONE);
                }
                else
                        Send_Notification(NOTIF_ONE, it, MSG_CENTER, APP_TEAM_NUM(this.team, CENTER_ONS_NOTSHIELDED));
index 623f71b3904ab7654d9e9e88e23291c45d84bb09..3ff4a54155a3cccaf0ea91b69a38a02ac90c15dc 100644 (file)
@@ -4,7 +4,8 @@
 
 #include "item.qh"
 
-REGISTRY(Items, BITS(7))
+// 24 so it matches the limit for the .items field
+REGISTRY(Items, 24)
 #define Items_from(i) _Items_from(i, NULL)
 #ifdef GAMEQC
 REGISTRY_DEPENDS(Items, Models)
index 75abe46cc49e031d22093ec99161644d41828b09..017ada75c0288df84ce093b80dffefa8316a810c 100644 (file)
@@ -15,8 +15,8 @@ ENDCLASS(Inventory)
 
 REGISTER_NET_LINKED(ENT_CLIENT_INVENTORY)
 
-const int Inventory_groups_major = 16;
-const int Inventory_groups_minor = 8; // ceil(Items_MAX / Inventory_groups_major)
+const int Inventory_groups_minor = 8; // exactly 1 byte
+const int Inventory_groups_major = 3; // ceil(Items_MAX / Inventory_groups_minor)
 
 #define G_MAJOR(id) (floor((id) / Inventory_groups_minor))
 #define G_MINOR(id) ((id) % Inventory_groups_minor)
@@ -28,7 +28,7 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
 {
     make_pure(this);
     g_inventory = this;
-    const int majorBits = ReadShort();
+    const int majorBits = ReadByte();
     for (int i = 0; i < Inventory_groups_major; ++i) {
         if (!(majorBits & BIT(i))) {
             continue;
@@ -50,6 +50,7 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
 #endif
 
 #ifdef SVQC
+int minorBitsArr[Inventory_groups_major];
 void Inventory_Write(Inventory data)
 {
     if (!data) {
@@ -58,45 +59,37 @@ void Inventory_Write(Inventory data)
     }
     TC(Inventory, data);
 
+       for (int i = 0; i < Inventory_groups_major; ++i)
+               minorBitsArr[i] = 0;
+
     int majorBits = 0;
     FOREACH(Items, true, {
         .int fld = inv_items[it.m_id];
         const bool changed = data.inventory.(fld) != data.(fld);
         if (changed) {
-            majorBits = BITSET(majorBits, BIT(G_MAJOR(it.m_id)), true);
+                       int maj = G_MAJOR(it.m_id);
+                       majorBits = BITSET(majorBits, BIT(maj), true);
+                       minorBitsArr[maj] = BITSET(minorBitsArr[maj], BIT(G_MINOR(it.m_id)), true);
         }
     });
-    WriteShort(MSG_ENTITY, majorBits);
+    WriteByte(MSG_ENTITY, majorBits);
 
-    int minorBits = 0;
-    int lastMaj = 0;
-    int maj = 0;
-    FOREACH(Items, majorBits & BIT(maj = G_MAJOR(it.m_id)), {
-        .int fld = inv_items[it.m_id];
-        const bool changed = data.inventory.(fld) != (data.inventory.(fld) = data.(fld));
-        if (changed) {
-            if (maj != lastMaj) {
-                lastMaj = maj;
-#define X() MACRO_BEGIN \
-    if (minorBits) { \
-        WriteByte(MSG_ENTITY, minorBits); \
-        for (int j = 0; j < Inventory_groups_minor; ++j) { \
-            if (!(minorBits & BIT(j))) { \
-                continue; \
-            } \
-            const entity it = Items_from(Inventory_groups_minor * maj + j); \
-            WriteByte(MSG_ENTITY, data.inv_items[it.m_id]); \
-        } \
-    } \
-MACRO_END
-                X();
-                minorBits = 0;
-            }
-            minorBits = BITSET(minorBits, BIT(G_MINOR(it.m_id)), true);
-        }
-    });
-    X();
-#undef X
+       for (int i = 0; i < Inventory_groups_major; ++i)
+       {
+               if (!(majorBits & BIT(i)))
+                       continue;
+
+               const int minorBits = minorBitsArr[i];
+               WriteByte(MSG_ENTITY, minorBits);
+               for (int j = 0; j < Inventory_groups_minor; ++j)
+               {
+                       if (!(minorBits & BIT(j)))
+                               continue;
+
+                       const entity it = Items_from(Inventory_groups_minor * i + j);
+                       WriteByte(MSG_ENTITY, data.inv_items[it.m_id]);
+               }
+       }
 }
 #endif
 
index cf4e288ba6cd1769c127ef9ca27ab16ca8411579..8ba0096713342a7c7a5364b95ffe8fb58674c2e2 100644 (file)
@@ -11,7 +11,7 @@
 #include <server/items.qh>
 #endif
 
-const int IT_UNLIMITED_WEAPON_AMMO             =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
+const int IT_UNLIMITED_AMMO                    =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
 const int IT_UNLIMITED_SUPERWEAPONS            =  BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
 
 const int IT_JETPACK                           =  BIT(2); // actual item
@@ -44,8 +44,7 @@ const int IT_SUPERWEAPON                              = BIT(21); // suit
 const int IT_STRENGTH                                  = BIT(22);
 
 // item masks
-const int IT_UNLIMITED_AMMO                    = IT_UNLIMITED_WEAPON_AMMO | IT_UNLIMITED_SUPERWEAPONS;
-const int IT_PICKUPMASK                        = IT_UNLIMITED_AMMO | IT_JETPACK | IT_FUEL_REGEN; // strength and invincible are handled separately
+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);
index 3a13a1f81855c51c2eaeea4bea5adda6e10c07b3..739d94aca1e8b3fb9954ce8a278570f96c6363cf 100644 (file)
@@ -2,15 +2,6 @@
 
 #ifdef SVQC
 
-METHOD(Bullets, m_spawnfunc_hookreplace, GameItem(Bullets this, entity e))
-{
-       if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
-       {
-               return ITEM_Shells;
-       }
-       return this;
-}
-
 METHOD(Shells, m_spawnfunc_hookreplace, GameItem(Shells this, entity e))
 {
        if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
index 6fbb7ce896235d53fe240be81fd83ea0aea25002..136fb125a4e293b7e03156e222694eef25c831ac 100644 (file)
@@ -124,7 +124,7 @@ REGISTER_GAMETYPE(DEATHMATCH, NEW(Deathmatch));
 CLASS(LastManStanding, Gametype)
     INIT(LastManStanding)
     {
-        this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",false,true,"","timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
+        this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",false,true,"","timelimit=20 lives=5 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
     }
     METHOD(LastManStanding, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
     {
@@ -302,7 +302,7 @@ void HUD_Mod_CA(vector pos, vector mySize);
 CLASS(ClanArena, Gametype)
     INIT(ClanArena)
     {
-        this.gametype_init(this, _("Clan Arena"),"ca","g_ca",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"));
+        this.gametype_init(this, _("Clan Arena"),"ca","g_ca",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill all enemy teammates to win the round"));
     }
     METHOD(ClanArena, m_parse_mapinfo, bool(string k, string v))
     {
@@ -497,7 +497,7 @@ REGISTER_GAMETYPE(NEXBALL, NEW(NexBall));
 CLASS(FreezeTag, Gametype)
     INIT(FreezeTag)
     {
-        this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to frozen teammates to revive them; freeze all enemies to win"));
+        this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill enemies to freeze them, stand next to frozen teammates to revive them; freeze all enemies to win"));
     }
     METHOD(FreezeTag, m_parse_mapinfo, bool(string k, string v))
     {
@@ -594,10 +594,13 @@ CLASS(Duel, Gametype)
     }
     METHOD(Duel, m_isForcedSupported, bool(Gametype this))
     {
-        // force all DM maps to work in duel?!
-        // TODO: we should really check the size of maps, some DM maps do not work for duel!
-        if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags))
-            return true;
+        if(!cvar("g_duel_not_dm_maps"))
+        {
+            // if this is set, all DM maps support duel too
+            // TODO: we should really check the size of maps, some DM maps do not work for duel!
+            if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags))
+                return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported)
+        }
         return false;
     }
 ENDCLASS(Duel)
index aa5b54a60ed4ba7ce22dbd761d2321610f989392..e9fd04b7263398217e507800c47261f50ab29696 100644 (file)
@@ -670,10 +670,15 @@ void door_init_shared(entity this)
                precache_sound(this.noise2);
        }
 
-       if (!this.wait)
-       {
-               this.wait = 3;
-       }
+        if(autocvar_sv_doors_always_open)
+        {
+                 this.wait = -1;
+        }
+        else if (!this.wait)
+        {
+               this.wait = 3;
+        }
+
        if (!this.lip)
        {
                this.lip = 8;
@@ -726,10 +731,14 @@ spawnfunc(func_door)
        this.pos1 = this.origin;
        this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
 
-       if (!this.speed)
-       {
-               this.speed = 100;
-       }
+        if(autocvar_sv_doors_always_open)
+        {
+                this.speed = max(750, this.speed);
+        }
+        else if (!this.speed)
+        {
+                this.speed = 100;
+        }
 
        settouch(this, door_touch);
 
index a0f67b759b9981c72d7e2e27a5394479c111a275..729f7e236e697e2aaef3a696b2f8d3f94a694e31 100644 (file)
@@ -10,12 +10,26 @@ bool corner_send(entity this, entity to, int sf)
 
        WriteVector(MSG_ENTITY, this.origin);
 
-       WriteString(MSG_ENTITY, this.target);
-       WriteString(MSG_ENTITY, this.target2);
-       WriteString(MSG_ENTITY, this.target3);
-       WriteString(MSG_ENTITY, this.target4);
-       WriteString(MSG_ENTITY, this.targetname);
-       WriteByte(MSG_ENTITY, this.target_random);
+       sf = 0;
+       sf = BITSET(sf, BIT(0), this.target_random);
+
+       sf = BITSET(sf, BIT(1), this.target && this.target != "");
+       sf = BITSET(sf, BIT(2), this.target2 && this.target2 != "");
+       sf = BITSET(sf, BIT(3), this.target3 && this.target3 != "");
+       sf = BITSET(sf, BIT(4), this.target4 && this.target4 != "");
+       sf = BITSET(sf, BIT(5), this.targetname && this.targetname != "");
+
+       WriteByte(MSG_ENTITY, sf);
+       if(sf & BIT(1))
+               WriteString(MSG_ENTITY, this.target);
+       if(sf & BIT(2))
+               WriteString(MSG_ENTITY, this.target2);
+       if(sf & BIT(3))
+               WriteString(MSG_ENTITY, this.target3);
+       if(sf & BIT(4))
+               WriteString(MSG_ENTITY, this.target4);
+       if(sf & BIT(5))
+               WriteString(MSG_ENTITY, this.targetname);
 
        WriteByte(MSG_ENTITY, this.wait);
 
@@ -54,12 +68,14 @@ NET_HANDLE(ENT_CLIENT_CORNER, bool isnew)
        this.origin = ReadVector();
        setorigin(this, this.origin);
 
-       this.target = strzone(ReadString());
-       this.target2 = strzone(ReadString());
-       this.target3 = strzone(ReadString());
-       this.target4 = strzone(ReadString());
-       this.targetname = strzone(ReadString());
-       this.target_random = ReadByte();
+       int targbits = ReadByte();
+       this.target_random = (targbits & BIT(0));
+
+       this.target = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
+       this.target2 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
+       this.target3 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
+       this.target4 = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
+       this.targetname = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
 
        this.wait = ReadByte();
 
index 7c70b8444e0fac5490ff7a0d5cf8882ef1dd59a7..6e9f02b874a2c51610282c881121da037dbfc2c5 100644 (file)
@@ -46,7 +46,7 @@ void dynlight_think(entity this)
 void dynlight_find_aiment(entity this)
 {
        entity targ;
-       if (!this.target)
+       if (!this.target || this.target == "")
                objerror (this, "dynlight: no target to follow");
 
        targ = find(NULL, targetname, this.target);
@@ -62,7 +62,7 @@ void dynlight_find_aiment(entity this)
 void dynlight_find_path(entity this)
 {
        entity targ;
-       if (!this.target)
+       if (!this.target || this.target == "")
                objerror (this, "dynlight: no target to follow");
 
        targ = find(NULL, targetname, this.target);
@@ -74,7 +74,7 @@ void dynlight_find_path(entity this)
 void dynlight_find_target(entity this)
 {
        entity targ;
-       if (!this.target)
+       if (!this.target || this.target == "")
                objerror (this, "dynlight: no target to follow");
 
        targ = find(NULL, targetname, this.target);
index 126a20ea26ec08e254c1ee6e9d9473479b084dda..e7eedd52c413474745eab4e7c142db34f14dba34 100644 (file)
@@ -43,7 +43,10 @@ spawnfunc(info_teleport_destination)
        {
        }
        else
+       {
                objerror (this, "^3Teleport destination without a targetname");
+               return; // don't link it to CSQC in this case!
+       }
 
        teleport_dest_link(this);
 }
index 5a63872dbd6c46b6742b3534be7b4531c0d38ef2..55ccf41fbf2db9da6b46b1e3008a027795d16878 100644 (file)
@@ -272,7 +272,7 @@ void Net_TargetMusic()
 
 void Ent_TriggerMusic_Think(entity this)
 {
-       if(this.active == ACTIVE_NOT)
+       if(this.active == ACTIVE_NOT || intermission)
        {
                return;
        }
index 339ade52a775cc86462c7f991b82a8d5ba8ac366..da86cabce89b83c048ed8a99342e07d501dcee2b 100644 (file)
@@ -257,7 +257,7 @@ void teleport_findtarget(entity this)
        if(n == 0)
        {
                // no dest!
-               objerror (this, "Teleporter with nonexistant target");
+               objerror (this, "Teleporter with nonexistent target");
                return;
        }
        else if(n == 1)
index 9156439f99e3bf19bb9bdc8425efe1fdcd06d53d..db255ebb7aff0d80f596dfeb91cdf35a43cf988d 100644 (file)
@@ -5,7 +5,7 @@ void counter_reset(entity this);
 void counter_use(entity this, entity actor, entity trigger)
 {
        entity store = this;
-       if(this.spawnflags & COUNTER_PER_PLAYER)
+       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(!IS_PLAYER(actor))
                        return;
index 94abd4041d3d1ff9a1a6f24f5a7db8284819244e..b110d9913fd97baa5b1d628b69c78fd173d32578 100644 (file)
@@ -18,7 +18,7 @@ void trigger_heal_touch(entity this, entity toucher)
                                toucher.triggerhealtime = time + this.delay;
 
                        bool playthesound = (this.spawnflags & HEAL_SOUND_ALWAYS);
-                       bool healed = Heal(toucher, this, GetResource(this, RES_HEALTH), this.max_health);
+                       bool healed = Heal(toucher, this, this.health, this.max_health);
 
                        if(playthesound || healed)
                                _sound (toucher, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
@@ -36,8 +36,8 @@ void trigger_heal_init(entity this)
        this.active = ACTIVE_ACTIVE;
        if(!this.delay)
                this.delay = 1;
-       if(!GetResource(this, RES_HEALTH))
-               SetResourceExplicit(this, RES_HEALTH, 10); // TODO: use a special field for this, it doesn't have actual health!
+       if(!this.health)
+               this.health = 10;
        if(!this.max_health)
                this.max_health = 200; // max health topoff for field
        if(this.noise == "")
index a61935eb8c5633515f95924872fb9daa25a49ccf..f438fbf01f5f8295032f45aa8e76647825377b04 100644 (file)
@@ -339,13 +339,57 @@ bool trigger_push_testorigin_for_item(entity tracetest_ent, entity item, vector
 }
 #endif
 
+#ifdef SVQC
+vector trigger_push_get_start_point(entity this)
+{
+       // calculate a typical start point for the jump
+       vector org = (this.absmin + this.absmax) * 0.5;
+       org.z = this.absmax.z - PL_MIN_CONST.z - 7;
+       return org;
+}
+
+float trigger_push_get_push_time(entity this, vector endpos)
+{
+       vector org = trigger_push_get_start_point(this);
+
+       float grav = PHYS_GRAVITY(NULL);
+
+       entity t = this.enemy;
+       if (t)
+       {
+               entity e = spawn();
+               setsize(e, PL_MIN_CONST, PL_MAX_CONST);
+               e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+               vector v = trigger_push_calculatevelocity(org, t, this.height, e);
+               vector v2 = trigger_push_calculatevelocity(endpos, t, this.height, e);
+               delete(e);
+               return (v.z + v2.z) / grav;
+       }
+       else if (!(this.target && this.target != ""))
+       {
+               if (!this.team)
+               {
+                       vector v = this.movedir;
+
+                       float t = v.z / grav;
+                       float jump_height = 1/2 * grav * (t ** 2);
+                       float remaining_height = org.z + jump_height - endpos.z;
+                       float v2_z = sqrt(2 * grav * remaining_height);
+
+                       return (v.z + v2_z) / grav;
+               }
+       }
+       return 0;
+}
+#endif
+
 /// if (item != NULL) returns true if the item can be reached by using this jumppad, false otherwise
 /// if (item == NULL) tests jumppad's trajectory and eventually spawns waypoints for it (return value doesn't matter)
 bool trigger_push_test(entity this, entity item)
 {
-       // first calculate a typical start point for the jump
-       vector org = (this.absmin + this.absmax) * 0.5;
-       org.z = this.absmax.z - PL_MIN_CONST.z - 7;
+#ifdef SVQC
+       vector org = trigger_push_get_start_point(this);
+#endif
 
        if (this.target)
        {
index 16118cb9d6e54906ea35f5634d095ad879f2a96f..7321fe23f996a4e50b885194fb3c98fd26e2d8a3 100644 (file)
@@ -1,7 +1,7 @@
 #include "magicear.qh"
 #ifdef SVQC
-float magicear_matched;
-float W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
+#include <common/weapons/weapon/tuba.qh>
+bool magicear_matched;
 string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
 {
        float domatch, dotrigger, matchstart, l;
index 0717f4beadd4eeb4aa0ae1c2a7cfcc94af38a0f9..f7d9df2900c4c8c40403ede1f45bc71ea3fcf326 100644 (file)
 
 /*
 *              t_swamp.c
-*              Adds spawnfunc_trigger_swamp and suppoart routines for xonotic 1.2.1+
+*              Adds spawnfunc_trigger_swamp and support routines for nexuiz 1.2.1+ and xonotic
 *              Author tZork (Jakob MG)
 *              jakob@games43.se
 *              2005 11 29
 */
 
-.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!) 
-.entity swampslug;
-
-#ifdef SVQC
-spawnfunc(trigger_swamp);
-#endif
-void swamp_touch(entity this, entity toucher);
-void swampslug_think(entity this);
-
 
 /*
 * Uses a entity calld swampslug to handle players in the swamp
@@ -46,7 +35,11 @@ void swampslug_think(entity this)
        //Slug dead? then remove curses.
        if(GetResource(this, RES_HEALTH) <= 0)
        {
-               this.owner.in_swamp = 0;
+               if(this.owner.swampslug == this)
+               {
+                       this.owner.in_swamp = false;
+                       this.owner.swampslug = NULL;
+               }
                delete(this);
                //centerprint(this.owner,"Killing slug...\n");
                return;
@@ -72,11 +65,12 @@ void swamp_touch(entity this, entity toucher)
        EXACTTRIGGER_TOUCH(this, toucher);
 
        // Chech if player alredy got a swampslug.
-       if(toucher.in_swamp != 1)
+       if(!toucher.in_swamp)
        {
                // If not attach one.
                //centerprint(toucher,"Entering swamp!\n");
-               toucher.swampslug = spawn();
+               if(!toucher.swampslug) // just incase
+                       toucher.swampslug = spawn();
                toucher.swampslug.swamp_lifetime = 2;
                setthink(toucher.swampslug, swampslug_think);
                toucher.swampslug.nextthink = time;
@@ -84,11 +78,11 @@ void swamp_touch(entity this, entity toucher)
                toucher.swampslug.dmg = this.dmg;
                toucher.swampslug.swamp_interval = this.swamp_interval;
                toucher.swamp_slowdown = this.swamp_slowdown;
-               toucher.in_swamp = 1;
+               toucher.in_swamp = true;
                return;
        }
 
-       //toucher.in_swamp = 1;
+       //toucher.in_swamp = true;
 
        //Revitalize players swampslug
        toucher.swampslug.swamp_lifetime = 2;
@@ -116,8 +110,8 @@ void swamp_link(entity this)
 }
 
 /*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
-Players gettin into the swamp will
-get slowd down and damaged
+Players in the swamp will be
+slowed down and damaged over time
 */
 spawnfunc(trigger_swamp)
 {
index f4df98378d544659b1c22f0c663919fb95f90c17..bfe860ed03af9561d2c4e37720adb873a4f83438 100644 (file)
@@ -2,7 +2,16 @@
 
 .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 (!?)
-.entity swampslug;
 
-.float in_swamp;              // bool
+.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);
+#endif
+void swamp_touch(entity this, entity toucher);
+void swampslug_think(entity this);
index 1608f471da24f10c4e09e32bcb8a8e1ef0345e71..fd9e3941e1285daafce81122fecfd8763a29b703 100644 (file)
@@ -219,7 +219,7 @@ bool HUD_MinigameMenu_Click_ExpandCollapse(entity this)
        {
                for ( e = HUD_MinigameMenu_entries; e != NULL; e = e.list_next )
                {
-                       if ( e.flags & 2 && e.origin_x == this.origin_x)
+                       if ( (e.flags & 2) && e.origin_x == this.origin_x)
                                HUD_MinigameMenu_Click(e);
                }
 
index 38aa4e33ada8d62930db4634610e5f2cb8610221..c6a1c2199b62b1c5a6ec305cbf81a28bbe3803e0 100644 (file)
@@ -17,7 +17,7 @@ CLASS(Model, Object)
             LOG_WARNF("Missing model: \"%s\"", s);
             return;
         }
-        profile(sprintf("precache_model(\"%s\")", s));
+        //profile(sprintf("precache_model(\"%s\")", s));
         precache_model(s);
         strcpy(this.model_str_, s);
     }
index 86e780e0a4657aa523489eb0b9ad82bc7bf9f698..efdd836d21e8af7bedd7de2ebffe8555031e173a 100644 (file)
@@ -36,7 +36,8 @@ CLASS(OffhandMageTeleport, OffhandWeapon)
         player.OffhandMageTeleport_key_pressed = key_pressed;
     }
 ENDCLASS(OffhandMageTeleport)
-OffhandMageTeleport OFFHAND_MAGE_TELEPORT; STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
+OffhandMageTeleport OFFHAND_MAGE_TELEPORT;
+STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
 
 float autocvar_g_monster_mage_health;
 float autocvar_g_monster_mage_damageforcescale = 0.5;
index 18f8f5963f2d9e704cbff2ebbf42618a41b024d4..23de31062cae854df3882b62ee0afdd1c69b04a1 100644 (file)
@@ -23,7 +23,7 @@ REGISTER_MONSTER(MAGE, NEW(Mage));
 #include <common/items/_mod.qh>
 
 CLASS(MageSpike, PortoLaunch)
-/* flags     */ ATTRIB(MageSpike, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(MageSpike, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(MageSpike, impulse, int, 9);
 /* refname   */ ATTRIB(MageSpike, netname, string, "magespike");
 /* wepname   */ ATTRIB(MageSpike, m_name, string, _("Mage spike"));
index 908f0f942070cd758715adbf72024759e248d62d..679b140494aa48d7c679b5df85725666b9111936 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_MONSTER(SPIDER, NEW(Spider));
 #include <common/weapons/_all.qh>
 
 CLASS(SpiderAttack, PortoLaunch)
-/* flags     */ ATTRIB(SpiderAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(SpiderAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(SpiderAttack, impulse, int, 9);
 /* refname   */ ATTRIB(SpiderAttack, netname, string, "spider");
 /* wepname   */ ATTRIB(SpiderAttack, m_name, string, _("Spider attack"));
index 2c5df05646e4a1615a12485fe849d06f02d09f6c..e54c9a797332a96aa2dbe000f6288dbe0f80ee4f 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_MONSTER(WYVERN, NEW(Wyvern));
 #include <common/weapons/_all.qh>
 
 CLASS(WyvernAttack, PortoLaunch)
-/* flags     */ ATTRIB(WyvernAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(WyvernAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(WyvernAttack, impulse, int, 9);
 /* refname   */ ATTRIB(WyvernAttack, netname, string, "wyvern");
 /* wepname   */ ATTRIB(WyvernAttack, m_name, string, _("Wyvern attack"));
index 97a68b5f8f92877e95d115b0bf6c50d03b804088..0673cd0baf24810d20dc452ce469e73a6ae31a51 100644 (file)
@@ -1095,15 +1095,12 @@ void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff)
        if(trace_ent && IS_MONSTER(trace_ent))
                reverse = true;
 
-       // TODO: fix this... tracing is broken if the floor is thin
-       /*
-       if(!allow_jumpoff)
+       if(!allow_jumpoff && IS_ONGROUND(this))
        {
-               a = b - '0 0 32';
-               traceline(b, a, MOVE_WORLDONLY, this);
+               traceline(b, b - '0 0 32', MOVE_NORMAL, this);
                if(trace_fraction == 1.0)
                        reverse = true;
-       } */
+       }
 
        if(reverse)
        {
@@ -1321,7 +1318,7 @@ bool Monster_Spawn(entity this, bool check_appear, int mon_id)
 
        if(!autocvar_g_monsters) { Monster_Remove(this); return false; }
 
-       if(!(this.spawnflags & MONSTERFLAG_RESPAWNED))
+       if(!(this.spawnflags & MONSTERFLAG_RESPAWNED) && !(this.flags & FL_MONSTER))
        {
                IL_PUSH(g_monsters, this);
                if(this.mdl && this.mdl != "")
index d3f4ee740ab1543d2bf8fae2090e111842f251de..13c98e93fa1f64e75271e79cba146614c1b6dd94 100644 (file)
@@ -16,6 +16,7 @@ void spawner_use(entity this, entity actor, entity trigger)
        e.noalign = this.noalign;
        e.angles = this.angles;
        e.monster_skill = this.monster_skill;
+       e.skin = this.skin;
        e = spawnmonster(e, this.spawnmob, 0, this, this, this.origin, false, true, this.monster_moveflags);
 }
 
index c1d658576e2cb4b22e43a7e6446356312467265f..cc4cc0129593044474468adff6b9434636fcdcf9 100644 (file)
@@ -171,7 +171,8 @@ void Mutator_Remove(Mutator mut);
 bool mutator_log = false;
 .bool m_added;
 
-#define MUTATOR_IS_ENABLED(this) MUTATOR_##this.mutatorcheck()
+#define _MUTATOR_IS_ENABLED(this) this.mutatorcheck()
+#define MUTATOR_IS_ENABLED(this) _MUTATOR_IS_ENABLED(MUTATOR_##this)
 
 #ifdef GAMEQC
 /** server mutators activate corresponding client mutators for all clients */
@@ -276,7 +277,7 @@ STATIC_INIT(Mutators) {
 }
 
 STATIC_INIT_LATE(Mutators) {
-    FOREACH(Mutators, it.mutatorcheck(), Mutator_Add(it));
+    FOREACH(Mutators, _MUTATOR_IS_ENABLED(it), Mutator_Add(it));
 }
 
 #define MUTATOR_ONADD                   if (mode == MUTATOR_ADDING)
index 7d4e583675b812169ee16ebc076b57f3973ee7e3..b381db4be19a6f0d9c8338f4f406d7f2f3a6e868 100644 (file)
@@ -3,6 +3,10 @@
 #include <common/teams.qh>
 #include <common/util.qh>
 
+#ifdef GAMEQC
+#include <common/mutators/mutator/waypoints/all.qh>
+#endif
+
 #ifdef GAMEQC
 REGISTER_WAYPOINT(Buff, _("Buff"), "", '1 0.5 0', 1);
 REGISTER_RADARICON(Buff, 1);
@@ -35,10 +39,10 @@ CLASS(Buff, Pickup)
 ENDCLASS(Buff)
 
 STATIC_INIT(REGISTER_BUFFS) {
-    FOREACH(Buffs, true, {
-        it.m_itemid = BIT(it.m_id - 1); \
-        it.m_sprite = strzone(strcat("buff-", it.netname)); \
-    });
+       FOREACH(Buffs, true, {
+               it.m_itemid = BIT(it.m_id - 1);
+               it.m_sprite = strzone(strcat("buff-", it.netname));
+       });
 }
 
 #ifdef SVQC
index c93902291da2383ca99ee6cabda85463009ac3b3..c9dbe5add1674f004a82bff50a180f9649172c1d 100644 (file)
@@ -1,3 +1,6 @@
 #pragma once
 
 #include "buffs.qh"
+
+float cvar_cl_buffs_autoreplace;
+REPLICATE(cvar_cl_buffs_autoreplace, bool, "cl_buffs_autoreplace");
index 58663be1ac72aafd49268046138727770b250871..256af90affb3650cfc444b0e9d33827af1504ab1 100644 (file)
@@ -180,9 +180,11 @@ void buff_Touch(entity this, entity toucher)
        {
                if (CS(toucher).cvar_cl_buffs_autoreplace && STAT(BUFFS, toucher) != STAT(BUFFS, this))
                {
+                       // TODO: lost-gained notification for this case
                        int buffid = buff_FirstFromFlags(STAT(BUFFS, toucher)).m_id;
-                       //Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_DROP, STAT(BUFFS, toucher));
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
+                       Send_Notification(NOTIF_ONE, toucher, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
+                       if(!IS_INDEPENDENT_PLAYER(toucher))
+                               Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
 
                        STAT(BUFFS, toucher) = 0;
                        //sound(toucher, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
@@ -193,20 +195,24 @@ void buff_Touch(entity this, entity toucher)
        this.owner = toucher;
        this.buff_active = false;
        this.lifetime = 0;
-       int buffid = buff_FirstFromFlags(STAT(BUFFS, this)).m_id;
-       Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_GOT, buffid);
-       Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF, toucher.netname, buffid);
+       entity thebuff = buff_FirstFromFlags(STAT(BUFFS, this));
+       Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_GOT, thebuff.m_id);
+       if(!IS_INDEPENDENT_PLAYER(toucher))
+               Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF, toucher.netname, thebuff.m_id);
 
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
        sound(toucher, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM);
        STAT(BUFFS, toucher) |= (STAT(BUFFS, this));
+       float bufftime = ((this.count) ? this.count : thebuff.m_time(thebuff));
+       if(bufftime)
+               STAT(BUFF_TIME, toucher) = min(time + bufftime, max(STAT(BUFF_TIME, toucher), time) + bufftime);
 }
 
 float buff_Available(entity buff)
 {
        if (buff == BUFF_Null)
                return false;
-       if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
+       if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_AMMO) || cvar("g_melee_only")))
                return false;
        if (buff == BUFF_VAMPIRE && cvar("g_vampire"))
                return false;
@@ -339,6 +345,12 @@ bool buff_Customize(entity this, entity client)
        return true;
 }
 
+void buff_Delete(entity this)
+{
+       WaypointSprite_Kill(this.buff_waypoint);
+       delete_fn(this);
+}
+
 void buff_Init(entity this)
 {
        if(!cvar("g_buffs")) { delete(this); return; }
@@ -374,6 +386,7 @@ void buff_Init(entity this)
        buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate + max(0, game_starttime - time));
        this.buff_active = !this.buff_activetime;
        this.pflags = PFLAGS_FULLDYNAMIC;
+       this.dtor = buff_Delete;
 
        if(this.spawnflags & 1)
                this.noalign = true;
@@ -562,9 +575,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
 
-       STAT(BUFFS, player) = 0;
-       STAT(BUFF_TIME, player) = 0;
-       PS(player).buff_shield = time + 0.5; // prevent picking up buffs immediately
+       player.oldbuffs = 0;
        // reset timers here to prevent them continuing after re-spawn
        player.buff_disability_time = 0;
        player.buff_disability_effect_time = 0;
@@ -609,8 +620,10 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDies)
        if(STAT(BUFFS, frag_target))
        {
                int buffid = buff_FirstFromFlags(STAT(BUFFS, frag_target)).m_id;
-               Send_Notification(NOTIF_ALL_EXCEPT, frag_target, MSG_INFO, INFO_ITEM_BUFF_LOST, frag_target.netname, buffid);
+               if(!IS_INDEPENDENT_PLAYER(frag_target))
+                       Send_Notification(NOTIF_ALL_EXCEPT, frag_target, MSG_INFO, INFO_ITEM_BUFF_LOST, frag_target.netname, buffid);
                STAT(BUFFS, frag_target) = 0;
+               STAT(BUFF_TIME, frag_target) = 0;
 
                if(frag_target.buff_model)
                {
@@ -630,11 +643,12 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerUseKey, CBC_ORDER_FIRST)
        {
                int buffid = buff_FirstFromFlags(STAT(BUFFS, player)).m_id;
                Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid);
-               Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
+               if(!IS_INDEPENDENT_PLAYER(player))
+                       Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
 
                STAT(BUFFS, player) = 0;
+               STAT(BUFF_TIME, player) = 0;
                PS(player).buff_shield = time + max(0, autocvar_g_buffs_pickup_delay);
-               //STAT(BUFF_TIME, player) = 0; // already notified
                sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                return true;
        }
@@ -846,7 +860,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                                Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message?
                                sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                        }
-                       else
+                       else if(!IS_INDEPENDENT_PLAYER(player))
                                Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
                        STAT(BUFFS, player) = 0;
                        PS(player).buff_shield = time + max(0, autocvar_g_buffs_pickup_delay); // always put in a delay, even if small
@@ -898,12 +912,13 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
        {
                entity buff = buff_FirstFromFlags(STAT(BUFFS, player));
                float bufftime = buff != BUFF_Null ? buff.m_time(buff) : 0;
-               STAT(BUFF_TIME, player) = (bufftime) ? time + bufftime : 0;
+               if(STAT(BUFF_TIME, player) <= time) // if the player still has a buff countdown, don't reset it!
+                       STAT(BUFF_TIME, player) = (bufftime) ? time + bufftime : 0;
 
                BUFF_ONADD(BUFF_AMMO)
                {
-                       player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_WEAPON_AMMO);
-                       player.items |= IT_UNLIMITED_WEAPON_AMMO;
+                       player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_AMMO);
+                       player.items |= IT_UNLIMITED_AMMO;
 
                        if(STAT(BUFFS, player) & BUFF_AMMO.m_itemid)
                        {
@@ -921,9 +936,9 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                BUFF_ONREM(BUFF_AMMO)
                {
                        if(player.buff_ammo_prev_infitems)
-                               player.items |= IT_UNLIMITED_WEAPON_AMMO;
+                               player.items |= IT_UNLIMITED_AMMO;
                        else
-                               player.items &= ~IT_UNLIMITED_WEAPON_AMMO;
+                               player.items &= ~IT_UNLIMITED_AMMO;
 
                        if(STAT(BUFFS, player) & BUFF_AMMO.m_itemid)
                        {
index 80a7828a703f409a707d36aac3b0e59fc8f02831..05ce178bd4e7d0952d3568cc1213f03e406c65b8 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/mutators/mutator/dodging/dodging.qc>
+#ifdef CSQC
+    #include <common/mutators/mutator/dodging/cl_dodging.qc>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/dodging/sv_dodging.qc>
 #endif
index fef7b8e6e4e7f289ea505ba469708bc116e3a280..3b106c653ae04ca2334fbea1d7544000164b461c 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/mutators/mutator/dodging/dodging.qh>
+#ifdef CSQC
+    #include <common/mutators/mutator/dodging/cl_dodging.qh>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/dodging/sv_dodging.qh>
 #endif
diff --git a/qcsrc/common/mutators/mutator/dodging/cl_dodging.qc b/qcsrc/common/mutators/mutator/dodging/cl_dodging.qc
new file mode 100644 (file)
index 0000000..a9d10ef
--- /dev/null
@@ -0,0 +1 @@
+#include "cl_dodging.qh"
diff --git a/qcsrc/common/mutators/mutator/dodging/cl_dodging.qh b/qcsrc/common/mutators/mutator/dodging/cl_dodging.qh
new file mode 100644 (file)
index 0000000..84f7731
--- /dev/null
@@ -0,0 +1,4 @@
+#pragma once
+
+float cvar_cl_dodging_timeout;
+REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
diff --git a/qcsrc/common/mutators/mutator/dodging/dodging.qc b/qcsrc/common/mutators/mutator/dodging/dodging.qc
new file mode 100644 (file)
index 0000000..9e7ea20
--- /dev/null
@@ -0,0 +1 @@
+#include "dodging.qh"
diff --git a/qcsrc/common/mutators/mutator/dodging/dodging.qh b/qcsrc/common/mutators/mutator/dodging/dodging.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index 6640cb8bf23a51a48c08cdd4662fbd89a4fcefcf..c97308d58ab1f8cd8a7db8adcd738c277baa739e 100644 (file)
 #endif
 
 #ifdef CSQC
+       float cvar_cl_dodging_timeout;
        #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
 #elif defined(SVQC)
+       .float cvar_cl_dodging_timeout;
        #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
@@ -56,8 +58,6 @@ bool autocvar_sv_dodging_sound;
 #include <common/animdecide.qh>
 #include <common/physics/player.qh>
 
-.float cvar_cl_dodging_timeout;
-
 REGISTER_MUTATOR(dodging, cvar("g_dodging"))
 {
        // this just turns on the cvar.
index fc571678b2c7f22ea1032f2f4a3d6e580cc83a02..c4f4b5d00cd861d9c717beb3fcc2edeca2157346 100644 (file)
@@ -18,7 +18,7 @@ int autocvar_g_instagib_extralives;
 float autocvar_g_instagib_speed_highspeed;
 
 IntrusiveList g_instagib_items;
-STATIC_INIT()
+STATIC_INIT(instagib)
 {
        g_instagib_items = IL_NEW();
        IL_PUSH(g_instagib_items, ITEM_VaporizerCells);
@@ -82,7 +82,7 @@ void instagib_ammocheck(entity this)
 
        if(IS_DEAD(this) || game_stopped)
                instagib_stop_countdown(this);
-       else if (GetResource(this, RES_CELLS) > 0 || (this.items & IT_UNLIMITED_WEAPON_AMMO) || (this.flags & FL_GODMODE))
+       else if (GetResource(this, RES_CELLS) > 0 || (this.items & IT_UNLIMITED_AMMO) || (this.flags & FL_GODMODE))
                instagib_stop_countdown(this);
        else if(autocvar_g_rm && autocvar_g_rm_laser)
        {
index 1379d586f10fd4da14b9f82d98571cd00bbe6c78..8d2bb318f0f2443f1200545a675f23b1d31d433c 100644 (file)
@@ -28,16 +28,12 @@ NET_HANDLE(itemstime, bool isNew)
 #endif
 
 #ifdef CSQC
-void Item_ItemsTime_Init()
-{
-    FOREACH(Items, true, {
-        ItemsTime_time[it.m_id] = -1;
-    });
-    ItemsTime_time[Items_MAX] = -1;
-}
 
 STATIC_INIT(ItemsTime_Init) {
-    Item_ItemsTime_Init();
+       FOREACH(Items, true, {
+               ItemsTime_time[it.m_id] = -1;
+       });
+       ItemsTime_time[Items_MAX] = -1;
 }
 
 int autocvar_hud_panel_itemstime = 2;
@@ -77,17 +73,11 @@ bool Item_ItemsTime_Allow(GameItem it)
 // reserve one more spot for superweapons time
 float it_times[Items_MAX + 1];
 
-void Item_ItemsTime_Init()
-{
-    FOREACH(Items, Item_ItemsTime_Allow(it), {
-        it_times[it.m_id] = -1;
-    });
-    it_times[Items_MAX] = -1;
-}
-
 STATIC_INIT(ItemsTime_Init) {
-    // items time
-    Item_ItemsTime_Init();
+       FOREACH(Items, Item_ItemsTime_Allow(it), {
+               it_times[it.m_id] = -1;
+       });
+       it_times[Items_MAX] = -1;
 }
 
 void Item_ItemsTime_ResetTimes()
index 081a1fdb6fd69d7767de22b0ebecd8c8445e93b4..0efd85635cc88503b9998675c59eaf2369fd347c 100644 (file)
@@ -24,6 +24,7 @@ REGISTER_MUTATOR(multijump, true);
 .bool multijump_ready;
 
 #ifdef CSQC
+bool cvar_cl_multijump;
 bool autocvar_cl_multijump = true;
 
        #define PHYS_MULTIJUMP_CLIENT(s)        autocvar_cl_multijump
@@ -114,10 +115,10 @@ MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
        }
 }
 
-#ifdef SVQC
-
 REPLICATE(cvar_cl_multijump, bool, "cl_multijump");
 
+#ifdef SVQC
+
 MUTATOR_HOOKFUNCTION(multijump, BuildMutatorsString)
 {
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ":multijump");
index 484aaddcdadc86a8cc9a72fecdd47799f9650747..d48319a421fa599861a11ba4aaabe1dabe71ac1b 100644 (file)
@@ -10,6 +10,9 @@ float autocvar_g_nades_spread = 0.04;
 REGISTER_STAT(NADES_SMALL, int, autocvar_g_nades_nade_small)
 
 #ifdef GAMEQC
+REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
+REPLICATE(cvar_cl_pokenade_type, string, "cl_pokenade_type");
+
 entity Nade_TrailEffect(int proj, int nade_team)
 {
     switch (proj)
@@ -891,15 +894,18 @@ void nade_damage(entity this, entity inflictor, entity attacker, float damage, i
                damage = this.max_health * 0.1;
        else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
        {
-               if(deathtype & HITTYPE_SECONDARY)
-               {
-                       damage = this.max_health * 0.1;
-                       force *= 10;
-               }
-               else
+               if(!(deathtype & HITTYPE_SECONDARY))
                        damage = this.max_health * 1.15;
        }
 
+       // melee slaps
+       entity death_weapon = DEATH_WEAPONOF(deathtype);
+       if(((deathtype & HITTYPE_SECONDARY) ? (death_weapon.spawnflags & WEP_TYPE_MELEE_SEC) : (death_weapon.spawnflags & WEP_TYPE_MELEE_PRI)))
+       {
+               damage = this.max_health * 0.1;
+               force *= 10;
+       }
+
        this.velocity += force;
        UpdateCSQCProjectile(this);
 
@@ -1030,7 +1036,7 @@ void nades_GiveBonus(entity player, float score)
                if ( STAT(NADE_BONUS_SCORE, player) >= 1 )
                {
                        Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
-                       play2(player, SND(KH_ALARM));
+                       play2(player, SND(NADE_BONUS));
                        STAT(NADE_BONUS, player)++;
                        STAT(NADE_BONUS_SCORE, player) -= 1;
                }
@@ -1247,7 +1253,8 @@ CLASS(NadeOffhand, OffhandWeapon)
                }
     }
 ENDCLASS(NadeOffhand)
-NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+NadeOffhand OFFHAND_NADE;
+STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
 
 MUTATOR_HOOKFUNCTION(nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
 {
@@ -1444,7 +1451,8 @@ MUTATOR_HOOKFUNCTION(nades, PlayerDies, CBC_ORDER_LAST)
 
        if(IS_PLAYER(frag_attacker))
        {
-               float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium) : autocvar_g_nades_bonus_score_minor);
+               float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium) 
+                                                                                                                                       : autocvar_g_nades_bonus_score_minor);
 
                if (SAME_TEAM(frag_attacker, frag_target) || frag_attacker == frag_target)
                        nades_RemoveBonus(frag_attacker);
@@ -1541,9 +1549,6 @@ MUTATOR_HOOKFUNCTION(nades, SpectateCopy)
        STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
 }
 
-REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
-REPLICATE(cvar_cl_pokenade_type, string, "cl_pokenade_type");
-
 MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
 {
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
index 2729316a88b4fd8c95eb24f1afc1580b3d7126f3..d76eb941450274fb626b8f1732ef4ecebf88e4f1 100644 (file)
@@ -101,6 +101,8 @@ MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
 #endif
 
 #ifdef CSQC
+float cvar_cl_nade_type;
+string cvar_cl_pokenade_type;
 bool Projectile_isnade(int proj); // TODO: remove
 
 void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator
index 37dac8f93123d0624d78e44f90e918e828c659d8..47e1c97a9a9a70f1df5a7214ac56e12e8080bbed 100644 (file)
@@ -28,7 +28,7 @@ Entity:
 -> This will spawn as Rifle in this mutator ONLY, and as Vortex otherwise.
 
 {
-"classname" "weapon_vortext"
+"classname" "weapon_vortex"
 "new_toys" "vortex rifle"
 }
 -> This will spawn as either Vortex or Rifle in this mutator ONLY, and as Vortex otherwise.
index efe8ee3aedf2449988527ca916cc77bc2055044e..7214a699e1122e759026f2b5995ee4a99305a943 100644 (file)
@@ -140,7 +140,7 @@ void NIX_GiveCurrentWeapon(entity this)
                SetResource(this, RES_CELLS, 0);
                SetResource(this, RES_PLASMA, 0);
                SetResource(this, RES_FUEL, 0);
-               if(this.items & IT_UNLIMITED_WEAPON_AMMO)
+               if(this.items & IT_UNLIMITED_AMMO)
                {
                        switch (wpn.ammo_type)
                        {
@@ -193,7 +193,7 @@ void NIX_GiveCurrentWeapon(entity this)
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
        }
 
-       if(!(this.items & IT_UNLIMITED_WEAPON_AMMO) && time > this.nix_nextincr)
+       if(!(this.items & IT_UNLIMITED_AMMO) && time > this.nix_nextincr)
        {
                switch (wpn.ammo_type)
                {
index 017cc2082adfc7a9468e293dde68c276160abff5..227be462699dbe7c827edbfe2acc682bbebf7608 100644 (file)
@@ -1,15 +1,16 @@
 // generated file; do not modify
+#include <common/mutators/mutator/overkill/okhmg.qc>
+#include <common/mutators/mutator/overkill/okmachinegun.qc>
+#include <common/mutators/mutator/overkill/oknex.qc>
+#include <common/mutators/mutator/overkill/okrpc.qc>
+#include <common/mutators/mutator/overkill/okshotgun.qc>
+#include <common/mutators/mutator/overkill/overkill.qc>
 #ifdef CSQC
     #include <common/mutators/mutator/overkill/cl_overkill.qc>
 #endif
 #ifdef SVQC
     #include <common/mutators/mutator/overkill/sv_overkill.qc>
 #endif
-#include <common/mutators/mutator/overkill/okhmg.qc>
-#include <common/mutators/mutator/overkill/okmachinegun.qc>
-#include <common/mutators/mutator/overkill/oknex.qc>
-#include <common/mutators/mutator/overkill/okrpc.qc>
-#include <common/mutators/mutator/overkill/okshotgun.qc>
 #ifdef SVQC
     #include <common/mutators/mutator/overkill/sv_weapons.qc>
 #endif
index 7731f17e169e9191fb49996c819cdf1ec200faa8..dc2bb0a5b1f7b26baa78c87a38c120791e0792ce 100644 (file)
@@ -1,12 +1,13 @@
 // generated file; do not modify
+#include <common/mutators/mutator/overkill/okhmg.qh>
+#include <common/mutators/mutator/overkill/okmachinegun.qh>
+#include <common/mutators/mutator/overkill/oknex.qh>
+#include <common/mutators/mutator/overkill/okrpc.qh>
+#include <common/mutators/mutator/overkill/okshotgun.qh>
+#include <common/mutators/mutator/overkill/overkill.qh>
 #ifdef CSQC
     #include <common/mutators/mutator/overkill/cl_overkill.qh>
 #endif
 #ifdef SVQC
     #include <common/mutators/mutator/overkill/sv_overkill.qh>
 #endif
-#include <common/mutators/mutator/overkill/okhmg.qh>
-#include <common/mutators/mutator/overkill/okmachinegun.qh>
-#include <common/mutators/mutator/overkill/oknex.qh>
-#include <common/mutators/mutator/overkill/okrpc.qh>
-#include <common/mutators/mutator/overkill/okshotgun.qh>
index bee61f2fea54516c00e7be4088be64b09a8fdab4..df55fb88c42a4663b96b9aaa5a6f3b61d908692f 100644 (file)
@@ -18,7 +18,7 @@ void W_OverkillHeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity
                return;
        }
 
-       if((!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (!(actor.items & IT_SUPERWEAPON) && !(actor.items & IT_UNLIMITED_SUPERWEAPONS)))
+       if((!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !(actor.items & IT_UNLIMITED_AMMO)) || (!(actor.items & IT_SUPERWEAPON) && !(actor.items & IT_UNLIMITED_SUPERWEAPONS)))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
index 68ddc9d9233bef0fcf6e6666015225965df70f1d..77204ae1a39d9a74802285e8afb1dc8f0958b7b8 100644 (file)
@@ -6,7 +6,7 @@ CLASS(OverkillHeavyMachineGun, Weapon)
 /* spawnfunc */ ATTRIB(OverkillHeavyMachineGun, m_canonical_spawnfunc, string, "weapon_okhmg");
 /* ammotype  */ ATTRIB(OverkillHeavyMachineGun, ammo_type, int, RES_BULLETS);
 /* impulse   */ ATTRIB(OverkillHeavyMachineGun, impulse, int, 3);
-/* flags     */ ATTRIB(OverkillHeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON);
+/* flags     */ ATTRIB(OverkillHeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON | WEP_FLAG_PENETRATEWALLS);
 /* rating    */ ATTRIB(OverkillHeavyMachineGun, bot_pickupbasevalue, float, 10000);
 /* color     */ ATTRIB(OverkillHeavyMachineGun, wpcolor, vector, '0.5 0.5 0');
 /* modelname */ ATTRIB(OverkillHeavyMachineGun, mdl, string, "ok_hmg");
@@ -35,6 +35,7 @@ CLASS(OverkillHeavyMachineGun, Weapon)
                P(class, prefix, delay, float, SEC) \
                P(class, prefix, edgedamage, float, SEC) \
                P(class, prefix, force, float, SEC) \
+               P(class, prefix, force_zscale, float, SEC) \
                P(class, prefix, lifetime, float, SEC) \
                P(class, prefix, radius, float, SEC) \
                P(class, prefix, refire, float, SEC) \
index f8dfa89fe5b5748e72bea985b7349315f1c56780..768e364a78535f8274516388f47519ed4294da21 100644 (file)
@@ -13,7 +13,7 @@ void W_OverkillMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weap
        }
 
        if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
-       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
index 321d92e2268a51cc352bd188aa2d1cadbe6a4848..77082c96211d6b6b4eec9080ff55e1a80cda8726 100644 (file)
@@ -32,6 +32,7 @@ CLASS(OverkillMachineGun, Weapon)
                P(class, prefix, delay, float, SEC) \
                P(class, prefix, edgedamage, float, SEC) \
                P(class, prefix, force, float, SEC) \
+               P(class, prefix, force_zscale, float, SEC) \
                P(class, prefix, lifetime, float, SEC) \
                P(class, prefix, radius, float, SEC) \
                P(class, prefix, refire, float, SEC) \
index cbcc285a54585382d61e0618fa7a2269a8985860..83a3a3cc052c3e9adbaf0143af71242def1946a5 100644 (file)
@@ -221,7 +221,7 @@ METHOD(OverkillNex, wr_think, void(entity thiswep, entity actor, .entity weapone
        //                              if(fire & 2) // only eat ammo when the button is pressed
        //                              {
        //                                      dt = min(dt, (1 - actor.(weaponentity).oknex_charge) / WEP_CVAR(oknex, charge_rate));
-       //                                      if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       //                                      if(!(actor.items & IT_UNLIMITED_AMMO))
        //                                      {
        //                                              // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        //                                              if(autocvar_g_balance_vortex_reload_ammo)
index d03f40ff2e0049b05820d9a9c1078b694c798fb7..1ffaf78b8ceeeea57116569d86cb70a1761769a6 100644 (file)
@@ -59,6 +59,7 @@ CLASS(OverkillNex, Weapon)
                P(class, prefix, delay, float, SEC) \
                P(class, prefix, edgedamage, float, SEC) \
                P(class, prefix, force, float, SEC) \
+               P(class, prefix, force_zscale, float, SEC) \
                P(class, prefix, lifetime, float, SEC) \
                P(class, prefix, radius, float, SEC) \
                P(class, prefix, refire, float, SEC) \
index 7d95296f96a37d85b8416be36880a7e534db7115..928bfc0b9a8453a84ce5584e5fd6734ffca9747c 100644 (file)
@@ -6,7 +6,7 @@ CLASS(OverkillRocketPropelledChainsaw, Weapon)
 /* spawnfunc */ ATTRIB(OverkillRocketPropelledChainsaw, m_canonical_spawnfunc, string, "weapon_okrpc");
 /* ammotype  */ ATTRIB(OverkillRocketPropelledChainsaw, ammo_type, int, RES_ROCKETS);
 /* impulse   */ ATTRIB(OverkillRocketPropelledChainsaw, impulse, int, 9);
-/* flags     */ ATTRIB(OverkillRocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
+/* flags     */ ATTRIB(OverkillRocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
 /* rating    */ ATTRIB(OverkillRocketPropelledChainsaw, bot_pickupbasevalue, float, 10000);
 /* color     */ ATTRIB(OverkillRocketPropelledChainsaw, wpcolor, vector, '0.5 0.5 0');
 /* modelname */ ATTRIB(OverkillRocketPropelledChainsaw, mdl, string, "ok_rl");
@@ -40,6 +40,7 @@ CLASS(OverkillRocketPropelledChainsaw, Weapon)
                P(class, prefix, delay, float, SEC) \
                P(class, prefix, edgedamage, float, SEC) \
                P(class, prefix, force, float, SEC) \
+               P(class, prefix, force_zscale, float, SEC) \
                P(class, prefix, lifetime, float, SEC) \
                P(class, prefix, radius, float, SEC) \
                P(class, prefix, refire, float, SEC) \
index a830e6ac46f9035d46c14ea8d75d89579534b669..2c75681d970cca83305a0dea2e6363b6c1e04065 100644 (file)
@@ -33,6 +33,7 @@ CLASS(OverkillShotgun, Weapon)
                P(class, prefix, delay, float, SEC) \
                P(class, prefix, edgedamage, float, SEC) \
                P(class, prefix, force, float, SEC) \
+               P(class, prefix, force_zscale, float, SEC) \
                P(class, prefix, lifetime, float, SEC) \
                P(class, prefix, radius, float, SEC) \
                P(class, prefix, refire, float, SEC) \
diff --git a/qcsrc/common/mutators/mutator/overkill/overkill.qc b/qcsrc/common/mutators/mutator/overkill/overkill.qc
new file mode 100644 (file)
index 0000000..3cb64ce
--- /dev/null
@@ -0,0 +1 @@
+#include "overkill.qh"
diff --git a/qcsrc/common/mutators/mutator/overkill/overkill.qh b/qcsrc/common/mutators/mutator/overkill/overkill.qh
new file mode 100644 (file)
index 0000000..3f59c93
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma once
+
index 15a2fc2e0c972427c1270223e0f40ad178609b81..8176669dea78164c5b7bc0e8fecc9e8f4febf8a2 100644 (file)
@@ -11,7 +11,7 @@ bool autocvar_g_overkill_itemwaypoints = true;
 .Weapon ok_lastwep[MAX_WEAPONSLOTS];
 
 IntrusiveList g_overkill_items;
-STATIC_INIT()
+STATIC_INIT(overkill)
 {
        g_overkill_items = IL_NEW();
        IL_PUSH(g_overkill_items, ITEM_HealthMega);
@@ -274,7 +274,10 @@ MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
        if(WEP_OVERKILL_RPC.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_RPC); }
        if(WEP_OVERKILL_HMG.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_HMG); }
 
-       start_items |= IT_UNLIMITED_WEAPON_AMMO;
+       // this gives unlimited ammo (the 4 types) but not fuel
+       // using `g_use_ammunition` instead gives also fuel which is unnecessary and distracting in the HUD
+       start_items |= IT_UNLIMITED_AMMO;
+
        start_weapons = warmup_start_weapons = ok_start_items;
 }
 
index 79e5dd3c5b0cbce85cee0d53108046f8a14bf3fa..63e3c19ef531ccae456e9bfb8c0986cb72c7bc72 100644 (file)
@@ -2,8 +2,8 @@
 
 string autocvar_g_overkill;
 bool autocvar_g_overkill_filter_healthmega;
-bool autocvar_g_overkill_filter_armormedium;
-bool autocvar_g_overkill_filter_armorbig;
+bool autocvar_g_overkill_filter_armormedium = true;
+bool autocvar_g_overkill_filter_armorbig = true;
 bool autocvar_g_overkill_filter_armormega;
 
 .float ok_item;
index d3c1922b997c9437ab82ba9f9c27603d1ed14e1f..58e20568eddf02d9d1ddd90616af3890d2e9ceb8 100644 (file)
@@ -1,19 +1,25 @@
 #include "sv_rocketflying.qh"
 
 string autocvar_g_rocket_flying;
+bool autocvar_g_rocket_flying_disabledelays = true;
 REGISTER_MUTATOR(rocketflying, expr_evaluate(autocvar_g_rocket_flying));
 
 MUTATOR_HOOKFUNCTION(rocketflying, EditProjectile)
 {
        entity proj = M_ARGV(1, entity);
 
-       if(proj.classname == "rocket" || proj.classname == "mine")
+       if(autocvar_g_rocket_flying_disabledelays && (proj.classname == "rocket" || proj.classname == "mine"))
        {
                // kill detonate delay of rockets
                proj.spawnshieldtime = time;
        }
 }
 
+MUTATOR_HOOKFUNCTION(rocketflying, AllowRocketJumping)
+{
+       M_ARGV(0, bool) = true; // force rocket jumping
+}
+
 MUTATOR_HOOKFUNCTION(rocketflying, BuildMutatorsString)
 {
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ":RocketFlying");
index fe3a6ebc5d612cd64ff0fd96d5df502f956176d2..e8306ea0818588a106ceafddafd1c4a77a545412 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc>
+#ifdef CSQC
+    #include <common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qc>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc>
 #endif
index b34f8f8f164c22c2bb724817ee2ca77fc3710453..ea2fd49e6ae15d9e697b4bfa72e2eb804f64e0a3 100644 (file)
@@ -1,4 +1,8 @@
 // generated file; do not modify
+#include <common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qh>
+#ifdef CSQC
+    #include <common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qh>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qh>
 #endif
diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qc
new file mode 100644 (file)
index 0000000..11774ca
--- /dev/null
@@ -0,0 +1 @@
+#include "cl_spawn_near_teammate.qh"
diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qh b/qcsrc/common/mutators/mutator/spawn_near_teammate/cl_spawn_near_teammate.qh
new file mode 100644 (file)
index 0000000..640a725
--- /dev/null
@@ -0,0 +1,4 @@
+#pragma once
+
+float cvar_cl_spawn_near_teammate;
+REPLICATE(cvar_cl_spawn_near_teammate, bool, "cl_spawn_near_teammate");
diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc
new file mode 100644 (file)
index 0000000..7453747
--- /dev/null
@@ -0,0 +1 @@
+#include "spawn_near_teammate.qh"
diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qh b/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qh
new file mode 100644 (file)
index 0000000..3f59c93
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma once
+
index 4192185dced0bd240245c72ba880b4d4016b2780..a9e1c5f57dd2996c7f5c6cf79b365cd11de84d60 100644 (file)
@@ -485,7 +485,7 @@ void Draw_WaypointSprite(entity this)
     if (autocvar_cl_hidewaypoints >= 2)
         return;
 
-    if (this.hideflags & 1 && autocvar_cl_hidewaypoints)
+    if ((this.hideflags & 1) && autocvar_cl_hidewaypoints)
         return; // fixed waypoint
 
     InterpolateOrigin_Do(this);
index e2190b66a26a9cef1c0efb477c51d53c7276422c..f08e2eceee3642b17f12d76ebd256e7d1869dcaf 100644 (file)
@@ -53,6 +53,7 @@ float autocvar_g_waypointsprite_timealphaexponent;
 bool autocvar_g_waypointsprite_turrets = true;
 float autocvar_g_waypointsprite_turrets_maxdist = 5000;
 bool autocvar_g_waypointsprite_turrets_text = false;
+bool autocvar_g_waypointsprite_turrets_onlyhurt = false;
 bool autocvar_g_waypointsprite_uppercase;
 bool autocvar_g_waypointsprite_text;
 float autocvar_g_waypointsprite_iconsize = 32;
index 412521272398e87680d6f793471cf17c1f456ad9..393133055754f2f2db68b2b0e22459242cd725f7 100644 (file)
 #define N_GNTLOFF 1
 #define N__ALWAYS 2
 
-#define MULTITEAM_ANNCE2(prefix, default, sound, channel, volume, position) \
-    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, default, sprintf(sound, strtolower(STATIC_NAME_TEAM_1)), channel, volume, position) \
-    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, default, sprintf(sound, strtolower(STATIC_NAME_TEAM_2)), channel, volume, position)
-#define MULTITEAM_ANNCE3(prefix, default, sound, channel, volume, position) \
-    MULTITEAM_ANNCE2(prefix, default, sound, channel, volume, position) \
-    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, default, sprintf(sound, strtolower(STATIC_NAME_TEAM_3)), channel, volume, position)
-#define MULTITEAM_ANNCE4(prefix, default, sound, channel, volume, position) \
-    MULTITEAM_ANNCE3(prefix, default, sound, channel, volume, position) \
-    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, default, sprintf(sound, strtolower(STATIC_NAME_TEAM_4)), channel, volume, position)
-#define MULTITEAM_ANNCE(prefix, teams, default, sound, channel, volume, position) \
-    NOTIF_ADD_AUTOCVAR(ANNCE_##prefix, default) \
-    MULTITEAM_ANNCE##teams(prefix, default, sound, channel, volume, position)
+#define MULTITEAM_ANNCE(prefix, defaultvalue, sound, channel, volume, position) \
+    NOTIF_ADD_AUTOCVAR(ANNCE_##prefix, defaultvalue) \
+    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_1)), channel, volume, position) \
+    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_2)), channel, volume, position) \
+    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_3)), channel, volume, position) \
+    MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_4)), channel, volume, position)
 
 // MSG_ANNCE_NOTIFICATIONS
     MSG_ANNCE_NOTIF(ACHIEVEMENT_AIRSHOT,        N_GNTLOFF, "airshot",           CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
 #define N_CONSOLE 1
 #define N_CHATCON 2
 
-#define MULTITEAM_INFO2(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, default, 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, default, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_2)), TCR(normal, type, 2), TCR(gentle, type, 2))
-#define MULTITEAM_INFO3(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    MULTITEAM_INFO2(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, default, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_3)), TCR(normal, type, 3), TCR(gentle, type, 3))
-#define MULTITEAM_INFO4(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    MULTITEAM_INFO3(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    MSG_INFO_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, default, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_4)), TCR(normal, type, 4), TCR(gentle, type, 4))
-#define MULTITEAM_INFO(prefix, teams, default, strnum, flnum, args, hudargs, icon, normal, gentle, type) \
-    NOTIF_ADD_AUTOCVAR(INFO_##prefix, default) \
-    MULTITEAM_INFO##teams(prefix, default, strnum, flnum, args, hudargs, icon, normal, gentle, type)
+#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_NOTIFICATIONS
     MSG_INFO_NOTIF(CHAT_NOSPECTATORS,                       N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "")
 
-    MULTITEAM_INFO(CTF_CAPTURE, 4,                          N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag"), "", FLAG)
-    MULTITEAM_INFO(CTF_CAPTURE_BROKEN, 4,                   N_CONSOLE,  2, 2, "s1 f1dtime s2 f2dtime", "s1",    "notify_%s_captured",       _("^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"), "", FLAG)
+    MULTITEAM_INFO(CTF_CAPTURE,                             N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag"), "", FLAG)
+    MULTITEAM_INFO(CTF_CAPTURE_BROKEN,                      N_CONSOLE,  2, 2, "s1 f1dtime s2 f2dtime", "s1",    "notify_%s_captured",       _("^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"), "", FLAG)
     MSG_INFO_NOTIF(CTF_CAPTURE_NEUTRAL,                     N_CONSOLE,  1, 0, "s1", "s1",                       "notify_neutral_captured",  _("^BG%s^BG captured the flag"), "")
-    MULTITEAM_INFO(CTF_CAPTURE_TIME, 4,                     N_CONSOLE,  1, 1, "s1 f1dtime", "s1",               "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"), "", FLAG)
-    MULTITEAM_INFO(CTF_CAPTURE_UNBROKEN, 4,                 N_CONSOLE,  2, 2, "s1 f1dtime s2 f2dtime", "s1",    "notify_%s_captured",       _("^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"), "", FLAG)
-    MULTITEAM_INFO(CTF_FLAGRETURN_ABORTRUN, 4,              N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was returned to base by its owner"), "", FLAG)
+    MULTITEAM_INFO(CTF_CAPTURE_TIME,                        N_CONSOLE,  1, 1, "s1 f1dtime", "s1",               "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"), "", FLAG)
+    MULTITEAM_INFO(CTF_CAPTURE_UNBROKEN,                    N_CONSOLE,  2, 2, "s1 f1dtime s2 f2dtime", "s1",    "notify_%s_captured",       _("^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"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_ABORTRUN,                 N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was returned to base by its owner"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_ABORTRUN_NEUTRAL,         N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe flag was returned by its owner"), "")
-    MULTITEAM_INFO(CTF_FLAGRETURN_DAMAGED, 4,               N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was destroyed and returned to base"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_DAMAGED,                  N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was destroyed and returned to base"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_DAMAGED_NEUTRAL,          N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe flag was destroyed and returned to base"), "")
-    MULTITEAM_INFO(CTF_FLAGRETURN_DROPPED, 4,               N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_DROPPED,                  N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_DROPPED_NEUTRAL,          N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe flag was dropped in the base and returned itself"), "")
-    MULTITEAM_INFO(CTF_FLAGRETURN_NEEDKILL, 4,              N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_NEEDKILL,                 N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_NEEDKILL_NEUTRAL,         N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe flag fell somewhere it couldn't be reached and returned to base"), "")
-    MULTITEAM_INFO(CTF_FLAGRETURN_SPEEDRUN, 4,              N_CONSOLE,  0, 1, "f1dtime", "",                    "",                         _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_SPEEDRUN,                 N_CONSOLE,  0, 1, "f1dtime", "",                    "",                         _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_SPEEDRUN_NEUTRAL,         N_CONSOLE,  0, 1, "f1dtime", "",                    "",                         _("^BGThe flag became impatient after ^F1%.2f^BG seconds and returned itself"), "")
-    MULTITEAM_INFO(CTF_FLAGRETURN_TIMEOUT, 4,               N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag has returned to the base"), "", FLAG)
+    MULTITEAM_INFO(CTF_FLAGRETURN_TIMEOUT,                  N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe ^TC^TT^BG flag has returned to the base"), "", FLAG)
     MSG_INFO_NOTIF(CTF_FLAGRETURN_TIMEOUT_NEUTRAL,          N_CONSOLE,  0, 0, "", "",                           "",                         _("^BGThe flag has returned to the base"), "")
-    MULTITEAM_INFO(CTF_LOST, 4,                             N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_lost",           _("^BG%s^BG lost the ^TC^TT^BG flag"), "", FLAG)
+    MULTITEAM_INFO(CTF_LOST,                                N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_lost",           _("^BG%s^BG lost the ^TC^TT^BG flag"), "", FLAG)
     MSG_INFO_NOTIF(CTF_LOST_NEUTRAL,                        N_CONSOLE,  1, 0, "s1", "s1",                       "notify_neutral_lost",      _("^BG%s^BG lost the flag"), "")
-    MULTITEAM_INFO(CTF_PICKUP, 4,                           N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_taken",          _("^BG%s^BG got the ^TC^TT^BG flag"), "", FLAG)
+    MULTITEAM_INFO(CTF_PICKUP,                              N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_taken",          _("^BG%s^BG got the ^TC^TT^BG flag"), "", FLAG)
     MSG_INFO_NOTIF(CTF_PICKUP_NEUTRAL,                      N_CONSOLE,  1, 0, "s1", "s1",                       "notify_neutral_taken",     _("^BG%s^BG got the flag"), "")
-    MULTITEAM_INFO(CTF_RETURN, 4,                           N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_returned",       _("^BG%s^BG returned the ^TC^TT^BG flag"), "", FLAG)
-    MULTITEAM_INFO(CTF_RETURN_MONSTER, 4,                   N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_returned",       _("^BG%s^BG returned the ^TC^TT^BG flag"), "", FLAG)
+    MULTITEAM_INFO(CTF_RETURN,                              N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_returned",       _("^BG%s^BG returned the ^TC^TT^BG flag"), "", FLAG)
+    MULTITEAM_INFO(CTF_RETURN_MONSTER,                      N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_returned",       _("^BG%s^BG returned the ^TC^TT^BG flag"), "", FLAG)
 
     MSG_INFO_NOTIF(COINTOSS,                                N_CHATCON,  1, 0, "s1", "",     "",     _("^F2Throwing coin... Result: %s^F2!"), "")
 
     MSG_INFO_NOTIF(DEATH_SELF_VH_WAKI_ROCKET,               N_CONSOLE,  2, 1, "s1 s2loc spree_lost", "s1",      "notify_death",         _("^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"), "")
     MSG_INFO_NOTIF(DEATH_SELF_VOID,                         N_CONSOLE,  3, 1, "s1 s2 s2loc spree_lost", "s1",   "notify_void",            "^BG%s^K1 %s^K1%s%s", "")
 
-    MULTITEAM_INFO(DEATH_TEAMKILL, 4,                       N_CONSOLE,  3, 1, "s1 s2 s3loc spree_end", "s2 s1",     "notify_teamkill_%s",   _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s"), "", NAME)
+    MULTITEAM_INFO(DEATH_TEAMKILL,                          N_CONSOLE,  3, 1, "s1 s2 s3loc spree_end", "s2 s1",     "notify_teamkill_%s",   _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s"), "", NAME)
 
     MSG_INFO_NOTIF(DOMINATION_CAPTURE_TIME,                 N_CONSOLE,  2, 2, "s1 s2 f1 f1points f2", "",       "",     _("^BG%s^BG%s^BG (%s %s every %s seconds)"), "")
 
     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_SELF,                          N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^K1 froze themself"), "")
 
-    MULTITEAM_INFO(ROUND_TEAM_WIN, 4,                       N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG team wins the round"), "", NAME)
+    MULTITEAM_INFO(ROUND_TEAM_WIN,                          N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG team wins the round"), "", NAME)
     MSG_INFO_NOTIF(ROUND_PLAYER_WIN,                        N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG wins the round"), "")
     MSG_INFO_NOTIF(ROUND_TIED,                              N_CONSOLE,  0, 0, "", "",           "",     _("^BGRound tied"), "")
     MSG_INFO_NOTIF(ROUND_OVER,                              N_CONSOLE,  0, 0, "", "",           "",     _("^BGRound over, there's no winner"), "")
     MSG_INFO_NOTIF(CONNECTING,                              N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG is connecting..."), "")
     MSG_INFO_NOTIF(JOIN_CONNECT,                            N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 connected"), "")
     MSG_INFO_NOTIF(JOIN_PLAY,                               N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 is now playing"), "")
-    MULTITEAM_INFO(JOIN_PLAY_TEAM, 4,                       N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 is now playing on the ^TC^TT team"), "", NAME)
+    MULTITEAM_INFO(JOIN_PLAY_TEAM,                          N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 is now playing on the ^TC^TT team"), "", NAME)
 
     MSG_INFO_NOTIF(KEEPAWAY_DROPPED,                        N_CONSOLE,  1, 0, "s1", "s1",       "notify_balldropped",       _("^BG%s^BG has dropped the ball!"), "")
     MSG_INFO_NOTIF(KEEPAWAY_PICKUP,                         N_CONSOLE,  1, 0, "s1", "s1",       "notify_ballpickedup",      _("^BG%s^BG has picked up the ball!"), "")
 
-    MULTITEAM_INFO(KEYHUNT_CAPTURE, 4,                      N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG captured the keys for the ^TC^TT team"), "", NAME)
-    MULTITEAM_INFO(KEYHUNT_DROP, 4,                         N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG dropped the ^TC^TT Key"), "", KEY)
-    MULTITEAM_INFO(KEYHUNT_LOST, 4,                         N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG lost the ^TC^TT Key"), "", KEY)
-    MULTITEAM_INFO(KEYHUNT_PUSHED, 4,                       N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^BG%s^BG pushed %s^BG causing the ^TC^TT Key ^BGdestruction"), "", KEY)
-    MULTITEAM_INFO(KEYHUNT_DESTROYED, 4,                    N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG destroyed the ^TC^TT Key"), "", KEY)
-    MULTITEAM_INFO(KEYHUNT_PICKUP, 4,                       N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG picked up the ^TC^TT Key"), "", KEY)
+    MULTITEAM_INFO(KEYHUNT_CAPTURE,                         N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG captured the keys for the ^TC^TT team"), "", NAME)
+    MULTITEAM_INFO(KEYHUNT_DROP,                            N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG dropped the ^TC^TT Key"), "", KEY)
+    MULTITEAM_INFO(KEYHUNT_LOST,                            N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG lost the ^TC^TT Key"), "", KEY)
+    MULTITEAM_INFO(KEYHUNT_PUSHED,                          N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^BG%s^BG pushed %s^BG causing the ^TC^TT Key ^BGdestruction"), "", KEY)
+    MULTITEAM_INFO(KEYHUNT_DESTROYED,                       N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG destroyed the ^TC^TT Key"), "", KEY)
+    MULTITEAM_INFO(KEYHUNT_PICKUP,                          N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG picked up the ^TC^TT Key"), "", KEY)
 
     MSG_INFO_NOTIF(LMS_FORFEIT,                             N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 forfeited"), "")
     MSG_INFO_NOTIF(LMS_NOLIVES,                             N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^F3 has no more lives left"), "")
 
     MSG_INFO_NOTIF(MONSTERS_DISABLED,                       N_CONSOLE,  0, 0, "", "",           "",     _("^BGMonsters are currently disabled"), "")
 
-    MULTITEAM_INFO(NEXBALL_RETURN_HELD, 4,                  N_CONSOLE,  0, 0, "", "",           "",     _("^BGThe ^TC^TT^BG team held the ball for too long"), "", NAME)
+    MULTITEAM_INFO(NEXBALL_RETURN_HELD,                     N_CONSOLE,  0, 0, "", "",           "",     _("^BGThe ^TC^TT^BG team held the ball for too long"), "", NAME)
 
     MSG_INFO_NOTIF(ONSLAUGHT_CAPTURE,                       N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^BG%s^BG captured %s^BG control point"), "")
-    MULTITEAM_INFO(ONSLAUGHT_CPDESTROYED, 4,                N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "", NAME)
-    MULTITEAM_INFO(ONSLAUGHT_GENDESTROYED, 4,               N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG generator has been destroyed"), "", GENERATOR)
-    MULTITEAM_INFO(ONSLAUGHT_GENDESTROYED_OVERTIME, 4,      N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "", GENERATOR)
+    MULTITEAM_INFO(ONSLAUGHT_CPDESTROYED,                   N_CONSOLE,  2, 0, "s1 s2", "",      "",     _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "", NAME)
+    MULTITEAM_INFO(ONSLAUGHT_GENDESTROYED,                  N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG generator has been destroyed"), "", GENERATOR)
+    MULTITEAM_INFO(ONSLAUGHT_GENDESTROYED_OVERTIME,         N_CONSOLE,  0, 0, "", "",           "",     _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "", GENERATOR)
 
     MSG_INFO_NOTIF(POWERUP_INVISIBILITY,                    N_CONSOLE,  1, 0, "s1", "s1",       "strength",     _("^BG%s^K1 picked up Invisibility"), "")
     MSG_INFO_NOTIF(POWERUP_SHIELD,                          N_CONSOLE,  1, 0, "s1", "s1",       "shield",       _("^BG%s^K1 picked up Shield"), "")
 
     MULTIICON_INFO(MINIGAME_INVITE,                         N_CONSOLE,  2, 0, "s2 minigame1_name s1", "s2", "minigame1_d", "minigames/%s/icon_notif",   _("^F4You have been invited by ^BG%s^F4 to join their game of ^F2%s^F4 (^F1%s^F4)"), "")
 
-    MULTITEAM_INFO(SCORES, 4,                               N_CONSOLE,  0, 0, "", "",           "",                     _("^TC^TT ^BGteam scores!"), "", NAME)
+    MULTITEAM_INFO(SCORES,                                  N_CONSOLE,  0, 0, "", "",           "",                     _("^TC^TT ^BGteam scores!"), "", NAME)
 
     MSG_INFO_NOTIF(SPECTATE_WARNING,                        N_CONSOLE,  0, 1, "f1secs", "",     "",                     _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "")
 
 #define N_DISABL 0
 #define N_ENABLE 1
 
-#define MULTITEAM_CENTER2(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, default, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 1), TCR(gentle, type, 1)) \
-    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, default, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 2), TCR(gentle, type, 2))
-#define MULTITEAM_CENTER3(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    MULTITEAM_CENTER2(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, default, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 3), TCR(gentle, type, 3))
-#define MULTITEAM_CENTER4(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    MULTITEAM_CENTER3(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, default, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 4), TCR(gentle, type, 4))
-#define MULTITEAM_CENTER(prefix, teams, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
-    NOTIF_ADD_AUTOCVAR(CENTER_##prefix, default) \
-    MULTITEAM_CENTER##teams(prefix, default, strnum, flnum, args, cpid, durcnt, normal, gentle, type)
+#define MULTITEAM_CENTER(prefix, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle, type) \
+    NOTIF_ADD_AUTOCVAR(CENTER_##prefix, defaultvalue) \
+    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 1), TCR(gentle, type, 1)) \
+    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 2), TCR(gentle, type, 2)) \
+    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 3), TCR(gentle, type, 3)) \
+    MSG_CENTER_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, strnum, flnum, args, cpid, durcnt, TCR(normal, type, 4), TCR(gentle, type, 4))
 
 // MSG_CENTER_NOTIFICATIONS
     MSG_CENTER_NOTIF(ALONE,                             N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^F4You are now alone!"), "")
     MSG_CENTER_NOTIF(CTF_CAPTURESHIELD_FREE,            N_ENABLE,    0, 0, "",               CPID_CTF_CAPSHIELD,     "0 0",  _("^BGYou are now free.\n^BGFeel free to ^F2try to capture^BG the flag again\n^BGif you think you will succeed."), "")
     MSG_CENTER_NOTIF(CTF_CAPTURESHIELD_INACTIVE,        N_ENABLE,    0, 0, "",               CPID_CTF_CAPSHIELD,     "0 0",  _("^BGThis flag is currently inactive"), "")
     MSG_CENTER_NOTIF(CTF_CAPTURESHIELD_SHIELDED,        N_ENABLE,    0, 0, "",               CPID_CTF_CAPSHIELD,     "0 0",  _("^BGYou are now ^F1shielded^BG from the flag(s)\n^BGfor ^F2too many unsuccessful attempts^BG to capture.\n^BGMake some defensive scores before trying again."), "")
-    MULTITEAM_CENTER(CTF_CAPTURE, 4,                    N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou captured the ^TC^TT^BG flag!"), "", FLAG)
+    MULTITEAM_CENTER(CTF_CAPTURE,                       N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou captured the ^TC^TT^BG flag!"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_CAPTURE_NEUTRAL,               N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou captured the flag!"), "")
     MSG_CENTER_NOTIF(CTF_FLAG_THROW_PUNISH,             N_ENABLE,    0, 1, "f1secs",         CPID_CTF_LOWPRIO,       "0 0",  _("^BGToo many flag throws! Throwing disabled for %s."), "")
-    MULTITEAM_CENTER(CTF_PASS_OTHER, 4,                 N_ENABLE,    2, 0, "s1 s2",          CPID_CTF_PASS,          "0 0",  _("^BG%s^BG passed the ^TC^TT^BG flag to %s"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PASS_OTHER,                    N_ENABLE,    2, 0, "s1 s2",          CPID_CTF_PASS,          "0 0",  _("^BG%s^BG passed the ^TC^TT^BG flag to %s"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PASS_OTHER_NEUTRAL,            N_ENABLE,    2, 0, "s1 s2",          CPID_CTF_PASS,          "0 0",  _("^BG%s^BG passed the flag to %s"), "")
-    MULTITEAM_CENTER(CTF_PASS_RECEIVED, 4,              N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou received the ^TC^TT^BG flag from %s"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PASS_RECEIVED,                 N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou received the ^TC^TT^BG flag from %s"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PASS_RECEIVED_NEUTRAL,         N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou received the flag from %s"), "")
     MSG_CENTER_NOTIF(CTF_PASS_REQUESTED,                N_ENABLE,    1, 0, "pass_key s1",    CPID_CTF_PASS,          "0 0",  _("^BGPress ^F2%s^BG to receive the flag from %s^BG"), "")
     MSG_CENTER_NOTIF(CTF_PASS_REQUESTING,               N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGRequesting %s^BG to pass you the flag"), "")
-    MULTITEAM_CENTER(CTF_PASS_SENT, 4,                  N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou passed the ^TC^TT^BG flag to %s"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PASS_SENT,                     N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou passed the ^TC^TT^BG flag to %s"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PASS_SENT_NEUTRAL,             N_ENABLE,    1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou passed the flag to %s"), "")
-    MULTITEAM_CENTER(CTF_PICKUP, 4,                     N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou got the ^TC^TT^BG flag!"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PICKUP,                        N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou got the ^TC^TT^BG flag!"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PICKUP_NEUTRAL,                N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou got the flag!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_RETURN,                 N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou got your %steam^BG's flag, return it!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_RETURN_ENEMY,           N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou got the %senemy^BG's flag, return it!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_ENEMY_NEUTRAL_VERBOSE,  N_ENABLE,    2, 0, "s1 s2 s1",       CPID_CTF_LOWPRIO,       "0 0",  _("^BGThe %senemy (^BG%s%s)^BG got the flag! Retrieve it!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_ENEMY_TEAM,             N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGThe %senemy^BG got their flag! Retrieve it!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_ENEMY_TEAM_VERBOSE,     N_ENABLE,    2, 0, "s1 s2 s1",       CPID_CTF_LOWPRIO,       "0 0",  _("^BGThe %senemy (^BG%s%s)^BG got their flag! Retrieve it!"), "")
-    MULTITEAM_CENTER(CTF_PICKUP_TEAM, 4,                N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate^BG got the ^TC^TT^BG flag! Protect them!"), "", FLAG)
-    MULTITEAM_CENTER(CTF_PICKUP_TEAM_VERBOSE, 4,        N_ENABLE,    2, 0, "s1 s2 s1",       CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate (^BG%s%s)^BG got the ^TC^TT^BG flag! Protect them!"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PICKUP_TEAM,                   N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate^BG got the ^TC^TT^BG flag! Protect them!"), "", FLAG)
+    MULTITEAM_CENTER(CTF_PICKUP_TEAM_VERBOSE,           N_ENABLE,    2, 0, "s1 s2 s1",       CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate (^BG%s%s)^BG got the ^TC^TT^BG flag! Protect them!"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PICKUP_TEAM_NEUTRAL,           N_ENABLE,    1, 0, "s1",             CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate^BG got the flag! Protect them!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_TEAM_VERBOSE_NEUTRAL,   N_ENABLE,    2, 0, "s1 s2 s1",       CPID_CTF_LOWPRIO,       "0 0",  _("^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"), "")
     MSG_CENTER_NOTIF(CTF_PICKUP_VISIBLE,                N_ENABLE,    0, 0, "",               CPID_STALEMATE,         "0 0",  _("^BGEnemies can now see you on radar!"), "")
-    MULTITEAM_CENTER(CTF_RETURN, 4,                     N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou returned the ^TC^TT^BG flag!"), "", FLAG)
+    MULTITEAM_CENTER(CTF_RETURN,                        N_ENABLE,    0, 0, "",               CPID_CTF_LOWPRIO,       "0 0",  _("^BGYou returned the ^TC^TT^BG flag!"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_STALEMATE_CARRIER,             N_ENABLE,    0, 0, "",               CPID_STALEMATE,         "0 0",  _("^BGStalemate! Enemies can now see you on radar!"), "")
     MSG_CENTER_NOTIF(CTF_STALEMATE_OTHER,               N_ENABLE,    0, 0, "",               CPID_STALEMATE,         "0 0",  _("^BGStalemate! Flag carriers can now be seen by enemies on radar!"), "")
 
 
     MSG_CENTER_NOTIF(GENERATOR_UNDERATTACK,             N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^BGThe generator is under attack!"), "")
 
-    MULTITEAM_CENTER(ROUND_TEAM_LOSS, 4,                N_ENABLE,    0, 0, "",               CPID_ROUND,             "0 0",  _("^TC^TT^BG team loses the round"), "", NAME)
-    MULTITEAM_CENTER(ROUND_TEAM_WIN, 4,                 N_ENABLE,    0, 0, "",               CPID_ROUND,             "0 0",  _("^TC^TT^BG team wins the round"), "", NAME)
+    MULTITEAM_CENTER(ROUND_TEAM_LOSS,                   N_ENABLE,    0, 0, "",               CPID_ROUND,             "0 0",  _("^TC^TT^BG team loses the round"), "", NAME)
+    MULTITEAM_CENTER(ROUND_TEAM_WIN,                    N_ENABLE,    0, 0, "",               CPID_ROUND,             "0 0",  _("^TC^TT^BG team wins the round"), "", NAME)
     MSG_CENTER_NOTIF(ROUND_PLAYER_WIN,                  N_ENABLE,    1, 0, "s1",             CPID_ROUND,             "0 0",  _("^BG%s^BG wins the round"), "")
 
     MSG_CENTER_NOTIF(FREEZETAG_SELF,                    N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^K1You froze yourself"), "")
     MSG_CENTER_NOTIF(KEEPAWAY_WARN,                     N_ENABLE,    0, 0, "",               CPID_KEEPAWAY_WARN,     "0 0",  _("^BGKilling people while you don't have the ball gives no points!"), "")
 
     MSG_CENTER_NOTIF(KEYHUNT_HELP,                      N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGAll keys are in your team's hands!\nHelp the key carriers to meet!"), "")
-    MULTITEAM_CENTER(KEYHUNT_INTERFERE, 4,              N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGAll keys are in ^TC^TT team^BG's hands!\nInterfere ^F4NOW^BG!"), "", NAME)
+    MULTITEAM_CENTER(KEYHUNT_INTERFERE,                 N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGAll keys are in ^TC^TT team^BG's hands!\nInterfere ^F4NOW^BG!"), "", NAME)
     MSG_CENTER_NOTIF(KEYHUNT_MEET,                      N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGAll keys are in your team's hands!\nMeet the other key carriers ^F4NOW^BG!"), "")
     MSG_CENTER_NOTIF(KEYHUNT_ROUNDSTART,                N_ENABLE,    0, 1, "",               CPID_KEYHUNT_OTHER,     "1 f1", _("^F4Round will start in ^COUNT"), "")
     MSG_CENTER_NOTIF(KEYHUNT_SCAN,                      N_ENABLE,    0, 1, "",               CPID_KEYHUNT_OTHER,     "f1 0", _("^BGScanning frequency range..."), "")
-    MULTITEAM_CENTER(KEYHUNT_START, 4,                  N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGYou are starting with the ^TC^TT Key"), "", KEY)
+    MULTITEAM_CENTER(KEYHUNT_START,                     N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGYou are starting with the ^TC^TT Key"), "", KEY)
 
     MSG_CENTER_NOTIF(LMS_NOLIVES,                       N_ENABLE,    0, 0, "",               CPID_LMS,               "0 0",  _("^BGYou have no lives left, you must wait until the next match"), "")
 
     MSG_CENTER_NOTIF(NIX_NEWWEAPON,                     N_ENABLE,    0, 1, "item_wepname",   CPID_NIX,               "0 0",  _("^F2Active weapon: ^F1%s"), "")
 
     MSG_CENTER_NOTIF(ONS_CAPTURE,                       N_ENABLE,    1, 0, "s1",             CPID_ONSLAUGHT,         "0 0",  _("^BGYou captured %s^BG control point"), "")
-    MULTITEAM_CENTER(ONS_CAPTURE_TEAM, 4,               N_ENABLE,    1, 0, "s1",             CPID_ONSLAUGHT,         "0 0",  _("^TC^TT^BG team captured %s^BG control point"), "", NAME)
+    MULTITEAM_CENTER(ONS_CAPTURE_TEAM,                  N_ENABLE,    1, 0, "s1",             CPID_ONSLAUGHT,         "0 0",  _("^TC^TT^BG team captured %s^BG control point"), "", NAME)
     MSG_CENTER_NOTIF(ONS_CONTROLPOINT_SHIELDED,         N_ENABLE,    0, 0, "",               CPID_ONS_CAPSHIELD,     "0 0",  _("^BGThis control point currently cannot be captured"), "")
     MSG_CENTER_NOTIF(ONS_GENERATOR_SHIELDED,            N_ENABLE,    0, 0, "",               CPID_ONS_CAPSHIELD,     "0 0",  _("^BGThe enemy generator cannot be destroyed yet\n^F2Capture some control points to unshield it"), "")
-    MULTITEAM_CENTER(ONS_NOTSHIELDED, 4,                N_ENABLE,    0, 0, "",               CPID_ONSLAUGHT,         "0 0",  _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "", NAME)
+    MULTITEAM_CENTER(ONS_NOTSHIELDED,                   N_ENABLE,    0, 0, "",               CPID_ONSLAUGHT,         "0 0",  _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "", NAME)
     MSG_CENTER_NOTIF(ONS_NOTSHIELDED_TEAM,              N_ENABLE,    0, 0, "",               CPID_ONSLAUGHT,         "0 0",  _("^K1Your generator is NOT shielded!\n^BGRe-capture control points to shield it!"), "")
     MSG_CENTER_NOTIF(ONS_TELEPORT,                      N_ENABLE,    0, 0, "pass_key",       CPID_ONSLAUGHT,         "0 0",  _("^BGPress ^F2%s^BG to teleport"), "")
     MSG_CENTER_NOTIF(ONS_TELEPORT_ANTISPAM,             N_ENABLE,    0, 1, "f1secs",         CPID_ONSLAUGHT,         "0 0",  _("^BGTeleporting disabled for %s"), "")
     MSG_CENTER_NOTIF(SUPERWEAPON_LOST,                  N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2Superweapons have been lost"), "")
     MSG_CENTER_NOTIF(SUPERWEAPON_PICKUP,                N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2You now have a superweapon"), "")
 
-    MULTITEAM_CENTER(TEAMCHANGE, 4,                     N_ENABLE,    0, 1, "",               CPID_TEAMCHANGE,        "1 f1", _("^K1Changing to ^TC^TT^K1 in ^COUNT"), "", NAME)
+    MULTITEAM_CENTER(TEAMCHANGE,                        N_ENABLE,    0, 1, "",               CPID_TEAMCHANGE,        "1 f1", _("^K1Changing to ^TC^TT^K1 in ^COUNT"), "", NAME)
     MSG_CENTER_NOTIF(TEAMCHANGE_AUTO,                   N_ENABLE,    0, 1, "",               CPID_TEAMCHANGE,        "1 f1", _("^K1Changing team in ^COUNT"), "")
     MSG_CENTER_NOTIF(TEAMCHANGE_SPECTATE,               N_ENABLE,    0, 1, "",               CPID_TEAMCHANGE,        "1 f1", _("^K1Spectating in ^COUNT"), "")
     MSG_CENTER_NOTIF(TEAMCHANGE_SUICIDE,                N_ENABLE,    0, 1, "",               CPID_TEAMCHANGE,        "1 f1", _("^K1Suicide in ^COUNT"), "")
 #define N_DISABL 0
 #define N_ENABLE 1
 
-#define MULTITEAM_MULTI2(prefix, default, anncepre, infopre, centerpre) \
-    MSG_MULTI_NOTIF(prefix##_RED, default, anncepre##_RED, infopre##_RED, centerpre##_RED) \
-    MSG_MULTI_NOTIF(prefix##_BLUE, default, anncepre##_BLUE, infopre##_BLUE, centerpre##_BLUE)
-#define MULTITEAM_MULTI3(prefix, default, anncepre, infopre, centerpre) \
-    MULTITEAM_MULTI2(prefix, default, anncepre, infopre, centerpre) \
-    MSG_MULTI_NOTIF(prefix##_YELLOW, default, anncepre##YELLOW, infopre##YELLOW, centerpre##YELLOW)
-#define MULTITEAM_MULTI4(prefix, default, anncepre, infopre, centerpre) \
-    MULTITEAM_MULTI3(prefix, default, anncepre, infopre, centerpre) \
-    MSG_MULTI_NOTIF(prefix##_PINK, default, anncepre##PINK, infopre##PINK, centerpre##PINK)
-#define MULTITEAM_MULTI(prefix, teams, default, anncepre, infopre, centerpre) \
-    MULTITEAM_MULTI##teams(prefix, default, anncepre, infopre, centerpre)
+#define MULTITEAM_MULTI(prefix, defaultvalue, anncepre, infopre, centerpre) \
+    MSG_MULTI_NOTIF(prefix##_RED, defaultvalue, anncepre##_RED, infopre##_RED, centerpre##_RED) \
+    MSG_MULTI_NOTIF(prefix##_BLUE, defaultvalue, anncepre##_BLUE, infopre##_BLUE, centerpre##_BLUE) \
+    MSG_MULTI_NOTIF(prefix##_YELLOW, defaultvalue, anncepre##YELLOW, infopre##YELLOW, centerpre##YELLOW) \
+    MSG_MULTI_NOTIF(prefix##_PINK, defaultvalue, anncepre##PINK, infopre##PINK, centerpre##PINK)
 
 // MSG_MULTI_NOTIFICATIONS
     MSG_MULTI_NOTIF(DEATH_MURDER_BUFF,                  N_ENABLE,  NULL,           INFO_DEATH_MURDER_BUFF,                 NULL)
     MSG_MULTI_NOTIF(WEAPON_VAPORIZER_MURDER,            N_ENABLE,  NULL,           INFO_WEAPON_VAPORIZER_MURDER,           NULL)
     MSG_MULTI_NOTIF(WEAPON_VORTEX_MURDER,               N_ENABLE,  NULL,           INFO_WEAPON_VORTEX_MURDER,              NULL)
 
-#define MULTITEAM_CHOICE2(prefix, default, challow, chtype, optiona, optionb) \
-    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, default, challow, chtype, optiona##_RED, optionb##_RED) \
-    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, default, challow, chtype, optiona##_BLUE, optionb##_BLUE)
-#define MULTITEAM_CHOICE3(prefix, default, challow, chtype, optiona, optionb) \
-    MULTITEAM_CHOICE2(prefix, default, challow, chtype, optiona, optionb) \
-    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, default, challow, chtype, optiona##_YELLOW, optionb##_YELLOW)
-#define MULTITEAM_CHOICE4(prefix, default, challow, chtype, optiona, optionb) \
-    MULTITEAM_CHOICE3(prefix, default, challow, chtype, optiona, optionb) \
-    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, default, challow, chtype, optiona##_PINK, optionb##_PINK)
-#define MULTITEAM_CHOICE(prefix, teams, default, challow, chtype, optiona, optionb) \
-    NOTIF_ADD_AUTOCVAR(CHOICE_##prefix, default) \
+#define MULTITEAM_CHOICE(prefix, defaultvalue, challow, chtype, optiona, optionb) \
+    NOTIF_ADD_AUTOCVAR(CHOICE_##prefix, defaultvalue) \
     NOTIF_ADD_AUTOCVAR(CHOICE_##prefix##_ALLOWED, challow) \
-    MULTITEAM_CHOICE##teams(prefix, default, challow, chtype, optiona, optionb)
+    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, challow, chtype, optiona##_RED, optionb##_RED) \
+    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, challow, chtype, optiona##_BLUE, optionb##_BLUE) \
+    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, challow, chtype, optiona##_YELLOW, optionb##_YELLOW) \
+    MSG_CHOICE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, challow, chtype, optiona##_PINK, optionb##_PINK)
 
 #undef N_DISABL
 #undef N_ENABLE
 #define A_ALWAYS 2
 
 // MSG_CHOICE_NOTIFICATIONS
-    MULTITEAM_CHOICE(CTF_CAPTURE_BROKEN, 4,     N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_BROKEN)
-    MULTITEAM_CHOICE(CTF_CAPTURE_TIME, 4,       N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_TIME)
-    MULTITEAM_CHOICE(CTF_CAPTURE_UNBROKEN, 4,   N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_UNBROKEN)
-    MULTITEAM_CHOICE(CTF_PICKUP_TEAM, 4,        N__NORMAL, A_ALWAYS,  MSG_CENTER, CENTER_CTF_PICKUP_TEAM,             CENTER_CTF_PICKUP_TEAM_VERBOSE)
+    MULTITEAM_CHOICE(CTF_CAPTURE_BROKEN,        N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_BROKEN)
+    MULTITEAM_CHOICE(CTF_CAPTURE_TIME,          N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_TIME)
+    MULTITEAM_CHOICE(CTF_CAPTURE_UNBROKEN,      N_VERBOSE, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_UNBROKEN)
+    MULTITEAM_CHOICE(CTF_PICKUP_TEAM,           N__NORMAL, A_ALWAYS,  MSG_CENTER, CENTER_CTF_PICKUP_TEAM,             CENTER_CTF_PICKUP_TEAM_VERBOSE)
     MSG_CHOICE_NOTIF(CTF_PICKUP_TEAM_NEUTRAL,   N__NORMAL, A_ALWAYS,  MSG_CENTER, CENTER_CTF_PICKUP_TEAM_NEUTRAL,     CENTER_CTF_PICKUP_TEAM_VERBOSE_NEUTRAL)
     MSG_CHOICE_NOTIF(CTF_PICKUP_ENEMY,          N__NORMAL, A_ALWAYS,  MSG_CENTER, CENTER_CTF_PICKUP_ENEMY,            CENTER_CTF_PICKUP_ENEMY_VERBOSE)
     MSG_CHOICE_NOTIF(CTF_PICKUP_ENEMY_NEUTRAL,  N__NORMAL, A_ALWAYS,  MSG_CENTER, CENTER_CTF_PICKUP_ENEMY_NEUTRAL,    CENTER_CTF_PICKUP_ENEMY_NEUTRAL_VERBOSE)
index b8e0d5c6998c8a37cc8ec5ea9d809116d2c3e235..663269c93558bac46a733f26d6c70a65e8921db7 100644 (file)
@@ -761,7 +761,7 @@ void Create_Notification_Entity_Choice(entity notif,
 #ifdef SVQC
 void Notification_GetCvars(entity this)
 {
-       FOREACH(Notifications, it.nent_type == MSG_CHOICE, {
+       FOREACH(Notifications, it.nent_type == MSG_CHOICE && (!it.nent_teamnum || it.nent_teamnum == NUM_TEAM_1), {
                GetCvars_handleFloat(
                        this,
                        CS(this),
index dc63a70803963ceb4c7c8f2e9b49066a6dca225e..ee39b1881ab100937221ae3604d1cac68bb817ae 100644 (file)
@@ -295,7 +295,7 @@ void Send_Notification_WOCOVA(
 // MAKE SURE THIS IS ALWAYS SYNCHRONIZED WITH THE DUMP
 // NOTIFICATIONS FUNCTION IN THE .QC FILE!
 
-#define NOTIF_ADD_AUTOCVAR(name,default) float autocvar_notification_##name = default;
+#define NOTIF_ADD_AUTOCVAR(name,defaultvalue) float autocvar_notification_##name = defaultvalue;
 
 float autocvar_notification_show_location = false;
 string autocvar_notification_show_location_string = ""; //_(" at the %s");
@@ -699,7 +699,9 @@ REGISTRY_SORT(Notifications);
 STATIC_INIT(Notifications) { FOREACH(Notifications, true, it.m_id = i); }
 REGISTRY_CHECK(Notifications)
 
-const int NOTIF_CHOICE_MAX = 50;
+const int NOTIF_CHOICE_MAX = 20;
+// NOTE: a team choice is actually made of 4 choices (one per team) with the same nent_choice_idx
+// thus they are counted as 1 in nent_choice_count
 int nent_choice_count = 0;
 .int nent_choice_idx;
 .int msg_choice_choices[NOTIF_CHOICE_MAX]; // set on each player containing MSG_CHOICE choices
@@ -707,12 +709,11 @@ int nent_choice_count = 0;
 bool notif_error;
 bool notif_global_error;
 
-STATIC_INIT_LATE(Notif_Choices) {
-       int c = 0;
-       FOREACH(Notifications, it.nent_type == MSG_CHOICE, { c++; });
-       if (c > NOTIF_CHOICE_MAX) {
-               LOG_FATALF("Too many MSG_CHOICE notifications (%d)", c);
-       }
+STATIC_INIT_LATE(Notif_Choices)
+{
+       if (nent_choice_count > NOTIF_CHOICE_MAX)
+               LOG_FATALF("Too many MSG_CHOICE notifications (%d), hit NOTIF_CHOICE_MAX (%d) limit",
+                       nent_choice_count, NOTIF_CHOICE_MAX);
 }
 
 string Get_Notif_CvarName(Notification notif)
@@ -736,16 +737,16 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
        return it;
 }
 
-#define MSG_ANNCE_NOTIF_TEAM(teamnum, name, cvarname, default, sound, channel, volume, position) \
-       MSG_ANNCE_NOTIF_(teamnum, ANNCE_##name, ANNCE_##cvarname, default, sound, channel, volume, position)
+#define MSG_ANNCE_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position) \
+       MSG_ANNCE_NOTIF_(teamnum, ANNCE_##name, ANNCE_##cvarname, defaultvalue, sound, channel, volume, position)
 
-#define MSG_ANNCE_NOTIF(name, default, sound, channel, volume, position) \
-       NOTIF_ADD_AUTOCVAR(ANNCE_##name, default) \
-       MSG_ANNCE_NOTIF_(0, ANNCE_##name, ANNCE_##name, default, sound, channel, volume, position)
+#define MSG_ANNCE_NOTIF(name, defaultvalue, sound, channel, volume, position) \
+       NOTIF_ADD_AUTOCVAR(ANNCE_##name, defaultvalue) \
+       MSG_ANNCE_NOTIF_(0, ANNCE_##name, ANNCE_##name, defaultvalue, sound, channel, volume, position)
 
-#define MSG_ANNCE_NOTIF_(teamnum, name, cvarname, default, sound, channel, volume, position) \
+#define MSG_ANNCE_NOTIF_(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position) \
        REGISTER(Notifications, name, m_id, new_pure(msg_annce_notification)) { \
-               Create_Notification_Entity      (this, default, ACVNN(cvarname), MSG_ANNCE, strtoupper(#name), teamnum); \
+               Create_Notification_Entity      (this, defaultvalue, ACVNN(cvarname), MSG_ANNCE, strtoupper(#name), teamnum); \
                Create_Notification_Entity_Annce(this, ACVNN(cvarname), strtoupper(#name), \
                        channel,   /* channel  */ \
                        sound,     /* snd      */ \
@@ -753,16 +754,16 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
                        position); /* position */ \
        }
 
-#define MSG_INFO_NOTIF_TEAM(teamnum, name, cvarname, default, strnum, flnum, args, hudargs, icon, normal, gentle) \
-       MSG_INFO_NOTIF_(teamnum, INFO_##name, INFO_##cvarname, default, strnum, flnum, args, hudargs, icon, normal, gentle)
+#define MSG_INFO_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle) \
+       MSG_INFO_NOTIF_(teamnum, INFO_##name, INFO_##cvarname, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle)
 
-#define MSG_INFO_NOTIF(name, default, strnum, flnum, args, hudargs, icon, normal, gentle) \
-       NOTIF_ADD_AUTOCVAR(INFO_##name, default) \
-       MSG_INFO_NOTIF_(0, INFO_##name, INFO_##name, default, strnum, flnum, args, hudargs, icon, normal, gentle)
+#define MSG_INFO_NOTIF(name, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle) \
+       NOTIF_ADD_AUTOCVAR(INFO_##name, defaultvalue) \
+       MSG_INFO_NOTIF_(0, INFO_##name, INFO_##name, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle)
 
-#define MSG_INFO_NOTIF_(teamnum, name, cvarname, default, strnum, flnum, args, hudargs, icon, normal, gentle) \
+#define MSG_INFO_NOTIF_(teamnum, name, cvarname, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle) \
        REGISTER(Notifications, name, m_id, new_pure(msg_info_notification)) { \
-               Create_Notification_Entity           (this, default, ACVNN(cvarname), MSG_INFO, strtoupper(#name), teamnum); \
+               Create_Notification_Entity           (this, defaultvalue, ACVNN(cvarname), MSG_INFO, strtoupper(#name), teamnum); \
                Create_Notification_Entity_InfoCenter(this, ACVNN(cvarname), strtoupper(#name), strnum, flnum, \
                        args,     /* args    */ \
                        hudargs,  /* hudargs */ \
@@ -774,12 +775,12 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
        }
 
 .string nent_iconargs;
-#define MULTIICON_INFO(name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
-       MULTIICON_INFO_(INFO_##name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle)
-#define MULTIICON_INFO_(name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
-       NOTIF_ADD_AUTOCVAR(name, default) \
+#define MULTIICON_INFO(name, defaultvalue, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
+       MULTIICON_INFO_(INFO_##name, defaultvalue, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle)
+#define MULTIICON_INFO_(name, defaultvalue, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
+       NOTIF_ADD_AUTOCVAR(name, defaultvalue) \
        REGISTER(Notifications, name, m_id, new_pure(msg_info_notification)) { \
-               Create_Notification_Entity           (this, default, ACVNN(name), MSG_INFO, strtoupper(#name), 0); \
+               Create_Notification_Entity           (this, defaultvalue, ACVNN(name), MSG_INFO, strtoupper(#name), 0); \
                Create_Notification_Entity_InfoCenter(this, ACVNN(name), strtoupper(#name), strnum, flnum, \
                        args,     /* args    */ \
                        hudargs,  /* hudargs */ \
@@ -791,16 +792,16 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
                this.nent_iconargs = iconargs; \
        }
 
-#define MSG_CENTER_NOTIF_TEAM(teamnum, name, cvarname, default, strnum, flnum, args, cpid, durcnt, normal, gentle) \
-       MSG_CENTER_NOTIF_(teamnum, CENTER_##name, CENTER_##cvarname, default, strnum, flnum, args, cpid, durcnt, normal, gentle)
+#define MSG_CENTER_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle) \
+       MSG_CENTER_NOTIF_(teamnum, CENTER_##name, CENTER_##cvarname, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle)
 
-#define MSG_CENTER_NOTIF(name, default, strnum, flnum, args, cpid, durcnt, normal, gentle) \
-       NOTIF_ADD_AUTOCVAR(CENTER_##name, default) \
-       MSG_CENTER_NOTIF_(0, CENTER_##name, CENTER_##name, default, strnum, flnum, args, cpid, durcnt, normal, gentle)
+#define MSG_CENTER_NOTIF(name, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle) \
+       NOTIF_ADD_AUTOCVAR(CENTER_##name, defaultvalue) \
+       MSG_CENTER_NOTIF_(0, CENTER_##name, CENTER_##name, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle)
 
-#define MSG_CENTER_NOTIF_(teamnum, name, cvarname, default, strnum, flnum, args, cpid, durcnt, normal, gentle) \
+#define MSG_CENTER_NOTIF_(teamnum, name, cvarname, defaultvalue, strnum, flnum, args, cpid, durcnt, normal, gentle) \
        REGISTER(Notifications, name, m_id, new_pure(msg_center_notification)) { \
-               Create_Notification_Entity           (this, default, ACVNN(cvarname), MSG_CENTER, strtoupper(#name), teamnum); \
+               Create_Notification_Entity           (this, defaultvalue, ACVNN(cvarname), MSG_CENTER, strtoupper(#name), teamnum); \
                Create_Notification_Entity_InfoCenter(this, ACVNN(cvarname), strtoupper(#name), strnum, flnum, \
                        args,    /* args    */ \
                        "",      /* hudargs */ \
@@ -811,28 +812,30 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
                        gentle); /* gentle  */ \
        }
 
-#define MSG_MULTI_NOTIF(name, default, anncename, infoname, centername) \
-       NOTIF_ADD_AUTOCVAR(name, default) \
+#define MSG_MULTI_NOTIF(name, defaultvalue, anncename, infoname, centername) \
+       NOTIF_ADD_AUTOCVAR(name, defaultvalue) \
        REGISTER(Notifications, name, m_id, new_pure(msg_multi_notification)) { \
-               Create_Notification_Entity      (this, default, ACVNN(name), MSG_MULTI, strtoupper(#name), 0); \
+               Create_Notification_Entity      (this, defaultvalue, ACVNN(name), MSG_MULTI, strtoupper(#name), 0); \
                Create_Notification_Entity_Multi(this, ACVNN(name), strtoupper(#name), \
                        anncename,   /* anncename  */ \
                        infoname,    /* infoname   */ \
                        centername); /* centername */ \
        }
 
-#define MSG_CHOICE_NOTIF_TEAM(teamnum, name, cvarname, default, challow, chtype, optiona, optionb) \
-       MSG_CHOICE_NOTIF_(teamnum, CHOICE_##name, CHOICE_##cvarname, default, challow, chtype, optiona, optionb)
+#define MSG_CHOICE_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, challow, chtype, optiona, optionb) \
+       MSG_CHOICE_NOTIF_(teamnum, CHOICE_##name, CHOICE_##cvarname, defaultvalue, challow, chtype, optiona, optionb)
 
-#define MSG_CHOICE_NOTIF(name, default, challow, chtype, optiona, optionb) \
-       NOTIF_ADD_AUTOCVAR(CHOICE_##name, default) \
+#define MSG_CHOICE_NOTIF(name, defaultvalue, challow, chtype, optiona, optionb) \
+       NOTIF_ADD_AUTOCVAR(CHOICE_##name, defaultvalue) \
        NOTIF_ADD_AUTOCVAR(CHOICE_##name##_ALLOWED, challow) \
-       MSG_CHOICE_NOTIF_(0, CHOICE_##name, CHOICE_##name, default, challow, chtype, optiona, optionb)
+       MSG_CHOICE_NOTIF_(0, CHOICE_##name, CHOICE_##name, defaultvalue, challow, chtype, optiona, optionb)
 
-#define MSG_CHOICE_NOTIF_(teamnum, name, cvarname, default, challow, chtype, optiona, optionb) \
+#define MSG_CHOICE_NOTIF_(teamnum, name, cvarname, defaultvalue, challow, chtype, optiona, optionb) \
        REGISTER(Notifications, name, m_id, new_pure(msg_choice_notification)) { \
-               this.nent_choice_idx = nent_choice_count++; \
-               Create_Notification_Entity       (this, default, ACVNN(cvarname), MSG_CHOICE, strtoupper(#name), teamnum); \
+               this.nent_choice_idx = nent_choice_count; \
+               if (!teamnum || teamnum == NUM_TEAM_4) \
+                       nent_choice_count++; \
+               Create_Notification_Entity       (this, defaultvalue, ACVNN(cvarname), MSG_CHOICE, strtoupper(#name), teamnum); \
                Create_Notification_Entity_Choice(this, ACVNN(cvarname), strtoupper(#name), \
                        challow,                                 /* challow_def */ \
                        autocvar_notification_##cvarname##_ALLOWED,  /* challow_var */ \
@@ -856,4 +859,17 @@ REGISTRY_END(Notifications)
                LOG_SEVERE("Notification initialization failed! Read above and fix the errors!");
 }
 
+#ifdef CSQC
+.int cvar_value;
+void ReplicateVars(bool would_destroy)
+{
+       if (!would_destroy)
+               FOREACH(Notifications, it.nent_type == MSG_CHOICE, {
+                       string cvarname = sprintf("notification_%s", Get_Notif_CvarName(it));
+                       // NOTE: REPLICATE_SIMPLE can return;
+                       REPLICATE_SIMPLE(it.cvar_value, cvarname);
+               });
+}
+#endif
+
 #include "all.inc"
index cbb54cd26e575c8cb6e67740b0b48fa2f02516bf..8eb2277d54ad9cd2b98c2d9dc5d2199725245c7c 100644 (file)
@@ -34,8 +34,10 @@ void _Movetype_WallFriction(entity this, vector stepnormal)  // SV_WallFriction
 }
 
 vector planes[MAX_CLIP_PLANES];
-int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, bool applystepnormal, float stepheight) // SV_FlyMove
 {
+       move_stepnormal = '0 0 0';
+
        if(dt <= 0)
                return 0;
 
@@ -150,8 +152,8 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        // step - return it to caller
                        blocked |= 2;
                        // save the trace for player extrafriction
-                       if(stepnormal)
-                               stepnormal = trace_plane_normal;
+                       if(applystepnormal)
+                               move_stepnormal = trace_plane_normal;
                }
 
                if(my_trace_fraction >= 0.001)
@@ -348,6 +350,10 @@ void _Movetype_LinkEdict_TouchAreaGrid(entity this)  // SV_LinkEdict_TouchAreaGr
                        trace_plane_normal = '0 0 1';
                        trace_plane_dist = 0;
                        trace_ent = this;
+                       trace_dpstartcontents = 0;
+                       trace_dphitcontents = 0;
+                       trace_dphitq3surfaceflags = 0;
+                       trace_dphittexturename = string_null;
 
                        gettouch(it)(it, this);
                }
@@ -505,10 +511,11 @@ bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool
 {
        _Movetype_PushEntityTrace(this, push);
 
+       // NOTE: this is a workaround for the QC's lack of a worldstartsolid trace parameter
        if(trace_startsolid && failonstartsolid)
        {
                int oldtype = this.move_nomonsters;
-               this.move_nomonsters = MOVE_NOMONSTERS;
+               this.move_nomonsters = MOVE_WORLDONLY;
                _Movetype_PushEntityTrace(this, push);
                this.move_nomonsters = oldtype;
                if(trace_startsolid)
@@ -523,7 +530,7 @@ bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool
                _Movetype_LinkEdict(this, true);
 
        if(trace_fraction < 1)
-               if(this.solid >= SOLID_TRIGGER && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
+               if(this.solid >= SOLID_TRIGGER && trace_ent && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
                        _Movetype_Impact(this, trace_ent);
 
        return (this.origin == last_origin); // false if teleported by touch
index 1eb2d95e47b8ab98c8ae6d96e4c24b6135f16b7a..51da5e730c1169de3b2552b93953d0b68b0720b2 100644 (file)
@@ -85,8 +85,11 @@ const int UNSTICK_FINE = 0;
 const int UNSTICK_FIXED = 1;
 const int UNSTICK_STUCK = 2;
 
+// set by _Movetype_FlyMove
+vector move_stepnormal;
+
 void _Movetype_WallFriction(entity this, vector stepnormal);
-int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight);
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, bool applystepnormal, float stepheight);
 void _Movetype_CheckVelocity(entity this);
 void _Movetype_CheckWaterTransition(entity ent);
 void _Movetype_CheckStuck(entity this);
index a41269f79c562122fe8f01e6745cfa7df2180748..30ebe6afadf73a244831de58421d3afe60379066 100644 (file)
@@ -7,14 +7,14 @@ void _Movetype_Physics_Step(entity this, float dt) // SV_Physics_Step
                {
                        UNSET_ONGROUND(this);
                        _Movetype_CheckVelocity(this);
-                       _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+                       _Movetype_FlyMove(this, dt, true, false, 0);
                        _Movetype_LinkEdict(this, true);
                }
        }
        else
        {
                _Movetype_CheckVelocity(this);
-               _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+               _Movetype_FlyMove(this, dt, true, false, 0);
                _Movetype_LinkEdict(this, true);
 
                // TODO? movetypesteplandevent
index 5c7ae9ee2a6e2797e7c2b4db9f09d8a42e1c3548..13224f8a3443d022658aa9307dca2f522979d16f 100644 (file)
@@ -1,8 +1,6 @@
 #include "walk.qh"
 void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 {
-       vector stepnormal = '0 0 0';
-
        // if frametime is 0 (due to client sending the same timestamp twice), don't move
        if (dt <= 0)
                return;
@@ -28,7 +26,7 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
                        this.pm_time -= dt;
        }
 
-       int clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES(this) ? PHYS_STEPHEIGHT(this) : 0);
+       int clip = _Movetype_FlyMove(this, dt, applygravity, false, GAMEPLAYFIX_STEPMULTIPLETIMES(this) ? PHYS_STEPHEIGHT(this) : 0);
 
        if (GAMEPLAYFIX_DOWNTRACEONGROUND(this) && !(clip & 1))
        {
@@ -108,7 +106,7 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 
                // move forward
                this.velocity_z = 0;
-               clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, 0);
+               clip = _Movetype_FlyMove(this, dt, applygravity, true, 0);
                this.velocity_z += start_velocity.z;
                if (clip & 8)
                {
@@ -142,7 +140,7 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 
                // extra friction based on view angle
                if ((clip & 2) && PHYS_WALLFRICTION(this))
-                       _Movetype_WallFriction(this, stepnormal);
+                       _Movetype_WallFriction(this, move_stepnormal);
        }
        // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
        else if (!GAMEPLAYFIX_STEPDOWN(this) || this.waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || IS_ONGROUND(this))
index acef8c97ad183273d5e944e5c119838bc4d6eb54..251bf995aaf9ae966bd09da2b80fca977398948e 100644 (file)
@@ -472,7 +472,7 @@ void CheckPlayerJump(entity this)
 
                bool air_jump = !playerjump || M_ARGV(2, bool);
                bool activate = JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this);
-               bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO);
+               bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_AMMO);
 
                if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
                else if (this.jetpack_stopped) { }
@@ -785,7 +785,7 @@ void PM_jetpack(entity this, float maxspd_mod, float dt)
        wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
 
        fvel = min(1, vlen(wishvel) / best);
-       if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+       if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
                f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * dt * fvel));
        else
                f = 1;
@@ -798,7 +798,7 @@ void PM_jetpack(entity this, float maxspd_mod, float dt)
                UNSET_ONGROUND(this);
 
 #ifdef SVQC
-               if (!(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+               if (!(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
                        TakeResource(this, RES_FUEL, PHYS_JETPACK_FUEL(this) * dt * fvel * f);
 
                ITEMS_STAT(this) |= IT_USING_JETPACK;
index 2c9bbcde805eb9770015c385877971563b872731..cf272e5635a1eb66e72ec90810b864b10eff9f27 100644 (file)
@@ -152,6 +152,8 @@ void PlayerStats_GameReport_FinalizePlayer(entity p)
                        if(latency)
                                PlayerStats_GameReport_Event_Player(p, PLAYERSTATS_AVGLATENCY, latency);
                }
+
+               db_put(PS_GR_OUT_DB, sprintf("%s:_ranked", p.playerstats_id), ftos(CS(p).cvar_cl_allow_uidranking));
        }
 
        strfree(p.playerstats_id);
@@ -376,6 +378,10 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
                                        url_fputs(fh, sprintf("t %s\n", tt));
                                }
 
+                               // elo ranking enabled
+                               nn = db_get(PS_GR_OUT_DB, sprintf("%s:_ranked", p));
+                               if(nn != "") { url_fputs(fh, sprintf("r %s\n", nn)); }
+
                                // output player events
                                for(e = PS_GR_OUT_EVL; (en = db_get(PS_GR_OUT_DB, sprintf("*:%s", e))) != ""; e = en)
                                {
index 31b5ed4873642ceb21b2fb3fae77b66c5770fd23..29f2946b059d7d4c65c9f2c9cf1e8cef3da52753 100644 (file)
@@ -198,6 +198,7 @@ SOUND(ONS_CONTROLPOINT_BUILT, "onslaught/controlpoint_built");
 SOUND(ONS_CONTROLPOINT_UNDERATTACK, "onslaught/controlpoint_underattack");
 SOUND(ONS_DAMAGEBLOCKEDBYSHIELD, "onslaught/damageblockedbyshield");
 SOUND(ONS_ELECTRICITY_EXPLODE, "onslaught/electricity_explode");
+SOUND(ONS_GENERATOR_ALARM, "kh/alarm"); // FIXME: unique sound
 SOUND(ONS_GENERATOR_DECAY, "onslaught/generator_decay");
 SOUND(ONS_GENERATOR_UNDERATTACK, "onslaught/generator_underattack");
 SOUND(ONS_HIT1, "onslaught/ons_hit1");
@@ -236,6 +237,7 @@ SOUND(VEH_SPIDERBOT_STRAFE, "vehicles/spiderbot_strafe");
 SOUND(VEH_SPIDERBOT_WALK, "vehicles/spiderbot_walk");
 
 SOUND(NADE_BEEP, "overkill/grenadebip");
+SOUND(NADE_BONUS, "kh/alarm"); // FIXME: unique sound
 
 SOUND(BUFF_LOST, "relics/relic_effect");
 
index af85fa1a332082b48d3d2d5c33345141ee274588..45cd41f15e1041e28acdfe95d0265749db116b7f 100644 (file)
@@ -130,7 +130,7 @@ CLASS(Sound, Object)
                TC(Sound, this);
                string s = _Sound_fixpath(this.sound_str());
                if (!s) return;
-               profile(sprintf("precache_sound(\"%s\")", s));
+               //profile(sprintf("precache_sound(\"%s\")", s));
                precache_sound(s);
                strcpy(this.sound_str_, s);
        }
index 2a1168eae017978fe7f56d72004bda716fc49344..0f40acfc6856b65ad68446091b5a9142d3d16e13 100644 (file)
@@ -5,6 +5,9 @@ void Inventory_delete(entity this);
 
 void PlayerState_attach(entity this)
 {
+       if (PS(this))
+               return;
+
        this._ps = NEW(PlayerState, this);
 
        Inventory_new(PS(this));
@@ -38,8 +41,6 @@ void ClientState_attach(entity this)
 {
        this._cs = NEW(ClientState, this);
 
-    GetCvars(this, CS(this), 0);  // get other cvars from player
-
        // TODO: fold all of these into ClientState
 
        DecodeLevelParms(this);
index cf51ea66b3ebf7b24d86c16c89756347fa5bca0c..488d44220b19e46ca047d18e11511e3d2d223e0b 100644 (file)
@@ -43,8 +43,12 @@ const int MAX_CL_STATS = 256;
 #endif
 
 #ifdef SVQC
+/// all the weapons actually spawned in the map, does not include filtered items
 vector weaponsInMap;
+/// all the weapons placed by the mapper (weaponreplace applied), ignores most filters
+vector weaponsInMapAll;
 #endif
+
 REGISTER_STAT(WEAPONS, vectori)
 REGISTER_STAT(WEAPONSINMAP, vectori, weaponsInMap)
 
@@ -183,12 +187,12 @@ REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref)
 REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer)
 
 #ifdef SVQC
-int autocvar_sv_gameplayfix_downtracesupportsongroundflag;
-int autocvar_sv_gameplayfix_easierwaterjump;
-int autocvar_sv_gameplayfix_stepdown;
-int autocvar_sv_gameplayfix_stepmultipletimes;
-int autocvar_sv_gameplayfix_unstickplayers;
-int autocvar_sv_gameplayfix_fixedcheckwatertransition;
+int autocvar_sv_gameplayfix_downtracesupportsongroundflag = 1;
+int autocvar_sv_gameplayfix_easierwaterjump = 1;
+int autocvar_sv_gameplayfix_stepdown = 2;
+int autocvar_sv_gameplayfix_stepmultipletimes = 1;
+int autocvar_sv_gameplayfix_unstickplayers = 1;
+int autocvar_sv_gameplayfix_fixedcheckwatertransition = 1;
 #endif
 REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag)
 REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump)
@@ -325,7 +329,7 @@ REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float)
 REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float)
 REGISTER_STAT(MOVEVARS_AIRCONTROL_BACKWARDS, bool)
 REGISTER_STAT(MOVEVARS_AIRCONTROL_SIDEWARDS, bool)
-noref bool autocvar_sv_gameplayfix_nogravityonground;
+noref bool autocvar_sv_gameplayfix_nogravityonground = true;
 REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID
                               | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0)
                               | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0)
@@ -370,14 +374,6 @@ int autocvar_sv_wallclip;
 #endif
 REGISTER_STAT(MOVEVARS_WALLCLIP, int, autocvar_sv_wallclip)
 
-
-#ifdef CSQC
-noref int autocvar_cl_gunalign;
-#endif
-#ifdef SVQC
-.int cvar_cl_gunalign;
-REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
-#endif
 REGISTER_STAT(GUNALIGN, int)
 #ifdef SVQC
 SPECTATE_COPYFIELD(_STAT(GUNALIGN))
index 466b38311214c20d0aa66baefa1a7d35fcf93c98..9d595b9591df90326e8d188c17ef2abfdc94f6ee 100644 (file)
@@ -356,8 +356,8 @@ bool ItemSend(entity this, entity to, int sf)
        {
                WriteShort(MSG_ENTITY, this.colormap);
                WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
-        WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
-        WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
+               WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
+               WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
        }
 
        if(sf & ISF_DROP)
@@ -402,7 +402,7 @@ bool have_pickup_item(entity this)
        return true;
 }
 
-void Item_Show (entity e, int mode)
+void Item_Show(entity e, int mode)
 {
        e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST);
        e.ItemStatus &= ~ITS_STAYWEP;
@@ -479,13 +479,13 @@ float Item_ItemsTime_UpdateTime(entity e, float t);
 void Item_ItemsTime_SetTime(entity e, float t);
 void Item_ItemsTime_SetTimesForAllPlayers();
 
-void Item_Respawn (entity this)
+void Item_Respawn(entity this)
 {
        Item_Show(this, 1);
        sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM);     // play respawn sound
        setorigin(this, this.origin);
 
-    if (Item_ItemsTime_Allow(this.itemdef) || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
+       if (Item_ItemsTime_Allow(this.itemdef) || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
        {
                float t = Item_ItemsTime_UpdateTime(this, 0);
                Item_ItemsTime_SetTime(this, t);
@@ -499,7 +499,7 @@ void Item_Respawn (entity this)
        Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
 }
 
-void Item_RespawnCountdown (entity this)
+void Item_RespawnCountdown(entity this)
 {
        if(this.item_respawncounter >= ITEM_RESPAWN_TICKS)
        {
@@ -624,7 +624,7 @@ float adjust_respawntime(float normal_respawntime) {
                }
        }
        TeamBalance_Destroy(balance);
-       
+
        if (players >= 2) {
                return normal_respawntime * (r / (players + o) + l);
        } else {
@@ -780,14 +780,14 @@ bool Item_GiveTo(entity item, entity player)
                }
        }
        bool pickedup = false;
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max));
-       pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max));
+       pickedup |= Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
        if (item.itemdef.instanceOfWeaponPickup)
        {
                WepSet w;
@@ -927,6 +927,9 @@ void Item_Touch(entity this, entity toucher)
 
 LABEL(pickup)
 
+       if(this.target && this.target != "" && this.target != "###item###") // defrag support
+               SUB_UseTargets(this, toucher, NULL);
+
        STAT(LAST_PICKUP, toucher) = time;
 
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
@@ -1005,8 +1008,8 @@ void Item_FindTeam(entity this)
                });
 
                e = RandomSelection_chosen_ent;
-               e.state = 0;
-               Item_Show(e, 1);
+               if (!e)
+                       return;
 
                IL_EACH(g_items, it.team == this.team,
                {
@@ -1018,11 +1021,11 @@ void Item_FindTeam(entity this)
                                        Item_Show(it, -1);
                                        it.state = 1; // state 1 = initially hidden item, apparently
                                }
+                               else
+                                       Item_Reset(it);
                                it.effects &= ~EF_NODRAW;
                        }
                });
-
-               Item_Reset(this);
        }
 }
 
@@ -1169,7 +1172,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
 {
        string itemname = def.m_name;
        Model itemmodel = def.m_model;
-    Sound pickupsound = def.m_sound;
+       Sound pickupsound = def.m_sound;
        float(entity player, entity item) pickupevalfunc = def.m_pickupevalfunc;
        float pickupbasevalue = def.m_botvalue;
        int itemflags = def.m_itemflags;
@@ -1177,10 +1180,10 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        startitem_failed = false;
 
        this.item_model_ent = itemmodel;
-    this.item_pickupsound_ent = pickupsound;
+       this.item_pickupsound_ent = pickupsound;
 
-    if(def.m_iteminit)
-       def.m_iteminit(def, this);
+       if(def.m_iteminit)
+               def.m_iteminit(def, this);
 
        if(!this.respawntime) // both need to be set
        {
@@ -1314,7 +1317,11 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                        || (def.instanceOfHealth && def != ITEM_HealthSmall)
                        || (def.instanceOfArmor && def != ITEM_ArmorSmall)
                        || (itemid & (IT_KEY1 | IT_KEY2))
-               ) this.target = "###item###"; // for finding the nearest item using findnearest
+               )
+               {
+                       if(!this.target || this.target == "")
+                               this.target = "###item###"; // for finding the nearest item using findnearest
+               }
 
                Item_ItemsTime_SetTime(this, 0);
        }
@@ -1353,7 +1360,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        }
 
        this.state = 0;
-       if(this.team) // broken, no idea why.
+       if(this.team)
        {
                if(!this.cnt)
                        this.cnt = 1; // item probability weight
@@ -1470,9 +1477,6 @@ void target_items_use(entity this, entity actor, entity trigger)
 
 spawnfunc(target_items)
 {
-       int n;
-       string s;
-
        this.use = target_items_use;
        if(!this.strength_finished)
                this.strength_finished = autocvar_g_balance_powerup_strength_time;
@@ -1481,7 +1485,7 @@ spawnfunc(target_items)
        if(!this.superweapons_finished)
                this.superweapons_finished = autocvar_g_balance_superweapons_time;
 
-       n = tokenize_console(this.netname);
+       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));
@@ -1490,8 +1494,9 @@ spawnfunc(target_items)
        {
                for(int j = 0; j < n; ++j)
                {
-                       if     (argv(j) == "unlimited_ammo")         this.items |= IT_UNLIMITED_AMMO;
-                       else if(argv(j) == "unlimited_weapon_ammo")  this.items |= IT_UNLIMITED_WEAPON_AMMO;
+                       // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+                       if     (argv(j) == "unlimited_ammo")         this.items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+                       else if(argv(j) == "unlimited_weapon_ammo")  this.items |= IT_UNLIMITED_AMMO;
                        else if(argv(j) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
                        else if(argv(j) == "strength")               this.items |= ITEM_Strength.m_itemid;
                        else if(argv(j) == "invincible")             this.items |= ITEM_Shield.m_itemid;
@@ -1502,15 +1507,17 @@ spawnfunc(target_items)
                        {
                                FOREACH(Buffs, it != BUFF_Null,
                                {
-                                       s = Buff_UndeprecateName(argv(j));
-                                       if(s == it.m_name)
+                                       string s = Buff_UndeprecateName(argv(j));
+                                       if(s == it.netname)
                                        {
                                                STAT(BUFFS, this) |= (it.m_itemid);
+                                               if(!STAT(BUFF_TIME, this))
+                                                       STAT(BUFF_TIME, this) = it.m_time(it);
                                                break;
                                        }
                                });
                                FOREACH(Weapons, it != WEP_Null, {
-                                       s = W_UndeprecateName(argv(j));
+                                       string s = W_UndeprecateName(argv(j));
                                        if(s == it.netname)
                                        {
                                                STAT(WEAPONS, this) |= (it.m_wepset);
@@ -1550,7 +1557,7 @@ spawnfunc(target_items)
                }
 
                this.netname = "";
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
+               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");
@@ -1565,7 +1572,7 @@ spawnfunc(target_items)
                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, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(STAT(BUFFS, this) & (it.m_itemid)), it.m_name));
+               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);
@@ -1575,8 +1582,8 @@ spawnfunc(target_items)
        for(int j = 0; j < n; ++j)
        {
                FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(argv(j)) == it.netname, {
-            it.wr_init(it);
-            break;
+                       it.wr_init(it);
+                       break;
                });
        }
 }
@@ -1615,28 +1622,28 @@ 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);
-       switch(op)
+       switch (op)
        {
                case OP_SET:
-                       if(val > 0)
-                               STAT(BUFFS, e) |= thebuff.m_itemid;
-                       else
-                               STAT(BUFFS, e) &= ~thebuff.m_itemid;
+                       STAT(BUFF_TIME, e) = val;
                        break;
                case OP_MIN:
-               case OP_PLUS:
-                       if(val > 0)
-                               STAT(BUFFS, e) |= thebuff.m_itemid;
+                       STAT(BUFF_TIME, e) = max(STAT(BUFF_TIME, e), val);
                        break;
                case OP_MAX:
-                       if(val <= 0)
-                               STAT(BUFFS, e) &= ~thebuff.m_itemid;
+                       STAT(BUFF_TIME, e) = min(STAT(BUFF_TIME, e), val);
+                       break;
+               case OP_PLUS:
+                       STAT(BUFF_TIME, e) += val;
                        break;
                case OP_MINUS:
-                       if(val > 0)
-                               STAT(BUFFS, e) &= ~thebuff.m_itemid;
+                       STAT(BUFF_TIME, e) -= val;
                        break;
        }
+       if(STAT(BUFF_TIME, e) <= 0)
+               STAT(BUFFS, e) &= ~thebuff.m_itemid;
+       else
+               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);
 }
@@ -1706,6 +1713,7 @@ 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(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
 
        PREGIVE(e, items);
        PREGIVE_WEAPONS(e);
@@ -1753,13 +1761,13 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveValue(e, strength_finished, op, val);
                                got += GiveValue(e, invincible_finished, op, val);
                                got += GiveValue(e, superweapons_finished, op, val);
-                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, 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);
                                got += GiveResourceValue(e, RES_HEALTH, op, val);
                                got += GiveResourceValue(e, RES_ARMOR, op, val);
                        case "allweapons":
-                               FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED), got += GiveWeapon(e, it.m_id, op, val));
+                               FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)), got += GiveWeapon(e, it.m_id, op, val));
                        //case "allbuffs": // all buffs makes a player god, do not want!
                                //FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val));
                        case "allammo":
@@ -1771,10 +1779,11 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveResourceValue(e, RES_FUEL, op, val);
                                break;
                        case "unlimited_ammo":
-                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
+                               // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+                               got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
                                break;
                        case "unlimited_weapon_ammo":
-                               got += GiveBit(e, items, IT_UNLIMITED_WEAPON_AMMO, op, val);
+                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
                                break;
                        case "unlimited_superweapons":
                                got += GiveBit(e, items, IT_UNLIMITED_SUPERWEAPONS, op, val);
@@ -1820,7 +1829,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.m_name,
+                               FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.netname,
                                {
                                        got += GiveBuff(e, it, op, val);
                                        break;
@@ -1837,7 +1846,7 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND_POWERUP, SND_POWEROFF);
-       POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, SND_POWERUP, SND_POWEROFF);
+       POSTGIVE_BIT(e, items, IT_UNLIMITED_AMMO, SND_POWERUP, SND_POWEROFF);
        POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND_ITEMPICKUP, SND_Null);
        FOREACH(Weapons, it != WEP_Null, {
                POSTGIVE_WEAPON(e, it, SND_WEAPONPICKUP, SND_Null);
@@ -1858,7 +1867,7 @@ float GiveItems(entity e, float beginarg, float endarg)
        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(!g_weaponarena && STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS)
+               if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
                        e.superweapons_finished = autocvar_g_balance_superweapons_time;
 
        if(e.strength_finished <= 0)
@@ -1873,6 +1882,10 @@ float GiveItems(entity e, float beginarg, float endarg)
                e.superweapons_finished = 0;
        else
                e.superweapons_finished += time;
+       if(STAT(BUFF_TIME, e) <= 0)
+               STAT(BUFF_TIME, e) = 0;
+       else
+               STAT(BUFF_TIME, e) += time;
 
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
index a0321c2444961234305f7689ef5d32b8d0008685..5c916866f8691f840d34f43ccdf39a51a7d5f95c 100644 (file)
@@ -1,6 +1,6 @@
 #pragma once
 
-const int AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
+const int AMMO_COUNT = 4; // amount of ammo types to show in the ammo panel
 
 // item networking
 const int ISF_LOCATION                         = BIT(1);
index f5ba71477982d4ec6b727d1312aaf36633269a1c..25c61b4b67b19c1192a7752b23a77f8cd7945581 100644 (file)
@@ -2,43 +2,6 @@
 
 #ifdef SVQC
 
-/**
-    turret_checkpoint
-**/
-
-
-//.entity checkpoint_target;
-
-/*
-#define checkpoint_cache_who  flagcarried
-#define checkpoint_cache_from lastrocket
-#define checkpoint_cache_to   selected_player
-*/
-
-/*
-entity path_makeorcache(entity forwho,entity start, entity end)
-{
-    entity pth;
-
-    //pth = pathlib_makepath(forwho, start.origin,end.origin,PFL_GROUNDSNAP,500,1.5,PT_QUICKSTAR);
-
-    return pth;
-}
-*/
-
-void turret_checkpoint_use()
-{
-}
-
-#if 0
-void turret_checkpoint_think(entity this)
-{
-    if(this.enemy)
-        te_lightning1(this,this.origin, this.enemy.origin);
-
-    this.nextthink = time + 0.25;
-}
-#endif
 /*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
 -----------KEYS------------
 target: .targetname of next waypoint in chain.
@@ -46,30 +9,25 @@ wait:   Pause at this point # seconds.
 -----------SPAWNFLAGS-----------
 ---------NOTES----------
 If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
-If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+If the checkpoint chain is not looped, the unit will go "Roaming" when the last point is reached.
 */
-//float tc_acum;
 void turret_checkpoint_init(entity this)
 {
     traceline(this.origin + '0 0 16', this.origin - '0 0 1024', MOVE_WORLDONLY, this);
     setorigin(this, trace_endpos + '0 0 32');
 
-    if(this.target != "")
+    if(this.target && this.target != "")
     {
         this.enemy = find(NULL, targetname, this.target);
-        if(this.enemy == NULL)
-            LOG_TRACE("A turret_checkpoint faild to find its target!");
+        if(!this.enemy)
+            LOG_TRACE("A turret_checkpoint failed to find its target!");
     }
-    //setthink(this, turret_checkpoint_think);
-    //this.nextthink = time + tc_acum + 0.25;
-    //tc_acum += 0.25;
 }
 
 spawnfunc(turret_checkpoint)
 {
     setorigin(this, this.origin);
-    setthink(this, turret_checkpoint_init);
-    this.nextthink = time + 0.2;
+    InitializeEntity(this, turret_checkpoint_init, INITPRIO_FINDTARGET);
 }
 
 // Compat.
index f9374497c8114f35346cedc0e13a46a47817ce45..df20e1ad2f2d8371638de205f191a458be3db41e 100644 (file)
@@ -175,28 +175,37 @@ void turret_draw2d(entity this)
                t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
        }
 
-       o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
-       if(autocvar_g_waypointsprite_turrets_text)
+       bool draw_healthbar = ((this.helpme && time < this.helpme) || !autocvar_g_waypointsprite_turrets_onlyhurt || hud != HUD_NORMAL);
+       bool draw_text = autocvar_g_waypointsprite_turrets_text;
+
+       if(draw_healthbar || draw_text) // make sure it's actually being drawn
+       {
+               o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
+       }
+       if(draw_text)
        {
                o = drawsprite_TextOrIcon(true, o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
        }
-       drawhealthbar(
-                       o,
-                       0,
-                       GetResource(this, RES_HEALTH) / 255,
-                       '0 0 0',
-                       '0 0 0',
-                       0.5 * SPRITE_HEALTHBAR_WIDTH * t,
-                       0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
-                       SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
-                       SPRITE_HEALTHBAR_BORDER * t,
-                       0,
-                       rgb,
-                       a * SPRITE_HEALTHBAR_BORDERALPHA,
-                       rgb,
-                       a * SPRITE_HEALTHBAR_HEALTHALPHA,
-                       DRAWFLAG_NORMAL
-                       );
+       if(draw_healthbar)
+       {
+               drawhealthbar(
+                               o,
+                               0,
+                               GetResource(this, RES_HEALTH) / 255,
+                               '0 0 0',
+                               '0 0 0',
+                               0.5 * SPRITE_HEALTHBAR_WIDTH * t,
+                               0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
+                               SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
+                               SPRITE_HEALTHBAR_BORDER * t,
+                               0,
+                               rgb,
+                               a * SPRITE_HEALTHBAR_BORDERALPHA,
+                               rgb,
+                               a * SPRITE_HEALTHBAR_HEALTHALPHA,
+                               DRAWFLAG_NORMAL
+                               );
+       }
 }
 
 void turret_construct(entity this, bool isnew)
index 84aae19335fd0d970a32a2024090780e16c3d372..fff1b3991576f178bcffa4b6b33015cbb4b43649 100644 (file)
@@ -788,7 +788,6 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
        tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target.origin);
        tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
        tvt_thadf = vlen(tvt_thadv);
-       tvt_tadf = vlen(tvt_tadv);
 
        /*
        if(validate_flags & TFL_TARGETSELECT_FOV)
index 8273e54dd1ba31b289a6a39240f8148147f66362..f7b14b0a65e5641295c962018bd6bd89ee70210f 100644 (file)
@@ -102,5 +102,4 @@ float turret_count;
 vector tvt_thadv; // turret head angle diff vector, updated by a successful call to turret_validate_target
 vector tvt_tadv; // turret angle diff vector, updated by a successful call to turret_validate_target
 float tvt_thadf; // turret head angle diff float, updated by a successful call to turret_validate_target
-float tvt_tadf; // turret angle diff float, updated by a successful call to turret_validate_target
 float tvt_dist; // turret distance, updated by a successful call to turret_validate_target
index cbf7cb30fcf69f63b90b2120ea41424826635d03..dfce8d3a0bf1a56654c29318d2838d1b33253afc 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(EWheelAttack, PortoLaunch)
-/* flags     */ ATTRIB(EWheelAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(EWheelAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(EWheelAttack, impulse, int, 5);
 /* refname   */ ATTRIB(EWheelAttack, netname, string, "turret_ewheel");
 /* wepname   */ ATTRIB(EWheelAttack, m_name, string, _("eWheel"));
index 13965bf513a911239d173ac78b1537225145aef5..d27061473a5a29064aa9517df3cf70586a18d30b 100644 (file)
@@ -1,9 +1,7 @@
 #pragma once
 
-// TODO: WEP_TYPE_OTHER?
-
 CLASS(FlacAttack, PortoLaunch)
-/* flags     */ ATTRIB(FlacAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(FlacAttack, spawnflags, int, WEP_FLAG_SPECIALATTACK | WEP_FLAG_HIDDEN);
 /* impulse   */ ATTRIB(FlacAttack, impulse, int, 5);
 /* refname   */ ATTRIB(FlacAttack, netname, string, "turret_flac");
 /* wepname   */ ATTRIB(FlacAttack, m_name, string, _("FLAC"));
index 69c67b800b7e7d432968e40981019f1d6d392f2d..61896cc3d4863db532555d0c5f15be1e7aaa35d5 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(HellionAttack, PortoLaunch)
-/* flags     */ ATTRIB(HellionAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(HellionAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(HellionAttack, impulse, int, 9);
 /* refname   */ ATTRIB(HellionAttack, netname, string, "turret_hellion");
 /* wepname   */ ATTRIB(HellionAttack, m_name, string, _("Hellion"));
index 7d44cfff91e8fb317773645f13f5c2d390b65804..f8acc5d3cfaee5248806e0a1fe4cfa49c1624328 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(HunterKillerAttack, PortoLaunch)
-/* flags     */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(HunterKillerAttack, impulse, int, 9);
 /* refname   */ ATTRIB(HunterKillerAttack, netname, string, "turret_hk");
 /* wepname   */ ATTRIB(HunterKillerAttack, m_name, string, _("Hunter-Killer"));
index ab8169e6cb15000bb77bca0508b1ef576988c928..517eef83abe9a020431ee6f9efa45efc51cbfc83 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(MachineGunTurretAttack, PortoLaunch)
-/* flags     */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(MachineGunTurretAttack, impulse, int, 9);
 /* refname   */ ATTRIB(MachineGunTurretAttack, netname, string, "turret_machinegun");
 /* wepname   */ ATTRIB(MachineGunTurretAttack, m_name, string, _("Machinegun"));
index ccb74771a6ad8121b7aa4627cb66362167b24cd4..5eb3755a6e0500e40eebb4016182a6abc6a31ae5 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(MLRSTurretAttack, PortoLaunch)
-/* flags     */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(MLRSTurretAttack, impulse, int, 9);
 /* refname   */ ATTRIB(MLRSTurretAttack, netname, string, "turret_mlrs");
 /* wepname   */ ATTRIB(MLRSTurretAttack, m_name, string, _("MLRS"));
index 0a3627631139a250552448dbf48f54870ae9a332..6b5b4fae803ce103d0846f783201e27a6c430788 100644 (file)
@@ -42,7 +42,7 @@ METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
         beam.attack_finished_single[0] = actor.attack_finished_single[0];
         actor.attack_finished_single[0] = time; // + autocvar_sys_ticrate;
 
-        setattachment(beam,actor.tur_head, "tag_fire");
+        setattachment(beam, actor.tur_head, "tag_fire");
 
         soundat (actor, trace_endpos, CH_SHOTS, SND(NEXIMPACT), VOL_BASE, ATTEN_NORM);
         if (!isPlayer)
@@ -53,17 +53,18 @@ METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
 
 void beam_think(entity this)
 {
-    if ((time > this.cnt) || (IS_DEAD(this.owner)))
+    entity actor = this.owner;
+    if ((time > this.cnt) || (IS_DEAD(actor)))
     {
-        this.owner.attack_finished_single[0] = time + this.owner.shot_refire;
-        this.owner.fireflag = 2;
-        this.owner.tur_head.frame = 10;
+        actor.attack_finished_single[0] = time + actor.shot_refire;
+        actor.fireflag = 2;
+        actor.tur_head.frame = 10;
         sound (this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
         delete(this);
         return;
     }
 
-    turret_do_updates(this.owner);
+    turret_do_updates(actor);
 
     if (time - this.shot_spread > 0)
     {
@@ -71,20 +72,18 @@ void beam_think(entity this)
         sound (this, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
     }
 
-
     this.nextthink = time + this.ticrate;
 
-    this.owner.attack_finished_single[0] = time + frametime;
-    FireImoBeam (   this.owner, this.tur_shotorg,
-                    this.tur_shotorg + this.tur_shotdir_updated * this.target_range,
-                    '-1 -1 -1' * this.shot_radius,
-                    '1 1 1' * this.shot_radius,
-                    this.shot_force,
+    actor.attack_finished_single[0] = time + frametime;
+    FireImoBeam (   actor, actor.tur_shotorg,
+                    actor.tur_shotorg + actor.tur_shotdir_updated * actor.target_range,
+                    '-1 -1 -1' * actor.shot_radius,
+                    '1 1 1' * actor.shot_radius,
+                    actor.shot_force,
                     this.shot_dmg,
                     0.75,
                     DEATH_TURRET_PHASER.m_id);
-    this.scale = vlen(this.owner.tur_shotorg - trace_endpos) / 256;
-
+    this.scale = vlen(actor.tur_shotorg - trace_endpos) / 256;
 }
 
 #endif
index ea45977d52e5a7921b3766ec7fc297635e2ae364..7b9dc457fe98396af5ca4248f622494ff6835665 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(PhaserTurretAttack, PortoLaunch)
-/* flags     */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(PhaserTurretAttack, impulse, int, 9);
 /* refname   */ ATTRIB(PhaserTurretAttack, netname, string, "turret_phaser");
 /* wepname   */ ATTRIB(PhaserTurretAttack, m_name, string, _("Phaser"));
index c0f63c1039673a3c65876fd4e883f7f618502dd6..299475cd08128b3be294bd39f32aa49a1330f793 100644 (file)
@@ -3,7 +3,7 @@
 #include "plasma_weapon.qh"
 
 CLASS(PlasmaDualAttack, PlasmaAttack)
-/* flags     */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* refname   */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
 /* wepname   */ ATTRIB(PlasmaDualAttack, m_name, string, _("Dual plasma"));
 ENDCLASS(PlasmaDualAttack)
index 3c11fdc0030bda7649d73e8ddd903d07940d420a..5ad91c363d81c0f67915d0e51af32d12d53dec70 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(PlasmaAttack, PortoLaunch)
-/* flags     */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(PlasmaAttack, impulse, int, 5);
 /* refname   */ ATTRIB(PlasmaAttack, netname, string, "turret_plasma");
 /* wepname   */ ATTRIB(PlasmaAttack, m_name, string, _("Plasma"));
index a7398526604e3ed5c6a77d129050481b6ff09b24..071f1d140905cd3a69ba541868d9302f45d73811 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(TeslaCoilTurretAttack, PortoLaunch)
-/* flags     */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(TeslaCoilTurretAttack, impulse, int, 9);
 /* refname   */ ATTRIB(TeslaCoilTurretAttack, netname, string, "turret_tesla");
 /* wepname   */ ATTRIB(TeslaCoilTurretAttack, m_name, string, _("Tesla Coil"));
index 7c4fc0bed03560a379a8969b7fca284e5a99d032..9f23ffb65a11f7520d4e6f143af2f23b6235e983 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 CLASS(WalkerTurretAttack, PortoLaunch)
-/* flags     */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(WalkerTurretAttack, impulse, int, 5);
 /* refname   */ ATTRIB(WalkerTurretAttack, netname, string, "turret_walker");
 /* wepname   */ ATTRIB(WalkerTurretAttack, m_name, string, _("Walker"));
index 817487c6d631d9c023c26d3581abb39244c3f486..6857ccad8dd8bc603637ff112e6e0e0cfc95d443 100644 (file)
@@ -28,72 +28,88 @@ void FireImoBeam(entity this, vector start, vector end, vector smin, vector smax
                                  float bforce, float f_dmg, float f_velfactor, int deathtype)
 
 {
-       vector hitloc, force, endpoint, dir;
-       entity ent;
-
-       dir = normalize(end - start);
-       force = dir * bforce;
+       vector dir = normalize(end - start);
+       vector force = dir * bforce;
 
        // go a little bit into the wall because we need to hit this wall later
        end = end + dir;
 
        // trace multiple times until we hit a wall, each obstacle will be made unsolid.
        // note down which entities were hit so we can damage them later
+       entity o = this;
        while (1)
        {
-               tracebox(start, smin, smax, end, false, this);
+               if(CS(this).antilag_debug)
+                       WarpZone_tracebox_antilag (this, start, smin, smax, end, false, o, CS(this).antilag_debug);
+               else
+                       WarpZone_tracebox_antilag (this, start, smin, smax, end, false, o, ANTILAG_LATENCY(this));
+               if(o && WarpZone_trace_firstzone)
+               {
+                       o = NULL;
+                       continue;
+               }
 
                // if it is NULL we can't hurt it so stop now
                if (trace_ent == NULL || trace_fraction == 1)
                        break;
 
-               if (trace_ent.solid == SOLID_BSP)
-                       break;
-
                // make the entity non-solid so we can hit the next one
+               IL_PUSH(g_railgunhit, trace_ent);
                trace_ent.railgunhit = true;
                trace_ent.railgunhitloc = end;
                trace_ent.railgunhitsolidbackup = trace_ent.solid;
+               trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start);
+               trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force);
 
                // stop if this is a wall
+               if (trace_ent.solid == SOLID_BSP)
+                       break;
 
                // make the entity non-solid
                trace_ent.solid = SOLID_NOT;
        }
 
-       endpoint = trace_endpos;
+       vector endpoint = trace_endpos;
+       entity endent = trace_ent;
+       float endq3surfaceflags = trace_dphitq3surfaceflags;
 
        // find all the entities the railgun hit and restore their solid state
-       ent = findfloat(NULL, railgunhit, true);
-       while (ent)
+       IL_EACH(g_railgunhit, it.railgunhit,
        {
-               // restore their solid type
-               ent.solid = ent.railgunhitsolidbackup;
-               ent = findfloat(ent, railgunhit, true);
-       }
+               it.solid = it.railgunhitsolidbackup;
+       });
+
+       /*
+               Unlike the railgun, this does NOT check for targets close by
+       */
 
        // find all the entities the railgun hit and hurt them
-       ent = findfloat(NULL, railgunhit, true);
-       while (ent)
+       IL_EACH(g_railgunhit, it.railgunhit,
        {
-               // get the details we need to call the damage function
-               hitloc = ent.railgunhitloc;
-               ent.railgunhitloc = '0 0 0';
-               ent.railgunhitsolidbackup = SOLID_NOT;
-               ent.railgunhit = false;
+               // removal from the list is handled below
+               /* no falloff applied */
 
                // apply the damage
-               if (ent.takedamage)
+               if (it.takedamage)
                {
-                       Damage (ent, this, this, f_dmg, deathtype, DMG_NOWEP, hitloc, force);
-                       ent.velocity = ent.velocity * f_velfactor;
-                       //ent.alpha = 0.25 + random() * 0.75;
+                       Damage(it, this, this, f_dmg, deathtype, DMG_NOWEP, it.railgunhitloc, it.railgunforce);
+                       // slow down the target
+                       it.velocity = it.velocity * f_velfactor;
                }
 
-               // advance to the next entity
-               ent = findfloat(ent, railgunhit, true);
-       }
+               it.railgunhitloc = '0 0 0';
+               it.railgunhitsolidbackup = SOLID_NOT;
+               it.railgunhit = false;
+               it.railgundistance = 0;
+       });
+
+       IL_CLEAR(g_railgunhit);
+
+       /* no accuracy, as a weapon entity is not attached */
+
        trace_endpos = endpoint;
+       trace_ent = endent;
+       trace_dphitq3surfaceflags = endq3surfaceflags;
 }
 
 #ifdef TURRET_DEBUG
index 0366f4604857df60615ec2cde4a7396cf155e77a..7713679f3ce57a2cbaa1deb6cd9f663a3245e6d0 100644 (file)
@@ -522,7 +522,7 @@ string fixPriorityList(string order, float from, float to, float subtract, float
                for(w = to; w >= from; --w)
                {
                        int wflags = Weapons_from(w).spawnflags;
-                       if((wflags & WEP_FLAG_HIDDEN) && (wflags & WEP_FLAG_MUTATORBLOCKED) && !(wflags & WEP_FLAG_NORMAL))
+                       if(wflags & WEP_FLAG_SPECIALATTACK)
                                continue;
                        for(i = 0; i < n; ++i)
                                if(stof(argv(i)) == w)
index 2033aa94b7eeeaa7a226ac516757cfbac84cd0cd..756e02cf51ffeb8aa85970233bfe7007d60818b9 100644 (file)
@@ -201,7 +201,7 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
        #else
                #define GENTLE autocvar_sv_gentle
        #endif
-       #define normal_or_gentle(normal, gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal)
+       #define normal_or_gentle(normal, gentle) ((GENTLE && (gentle != "")) ? gentle : normal)
 #endif
 
 #ifdef GAMEQC
index c8e47dabc20ea7efdb3b55b6c71ac86fbe49453d..6785a9f21536b0dc1f312cdb65bdae9bdc405f97 100644 (file)
@@ -777,17 +777,12 @@ void vehicles_impact(entity this, float _minspeed, float _speedfac, float _maxpa
 
        if(this.play_time < time)
        {
-               float wc = vlen(this.velocity - this.oldvelocity);
-               //dprint("oldvel: ", vtos(this.oldvelocity), "\n");
-               //dprint("vel: ", vtos(this.velocity), "\n");
-               if(_minspeed < wc)
+               if(vdist(this.velocity - this.oldvelocity, >, _minspeed))
                {
+                       float wc = vlen(this.velocity - this.oldvelocity);
                        float take = min(_speedfac * wc, _maxpain);
-                       Damage (this, NULL, NULL, take, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                       Damage(this, NULL, NULL, take, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
                        this.play_time = time + 0.25;
-
-                       //dprint("wc: ", ftos(wc), "\n");
-                       //dprint("take: ", ftos(take), "\n");
                }
        }
 }
@@ -924,12 +919,12 @@ void vehicles_touch(entity this, entity toucher)
        // Vehicle currently in use
        if(this.owner)
        {
-               if(!weaponLocked(this.owner))
                if(toucher != NULL)
                if((this.origin_z + this.maxs_z) > (toucher.origin_z))
                if(vehicles_crushable(toucher))
+               if(!weaponLocked(this.owner))
                {
-                       if(vdist(this.velocity, >=, 30))
+                       if(vdist(this.velocity, >=, autocvar_g_vehicles_crush_minspeed))
                                Damage(toucher, this, this.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH.m_id, DMG_NOWEP, '0 0 0', normalize(toucher.origin - this.origin) * autocvar_g_vehicles_crush_force);
 
                        return; // Dont do selfdamage when hitting "soft targets".
index 9870814d30e4e3287c39adf4f8fd3938b9b2bd6f..0d707b52fc15af238e7f156772b12a0d58f929fb 100644 (file)
@@ -12,6 +12,7 @@ AUTOCVAR(g_vehicles_steal, bool, true, "allow stealing enemy vehicles in teampla
 AUTOCVAR(g_vehicles_steal_show_waypoint, bool, true, "show a waypoint above the thief");
 float autocvar_g_vehicles_crush_dmg = 70;
 float autocvar_g_vehicles_crush_force = 50;
+float autocvar_g_vehicles_crush_minspeed = 100;
 bool autocvar_g_vehicles_delayspawn = true;
 float autocvar_g_vehicles_delayspawn_jitter = 10;
 float autocvar_g_vehicles_allow_bots;
index 7e4505ca3e0e7e6342cb08bbe76297e62b61d103..ede81f6c566fbb8689ed7399568cd1168a4d1ca3 100644 (file)
@@ -3,7 +3,7 @@
 #include <common/weapons/_all.qh>
 
 CLASS(RacerAttack, PortoLaunch)
-/* flags     */ ATTRIB(RacerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(RacerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(RacerAttack, impulse, int, 3);
 /* refname   */ ATTRIB(RacerAttack, netname, string, "racercannon");
 /* wepname   */ ATTRIB(RacerAttack, m_name, string, _("Racer cannon"));
index c7ffff79700ddb02e03dffc5dcacd20406a20024..37b87bbada36ff97a675eed836914a9b650a7c58 100644 (file)
@@ -3,7 +3,7 @@
 #include <common/weapons/_all.qh>
 
 CLASS(RaptorCannon, PortoLaunch)
-/* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(RaptorCannon, impulse, int, 3);
 /* refname   */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
 /* wepname   */ ATTRIB(RaptorCannon, m_name, string, _("Raptor cannon"));
@@ -11,7 +11,7 @@ ENDCLASS(RaptorCannon)
 REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
 
 CLASS(RaptorBomb, PortoLaunch)
-/* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(RaptorBomb, impulse, int, 3);
 /* refname   */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
 /* wepname   */ ATTRIB(RaptorBomb, m_name, string, _("Raptor bomb"));
@@ -19,7 +19,7 @@ ENDCLASS(RaptorBomb)
 REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
 
 CLASS(RaptorFlare, PortoLaunch)
-/* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
 /* impulse   */ ATTRIB(RaptorFlare, impulse, int, 3);
 /* refname   */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
 /* wepname   */ ATTRIB(RaptorFlare, m_name, string, _("Raptor flare"));
index a65a788ecf4020cd83d764fdce4b8b0f42be80eb..0be413f0fb0071fad8974f2022e50cea7a1bf838 100644 (file)
@@ -319,7 +319,7 @@ STATIC_INIT(register_weapons_done)
     FOREACH(Weapons, true, {
         WepSet set = it.m_wepset = _WepSet_FromWeapon(it.m_id = i);
         WEPSET_ALL |= set;
-        if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
+        if (it.spawnflags & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
         if (it == WEP_Null) continue;
         int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
         if (imp <= WEP_IMPULSE_END)
@@ -384,6 +384,13 @@ ENUMCLASS_END(WFRAME)
 vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
 void CL_WeaponEntity_SetModel(entity this, string name, bool _anim);
 
+#ifdef CSQC
+bool cvar_cl_accuracy_data_share;
+REPLICATE(cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share");
+bool cvar_cl_accuracy_data_receive;
+REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive");
+#endif
+
 #ifdef SVQC
 void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
 #endif
index f1cc349ca581668a4a2cf9bfac7a81f87a502f05..ab0fa0c17ffa8dc0f75702afa25c070a18b20b7e 100644 (file)
@@ -34,7 +34,7 @@ void Dump_Weapon_Settings()
        int wepcount = 1;
        #define WEP_CONFIG_WRITETOFILE(str) write_String_To_File(wep_config_file, str, wep_config_alsoprint)
        FOREACH(Weapons, it != WEP_Null, {
-               if((it.spawnflags & WEP_FLAG_HIDDEN) && (it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_NORMAL))
+               if(it.spawnflags & WEP_FLAG_SPECIALATTACK)
                        continue; // never include the attacks
                // step 1: clear the queue
                WEP_CONFIG_COUNT = 0;
index a2623ca201b6c6444c534d937961b61e68b427f4..3dd2a8048af45223f5ddaf383d1a649f262861ec 100644 (file)
@@ -198,6 +198,8 @@ const int WEP_FLAG_DUALWIELD      =  BIT(11); // weapon can be dual wielded
 const int WEP_FLAG_NODUAL         =  BIT(12); // weapon doesn't work well with dual wielding (fireball etc just explode on fire), doesn't currently prevent anything
 const int WEP_FLAG_PENETRATEWALLS =  BIT(13); // weapon has high calibur bullets that can penetrate thick walls (WEAPONTODO)
 const int WEP_FLAG_BLEED          =  BIT(14); // weapon pierces and causes bleeding (used for damage effects)
+const int WEP_FLAG_NOTRUEAIM      =  BIT(15); // weapon doesn't aim directly at targets
+const int WEP_FLAG_SPECIALATTACK  =  BIT(16); // marked as a special attack (not a true weapon), hidden from most weapon lists
 
 // variables:
 string weaponorder_byid;
index 6efb21495bbaed25831066aba3eddc9c91c24c18..5948d6a12e2831e0fcaf2f340cd7ae781ee72ce7 100644 (file)
@@ -232,7 +232,7 @@ void W_Arc_Beam_Think(entity this)
                }
 
                if(this == own.(weaponentity).arc_beam) { own.(weaponentity).arc_beam = NULL; }
-               if(!thiswep.wr_checkammo1(thiswep, own, weaponentity) && !(own.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!thiswep.wr_checkammo1(thiswep, own, weaponentity) && !(own.items & IT_UNLIMITED_AMMO))
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(own, weaponentity);
@@ -244,7 +244,7 @@ void W_Arc_Beam_Think(entity this)
 
        // decrease ammo
        float coefficient = frametime;
-       if(!(own.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(own.items & IT_UNLIMITED_AMMO))
        {
                float rootammo;
                if(burst)
index e3d713d470b5808f2f12a35b02cdaf6c53bb5755..310ea19a1b53e9e0caee892f20736d27281f43d3 100644 (file)
@@ -8,15 +8,19 @@ void W_Blaster_Touch(entity this, entity toucher)
 
        this.event_damage = func_null;
 
-       RadiusDamage(
+       RadiusDamageForSource(
                this,
+               (this.origin + (this.mins + this.maxs) * 0.5),
+               this.velocity,
                this.realowner,
                this.blaster_damage,
                this.blaster_edgedamage,
                this.blaster_radius,
                NULL,
                NULL,
+               false,
                this.blaster_force,
+               this.blaster_force_zscale,
                this.projectiledeathtype,
                this.weaponentity_fld,
                toucher
@@ -42,6 +46,7 @@ void W_Blaster_Attack(
        float atk_edgedamage,
        float atk_radius,
        float atk_force,
+       float atk_force_zscale,
        float atk_speed,
        float atk_spread,
        float atk_delay,
@@ -62,6 +67,7 @@ void W_Blaster_Attack(
        missile.blaster_edgedamage = atk_edgedamage;
        missile.blaster_radius = atk_radius;
        missile.blaster_force = atk_force;
+       missile.blaster_force_zscale = atk_force_zscale;
        missile.blaster_lifetime = atk_lifetime;
 
        setorigin(missile, w_shotorg);
@@ -129,6 +135,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
                 WEP_CVAR_PRI(blaster, edgedamage),
                 WEP_CVAR_PRI(blaster, radius),
                 WEP_CVAR_PRI(blaster, force),
+                WEP_CVAR_PRI(blaster, force_zscale),
                 WEP_CVAR_PRI(blaster, speed),
                 WEP_CVAR_PRI(blaster, spread),
                 WEP_CVAR_PRI(blaster, delay),
@@ -161,6 +168,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
                         WEP_CVAR_SEC(blaster, edgedamage),
                         WEP_CVAR_SEC(blaster, radius),
                         WEP_CVAR_SEC(blaster, force),
+                        WEP_CVAR_SEC(blaster, force_zscale),
                         WEP_CVAR_SEC(blaster, speed),
                         WEP_CVAR_SEC(blaster, spread),
                         WEP_CVAR_SEC(blaster, delay),
index c9825adf0b06d5f3ed4d936d1216680318f278a9..87824310c9d92f3478bc40455de063253d87b92e 100644 (file)
@@ -50,13 +50,15 @@ SPAWNFUNC_WEAPON(weapon_laser, WEP_BLASTER)
 
 CLASS(OffhandBlaster, OffhandWeapon)
 ENDCLASS(OffhandBlaster)
-OffhandBlaster OFFHAND_BLASTER; STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); }
+OffhandBlaster OFFHAND_BLASTER;
+STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); }
 
 #ifdef SVQC
 .float blaster_damage;
 .float blaster_edgedamage;
 .float blaster_radius;
 .float blaster_force;
+.float blaster_force_zscale;
 .float blaster_lifetime;
 
 // Will be demacroed after WEP_CVAR macros are also demacroed.
@@ -71,6 +73,7 @@ OffhandBlaster OFFHAND_BLASTER; STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER =
                WEP_CVAR_SEC(weapon_name, edgedamage), \
                WEP_CVAR_SEC(weapon_name, radius), \
                WEP_CVAR_SEC(weapon_name, force), \
+               WEP_CVAR_SEC(weapon_name, force_zscale), \
                WEP_CVAR_SEC(weapon_name, speed), \
                WEP_CVAR_SEC(weapon_name, spread), \
                WEP_CVAR_SEC(weapon_name, delay), \
index 3589146352e18d6fe74b3616147cc6233b3d7958..a69f43fbd3f7afbdd01bca9d88707ee5255c5729 100644 (file)
@@ -43,9 +43,15 @@ void W_Crylink_Dequeue(entity e)
        W_Crylink_Dequeue_Raw(e.crylink_owner, e.queueprev, e, e.queuenext);
 }
 
+void W_Crylink_DeleteLink(entity this)
+{
+       if(this.classname != "spike_oktoremove")
+               W_Crylink_Dequeue(this);
+       delete_fn(this);
+}
+
 void W_Crylink_Reset(entity this)
 {
-       W_Crylink_Dequeue(this);
        delete(this);
 }
 
@@ -263,7 +269,6 @@ void W_Crylink_Touch(entity this, entity toucher)
        else if(finalhit)
        {
                // just unlink
-               W_Crylink_Dequeue(this);
                delete(this);
                return;
        }
@@ -278,7 +283,6 @@ void W_Crylink_Touch(entity this, entity toucher)
 
 void W_Crylink_Fadethink(entity this)
 {
-       W_Crylink_Dequeue(this);
        delete(this);
 }
 
@@ -308,6 +312,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        for(counter = 0; counter < shots; ++counter)
        {
                proj = new(spike);
+               proj.dtor = W_Crylink_DeleteLink;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
                proj.crylink_owner = actor;
@@ -420,6 +425,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        for(counter = 0; counter < shots; ++counter)
        {
                proj = new(spike);
+               proj.dtor = W_Crylink_DeleteLink;
                proj.weaponentity_fld = weaponentity;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
@@ -568,7 +574,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
             }
             actor.(weaponentity).crylink_waitrelease = 0;
             if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-            if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+            if(!(actor.items & IT_UNLIMITED_AMMO))
             {
                 // ran out of ammo!
                 actor.cnt = thiswep.m_id;
index 5654488ddb065d4e9aeb49b8f95cda1889de2132..fce84c3b8eb88cc3d0b36a37861a361e5810f103 100644 (file)
@@ -47,7 +47,7 @@ void W_Devastator_Explode(entity this, entity directhitentity)
        if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(GetResource(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
-               if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(this.realowner.items & IT_UNLIMITED_AMMO))
                {
                        this.realowner.cnt = thiswep.m_id;
                        ATTACK_FINISHED(this.realowner, weaponentity) = time;
@@ -71,8 +71,11 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
 
        bool handled_as_rocketjump = false;
        entity head = NULL;
+       bool allow_rocketjump = WEP_CVAR(devastator, remote_jump);
+       MUTATOR_CALLHOOK(AllowRocketJumping, allow_rocketjump);
+       allow_rocketjump = M_ARGV(0, bool);
 
-       if(WEP_CVAR(devastator, remote_jump_radius))
+       if(allow_rocketjump && WEP_CVAR(devastator, remote_jump_radius))
        {
                head = WarpZone_FindRadius(
                        this.origin,
@@ -140,7 +143,7 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
        if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(GetResource(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
-               if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(this.realowner.items & IT_UNLIMITED_AMMO))
                {
                        this.realowner.cnt = thiswep.m_id;
                        ATTACK_FINISHED(this.realowner, weaponentity) = time;
@@ -314,7 +317,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity, int
        if(WEP_CVAR(devastator, detonatedelay) >= 0)
                missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay);
        else
-               missile.spawnshieldtime = -1;
+               missile.spawnshieldtime = -1; // NOTE: proximity based when rocket jumping
        missile.pushltime = time + WEP_CVAR(devastator, guidedelay);
        missile.classname = "rocket";
        missile.bot_dodge = true;
index 33814a5e1e0c3c3cda5b384e3fb272e08ee4d3e7..679f75499a3dfd1f4abaf82c64dfb19f4ea276ed 100644 (file)
@@ -40,6 +40,7 @@ CLASS(Devastator, Weapon)
         P(class, prefix, remote_damage, float, NONE) \
         P(class, prefix, remote_edgedamage, float, NONE) \
         P(class, prefix, remote_force, float, NONE) \
+        P(class, prefix, remote_jump, float, NONE) \
         P(class, prefix, remote_jump_damage, float, NONE) \
         P(class, prefix, remote_jump_force, float, NONE) \
         P(class, prefix, remote_jump_radius, float, NONE) \
index 51699bf0cdc560a981cf7cb5d9abdcec4998585c..0ffa0c74d973b92f00f9c5fb4b06b22a522f0704 100644 (file)
@@ -264,7 +264,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
 
        // this is different than WR_CHECKAMMO when it comes to reloading
        bool enough_ammo;
-       if(actor.items & IT_UNLIMITED_WEAPON_AMMO)
+       if(actor.items & IT_UNLIMITED_AMMO)
                enough_ammo = true;
        else if(autocvar_g_balance_hagar_reload_ammo)
                enough_ammo = actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
@@ -352,7 +352,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
 
                // we aren't checking ammo during an attack, so we must do it here
                if(!(thiswep.wr_checkammo1(thiswep, actor, weaponentity) + thiswep.wr_checkammo2(thiswep, actor, weaponentity)))
-               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(actor.items & IT_UNLIMITED_AMMO))
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(actor, weaponentity);
@@ -370,7 +370,7 @@ void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int
        }
 
        if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
-       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
index 8498597634bbcf7c689e1b5adcf2d480b75c0ff1..6511d22b572b4fab5938c035aea73d2e18dec6a2 100644 (file)
@@ -127,7 +127,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
        if(PHYS_INPUT_BUTTON_ATCK(actor))
        {
                if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
-               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(actor.items & IT_UNLIMITED_AMMO))
                {
                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
index d8cebd740ac49fc3daf8ec2c5d5111e30f27a740..d9e11dc012fb9d2736a0f04a56853d4ab9c9e14d 100644 (file)
@@ -145,7 +145,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         actor.(weaponentity).hook_refire = max(actor.(weaponentity).hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor(actor));
 
         // hook also inhibits health regeneration, but only for 1 second
-        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+        if(!(actor.items & IT_UNLIMITED_AMMO))
             actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
     }
 
@@ -163,7 +163,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         {
             if( time > actor.(weaponentity).hook_time_fueldecrease )
             {
-                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+                if(!(actor.items & IT_UNLIMITED_AMMO))
                 {
                     if( GetResource(actor, RES_FUEL) >= (time - actor.(weaponentity).hook_time_fueldecrease) * hooked_fuel )
                     {
index 1d15d448ec5b7442e6a6a30ead436665fad4af9e..bff975e005479ce5d12eaf5751ec11b6b06843f2 100644 (file)
@@ -4,7 +4,7 @@ CLASS(Hook, Weapon)
 /* spawnfunc */ ATTRIB(Hook, m_canonical_spawnfunc, string, "weapon_hook");
 /* ammotype  */ ATTRIB(Hook, ammo_type, int, RES_FUEL);
 /* impulse   */ ATTRIB(Hook, impulse, int, 0);
-/* flags     */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* flags     */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH | WEP_FLAG_NOTRUEAIM);
 /* rating    */ ATTRIB(Hook, bot_pickupbasevalue, float, 0);
 /* color     */ ATTRIB(Hook, wpcolor, vector, '0 0.5 0');
 /* modelname */ ATTRIB(Hook, mdl, string, "hookgun");
@@ -62,7 +62,8 @@ CLASS(OffhandHook, OffhandWeapon)
     }
 #endif
 ENDCLASS(OffhandHook)
-OffhandHook OFFHAND_HOOK; STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
+OffhandHook OFFHAND_HOOK;
+STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
 
 #ifdef SVQC
 
index 6679f2135fe2079904ec6f920a911eb2758556b1..86de79f600603d02f84bab06858b5dc533b42508 100644 (file)
@@ -2,15 +2,6 @@
 
 #ifdef SVQC
 
-METHOD(MachineGun, m_spawnfunc_hookreplace, Weapon(MachineGun this, entity e))
-{
-       if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
-       {
-               return WEP_SHOCKWAVE;
-       }
-       return this;
-}
-
 void W_MachineGun_MuzzleFlash_Think(entity this)
 {
        this.frame += 2;
@@ -93,7 +84,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit
        if(PHYS_INPUT_BUTTON_ATCK(actor))
        {
                if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(actor.items & IT_UNLIMITED_AMMO))
                {
                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
@@ -119,7 +110,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
-       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
@@ -164,7 +155,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                actor.punchangle_y = random() - 0.5;
        }
 
-       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), thiswep.m_id, EFFECT_BULLET);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), thiswep.m_id, EFFECT_BULLET);
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -199,10 +190,14 @@ METHOD(MachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponenti
 }
 METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(machinegun, reload_ammo) && actor.(weaponentity).clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
+    // forced reload - wait until the bulletcounter is 0 so a burst loop can finish
+    if(WEP_CVAR(machinegun, reload_ammo)
+        && actor.(weaponentity).clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))
+        && actor.(weaponentity).misc_bulletcounter >= 0)
+    {
         thiswep.wr_reload(thiswep, actor, weaponentity);
-    } else
-    if(WEP_CVAR(machinegun, mode) == 1)
+    }
+    else if(WEP_CVAR(machinegun, mode) == 1)
     {
         if(fire & 1)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
@@ -211,20 +206,39 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
             W_MachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
         }
 
+        // You can "shoot" more rounds than what's "used", and vice versa.
         if(fire & 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
         {
             if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-            if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+            if(!(actor.items & IT_UNLIMITED_AMMO))
             {
                 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                 w_ready(thiswep, actor, weaponentity, fire);
                 return;
             }
 
-            W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo), weaponentity);
+            float ammo_available;
+            if (WEP_CVAR(machinegun, reload_ammo) > 0)
+            {
+                ammo_available = actor.(weaponentity).clip_load;
+            }
+            else
+            {
+                ammo_available = GetResource(actor, thiswep.ammo_type);
+            }
 
-            actor.(weaponentity).misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
+            // We don't want to shoot 3 rounds if there's 2 left in the mag, so we'll use a fraction.
+            // Also keep the fraction <= 1 otherwise we'd mag dump in one burst.
+            float burst_fraction = min(1, ammo_available / WEP_CVAR(machinegun, burst_ammo));
+            int to_shoot = floor(WEP_CVAR(machinegun, burst) * burst_fraction);
+
+            // We also don't want to use 3 rounds if there's only 2 left.
+            int to_use = min(WEP_CVAR(machinegun, burst_ammo), ammo_available);
+            W_DecreaseAmmo(thiswep, actor, to_use, weaponentity);
+
+            // Bursting counts up to 0 from a negative.
+            actor.(weaponentity).misc_bulletcounter = -to_shoot;
             W_MachineGun_Attack_Burst(thiswep, actor, weaponentity, fire);
         }
     }
@@ -268,15 +282,16 @@ METHOD(MachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity wea
 METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
+    float burst_ammo_per_shot = WEP_CVAR(machinegun, burst_ammo) / WEP_CVAR(machinegun, burst);
     if(WEP_CVAR(machinegun, mode) == 1)
-        ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, burst_ammo);
+        ammo_amount = GetResource(actor, thiswep.ammo_type) >= burst_ammo_per_shot;
     else
         ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, first_ammo);
 
     if(WEP_CVAR(machinegun, reload_ammo))
     {
         if(WEP_CVAR(machinegun, mode) == 1)
-            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= burst_ammo_per_shot;
         else
             ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, first_ammo);
     }
@@ -284,6 +299,8 @@ METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity wea
 }
 METHOD(MachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
+       if(actor.(weaponentity).misc_bulletcounter < 0)
+               return;
     W_Reload(actor, weaponentity, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND_RELOAD);
 }
 METHOD(MachineGun, wr_suicidemessage, Notification(entity thiswep))
index a53d17a8d97ee5b0cc94e0ae078c28c86866733c..19bba63a2bb1241e62107e6b9fbb313ea91f1f70 100644 (file)
@@ -24,7 +24,7 @@ CLASS(MachineGun, Weapon)
                P(class, prefix, burst_animtime, float, NONE) \
                P(class, prefix, burst_refire2, float, NONE) \
                P(class, prefix, burst_refire, float, NONE) \
-               P(class, prefix, burst_speed, float, NONE) \
+               P(class, prefix, burst_spread, float, NONE) \
                P(class, prefix, first, float, NONE) \
                P(class, prefix, first_ammo, float, NONE) \
                P(class, prefix, first_damage, float, NONE) \
index d83fe59dc6fd5ad6df18357689b051c617da4622..4593442379a023b0dc0c80b86e66bd2cf2c9538c 100644 (file)
@@ -4,7 +4,7 @@ CLASS(Mortar, Weapon)
 /* spawnfunc */ ATTRIB(Mortar, m_canonical_spawnfunc, string, "weapon_mortar");
 /* ammotype  */ ATTRIB(Mortar, ammo_type, int, RES_ROCKETS);
 /* impulse   */ ATTRIB(Mortar, impulse, int, 4);
-/* flags     */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* flags     */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH | WEP_FLAG_NOTRUEAIM);
 /* rating    */ ATTRIB(Mortar, bot_pickupbasevalue, float, 7000);
 /* color     */ ATTRIB(Mortar, wpcolor, vector, '1 0 0');
 /* modelname */ ATTRIB(Mortar, mdl, string, "gl");
index 722171b9589555ffba0ce2a734153cf13245f7be..0e482d8ae82db239dbdd14160070da41befea332 100644 (file)
@@ -1,5 +1,84 @@
 #include "porto.qh"
 
+#ifdef CSQC
+STATIC_INIT(Porto)
+{
+       entity e = new_pure(porto);
+       e.draw = Porto_Draw;
+       IL_PUSH(g_drawables, e);
+       e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+}
+
+const int polyline_length = 16;
+.vector polyline[polyline_length];
+void Porto_Draw(entity this)
+{
+       if (spectatee_status || intermission == 1 || intermission == 2 || STAT(HEALTH) <= 0 || WEP_CVAR(porto, secondary)) return;
+
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wepent = viewmodels[slot];
+
+               if (wepent.activeweapon != WEP_PORTO) continue;
+
+               vector pos = view_origin;
+               vector dir = view_forward;
+               makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
+               pos += v_right * -wepent.movedir.y
+                       +  v_up * wepent.movedir.z;
+
+               if (wepent.angles_held_status)
+               {
+                       makevectors(wepent.angles_held);
+                       dir = v_forward;
+               }
+
+               wepent.polyline[0] = pos;
+
+               int portal_number = 0, portal1_idx = 1, portal_max = 2;
+               int n = 1 + 2;  // 2 lines == 3 points
+               for (int idx = 0; idx < n && idx < polyline_length - 1; )
+               {
+                       traceline(pos, pos + 65536 * dir, true, this);
+                       dir = reflect(dir, trace_plane_normal);
+                       pos = trace_endpos;
+                       wepent.polyline[++idx] = pos;
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+                       {
+                               n += 1;
+                               continue;
+                       }
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+                       {
+                               n = max(2, idx);
+                               break;
+                       }
+                       // check size
+                       {
+                               vector ang = vectoangles2(trace_plane_normal, dir);
+                               ang.x = -ang.x;
+                               makevectors(ang);
+                               if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                               {
+                                       n = max(2, idx);
+                                       break;
+                               }
+                       }
+                       portal_number += 1;
+                       if (portal_number >= portal_max) break;
+                       if (portal_number == 1) portal1_idx = idx;
+               }
+               for (int idx = 0; idx < n - 1; ++idx)
+               {
+                       vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
+                       if (idx == 0) p -= view_up * 16;  // line from player
+                       vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+                       Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
+               }
+       }
+}
+#endif
+
 #ifdef SVQC
 #include <common/mapobjects/trigger/jumppads.qh>
 #include <server/weapons/throwing.qh>
index 735426feb698366006f2dad88c9a330b724e146a..29820ef06baba6f4cc88eefbee9db167cd5a6246 100644 (file)
@@ -4,7 +4,7 @@ CLASS(PortoLaunch, Weapon)
 /* spawnfunc */ ATTRIB(PortoLaunch, m_canonical_spawnfunc, string, "weapon_porto");
 /* ammotype  */ ATTRIB(PortoLaunch, ammo_type, int, RES_NONE);
 /* impulse   */ ATTRIB(PortoLaunch, impulse, int, 0);
-/* flags     */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL);
+/* flags     */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL | WEP_FLAG_NOTRUEAIM);
 /* rating    */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0);
 /* color     */ ATTRIB(PortoLaunch, wpcolor, vector, '0.5 0.5 0.5');
 /* modelname */ ATTRIB(PortoLaunch, mdl, string, "porto");
@@ -38,6 +38,10 @@ REGISTER_WEAPON(PORTO, porto, NEW(PortoLaunch));
 
 SPAWNFUNC_WEAPON(weapon_porto, WEP_PORTO)
 
+#ifdef CSQC
+void Porto_Draw(entity this);
+#endif
+
 #ifdef SVQC
 .entity porto_current;
 .vector porto_v_angle; // holds "held" view angles
index f8c2be1d50777e1cea209366fe830aee87381009..d7ba289f5ca7ee9f1e92669a9fd5098b93791771 100644 (file)
@@ -342,8 +342,6 @@ void W_Seeker_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
 void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seeker_Attack
 {
-       float c;
-       entity oldenemy;
        this.cnt = this.cnt - 1;
 
        Weapon thiswep = WEP_SEEKER;
@@ -358,11 +356,10 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
        entity own = this.realowner;
 
-       oldenemy = own.enemy;
+       entity oldenemy = own.enemy;
        own.enemy = this.enemy;
 
-       c = own.cnt % 4;
-       switch(c)
+       switch(own.cnt % 4)
        {
                case 0:
                        W_Seeker_Fire_Missile(thiswep, own, weaponentity, '-1.25 -3.75 0', own.enemy); // TODO
index cdd0a0f92a315ecf1b3e774aa21b93ea17a5edfb..94f84ba5b1b8a88fa13b78e7c7afc7aed9f703a8 100644 (file)
@@ -3,6 +3,8 @@
 REGISTER_NET_TEMP(TE_CSQC_SHOCKWAVEPARTICLE)
 
 #ifdef SVQC
+// enable when shockwave replaces shotgun
+#if 0
 METHOD(Shockwave, m_spawnfunc_hookreplace, Weapon(Shockwave this, entity e))
 {
        //if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
@@ -12,6 +14,7 @@ METHOD(Shockwave, m_spawnfunc_hookreplace, Weapon(Shockwave this, entity e))
        }
        return this;
 }
+#endif
 
 const float MAX_SHOCKWAVE_HITS = 10;
 //#define DEBUG_SHOCKWAVE
index f42eea7d49c250a13f2270d226c3eb485f2a8b83..8b1cd48efd260701993a907826b50cfe0872e677 100644 (file)
@@ -4,7 +4,7 @@ CLASS(Shockwave, Weapon)
 /* spawnfunc */ ATTRIB(Shockwave, m_canonical_spawnfunc, string, "weapon_shockwave");
 /* ammotype  */ //ATTRIB(Shockwave, ammo_type, int, RES_NONE);
 /* impulse   */ ATTRIB(Shockwave, impulse, int, 2);
-/* flags     */ ATTRIB(Shockwave, spawnflags, int, WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
+/* flags     */ ATTRIB(Shockwave, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
 /* rating    */ ATTRIB(Shockwave, bot_pickupbasevalue, float, 3000);
 /* color     */ ATTRIB(Shockwave, wpcolor, vector, '0.5 0.25 0');
 /* modelname */ ATTRIB(Shockwave, mdl, string, "shotgun");
index a3bf16145ac438c8e5cc9d9150e0a9646f86379b..e2f4b640aa1b818f3a6b7640c9cf7be2d61c93b2 100644 (file)
@@ -2,13 +2,31 @@
 
 #ifdef SVQC
 
+METHOD(Shotgun, m_spawnfunc_hookreplace, Weapon(Shotgun this, entity e))
+{
+       if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
+       {
+               return WEP_MACHINEGUN;
+       }
+       return this;
+}
+
 void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary, float ammocount, float damage, float bullets, float spread, float solidpenetration, float force, entity bullet_trail_effect)
 {
        W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
 
        W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets, thiswep.m_id);
+
+       // TRICK: do the antilag outside the regular fireBullet function, so it isn't performed unnecessarily on every single bullet!
+       float lag = antilag_getlag(actor);
+       if(lag && bullets > 0)
+               antilag_takeback_all(actor, lag);
+
        for(int sc = 0;sc < bullets;sc = sc + 1)
-               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect);
+               fireBullet_antilag(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect, false);
+       
+       if(lag && bullets > 0)
+               antilag_restore_all(actor);
 
        Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, ammocount);
 
@@ -144,7 +162,7 @@ void W_Shotgun_Attack2(Weapon thiswep, entity actor, .entity weaponentity, int f
 void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
        if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if (!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
@@ -165,7 +183,7 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
        if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if (!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
@@ -245,7 +263,7 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     }
     if(actor.(weaponentity).clip_load >= 0) // we are not currently reloading
     if(WEP_CVAR(shotgun, secondary) == 1)
-    if(((fire & 1) && GetResource(actor, thiswep.ammo_type) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
+    if(((fire & 1) && GetResource(actor, thiswep.ammo_type) <= 0 && !(actor.items & IT_UNLIMITED_AMMO)) || (fire & 2))
     if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire)))
     {
         // attempt forcing playback of the anim by switching to another anim (that we never play) here...
index eb780808932fcd471d96d4727f6aa9cf6aae87a0..bf5fa0c98f271a2c012a49c7807c55c438fa4794 100644 (file)
@@ -268,7 +268,7 @@ void W_Tuba_NoteOn(entity actor, .entity weaponentity, float hittype)
        vector o;
        float n = W_Tuba_GetNote(actor, hittype);
 
-       hittype = 0;
+       hittype = HITTYPE_SOUND;
        if(actor.(weaponentity).tuba_instrument & 1)
                hittype |= HITTYPE_SECONDARY;
        if(actor.(weaponentity).tuba_instrument & 2)
index d932d98bd16f6d7554c32fb7f447ca9419be3c15..335326514d76fdfb85dbe49a43734737a11696dd 100644 (file)
@@ -3,7 +3,7 @@
 CLASS(Tuba, Weapon)
 /* spawnfunc */ ATTRIB(Tuba, m_canonical_spawnfunc, string, "weapon_tuba");
 /* impulse   */ ATTRIB(Tuba, impulse, int, 1);
-/* flags     */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL);
+/* flags     */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL | WEP_FLAG_NOTRUEAIM);
 /* rating    */ ATTRIB(Tuba, bot_pickupbasevalue, float, 2000);
 /* color     */ ATTRIB(Tuba, wpcolor, vector, '0 1 0');
 /* modelname */ ATTRIB(Tuba, mdl, string, "tuba");
@@ -51,3 +51,7 @@ classfield(Tuba) .float tuba_volume;
 classfield(Tuba) .float tuba_volume_initial;
 classfield(Tuba) .int tuba_instrument;
 #endif
+
+#ifdef SVQC
+bool W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo);
+#endif
index 207ae8e630dd4a2a36905f8808739ad929cd6907..f87a800a921aeeba42b06d248cbb16e303559472 100644 (file)
@@ -31,6 +31,7 @@ CLASS(Vaporizer, Weapon)
        P(class, prefix, delay, float, SEC) \
        P(class, prefix, edgedamage, float, SEC) \
        P(class, prefix, force, float, SEC) \
+        P(class, prefix, force_zscale, float, SEC) \
        P(class, prefix, lifetime, float, SEC) \
        P(class, prefix, radius, float, SEC) \
        P(class, prefix, refire, float, SEC) \
index fec4d756e97b5e3a5b1c672dc54a5521f8bd1d65..46fd4d8c0887639b8b8c32e8b116c0f60ff4538e 100644 (file)
@@ -159,6 +159,12 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i
 
 .float vortex_chargepool_pauseregen_finished;
 
+void W_Vortex_Charge(entity actor, .entity weaponentity, float dt)
+{
+    if(WEP_CVAR(vortex, charge) && actor.(weaponentity).vortex_charge < WEP_CVAR(vortex, charge_limit))
+        actor.(weaponentity).vortex_charge = min(1, actor.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_rate) * dt / W_TICSPERFRAME);
+}
+
 METHOD(Vortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(bot_aim(actor, weaponentity, 1000000, 0, 1, false))
@@ -171,8 +177,8 @@ METHOD(Vortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 }
 METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(vortex, charge) && actor.(weaponentity).vortex_charge < WEP_CVAR(vortex, charge_limit))
-        actor.(weaponentity).vortex_charge = min(1, actor.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+    if(!WEP_CVAR(vortex, charge_always))
+        W_Vortex_Charge(actor, weaponentity, frametime);
 
     if(WEP_CVAR_SEC(vortex, chargepool))
         if(actor.(weaponentity).vortex_chargepool_ammo < 1)
@@ -224,7 +230,7 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
                         if(fire & 2) // only eat ammo when the button is pressed
                         {
                             dt = min(dt, (1 - actor.(weaponentity).vortex_charge) / WEP_CVAR(vortex, charge_rate));
-                            if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+                            if(!(actor.items & IT_UNLIMITED_AMMO))
                             {
                                 // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
                                 if(autocvar_g_balance_vortex_reload_ammo)
index 570464cb913e7ddbc758509323b61fb0dc97baec..783e42a8ea567d146eb1e1dae62f91d9d666d7f3 100644 (file)
@@ -27,6 +27,7 @@ CLASS(Vortex, Weapon)
                P(class, prefix, chargepool_pause_regen, float, SEC) \
                P(class, prefix, chargepool_regen, float, SEC) \
                P(class, prefix, charge, float, NONE) \
+               P(class, prefix, charge_always, float, NONE) \
                P(class, prefix, charge_animlimit, float, NONE) \
                P(class, prefix, charge_limit, float, NONE) \
                P(class, prefix, charge_maxspeed, float, NONE) \
@@ -66,4 +67,6 @@ SPAWNFUNC_WEAPON(weapon_nex, WEP_VORTEX)
 
 #ifdef SVQC
 .float vortex_lasthit;
+
+void W_Vortex_Charge(entity actor, .entity weaponentity, float dt);
 #endif
index 6b1797c664e9b38fa36f7eee6d6526d2eea4cd5c..38ef3bd1f7d4c5303e5f639f5c6306711d1385ba 100644 (file)
@@ -36,10 +36,10 @@ MACRO_END
     \
     PROP(false, porto_v_angle_held, WEPENT_SET_NORMAL, \
        { WriteByte(chan, this.porto_v_angle_held); if(this.porto_v_angle_held) { \
-                WriteAngle(chan, this.porto_v_angle.x); WriteAngle(chan, this.porto_v_angle.y); \
+                WriteAngle(chan, this.owner.porto_v_angle.x); WriteAngle(chan, this.owner.porto_v_angle.y); \
                } }, \
        { (viewmodels[this.m_wepent_slot]).angles_held_status = ReadByte(); if((viewmodels[this.m_wepent_slot]).angles_held_status) { \
-               (viewmodels[this.m_wepent_slot]).angles_held_x = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_y = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_z = 0; } \
+               (viewmodels[this.m_wepent_slot]).angles_held = vec2(ReadAngle(), ReadAngle()); } \
                else { (viewmodels[this.m_wepent_slot]).angles_held = '0 0 0'; } }) \
     \
     PROP(false, tuba_instrument, WEPENT_SET_NORMAL, \
@@ -73,6 +73,10 @@ MACRO_END
     PROP(false, clip_size, WEPENT_SET_NORMAL, \
        { WriteShort(chan, this.clip_size); }, \
        { (viewmodels[this.m_wepent_slot]).clip_size = ReadShort(); }) \
+    \
+    PROP(false, skin, WEPENT_SET_NORMAL, \
+       { WriteShort(chan, this.skin); }, \
+       { (viewmodels[this.m_wepent_slot]).m_skin = ReadShort(); }) \
     \
        /**/
 
index 556f58194f5ed5298d52f0aad3f4e6ca3f046e2a..6d7128c33ca27323d91cd6ba8685fb6ca61ac0e4 100644 (file)
@@ -37,6 +37,8 @@ REGISTER_NET_TEMP(CLIENT_WEPENT)
 
        .float m_alpha;
 
+       .int m_skin;
+
        // only for Porto
        .bool angles_held_status;
        .vector angles_held;
index b38ba9d05a9313f670f8fa8bdeede09c565ebf2c..c084b5efe3a417b557202228d2b19ad98bf06a41 100644 (file)
@@ -61,6 +61,7 @@
        _("CI_THI^%d seconds"), /* third */ \
        _("CI_MUL^%d seconds")) /* multi */
 
+// returns 1st, 2nd, 3rd, nth ordinal number from a cardinal number (integer)
 ERASEABLE
 string count_ordinal(int interval)
 {
@@ -68,23 +69,20 @@ string count_ordinal(int interval)
        // to accomodate all languages unless we do a specific function for each one...
        // and since that's not technically feasible/practical, this is all we've got folks.
 
-       // Basically, it just allows you to represent a number or count in different ways
-       // depending on the number... like, with count_ordinal you can provide integers
-       // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
-       if (floor((interval % 100) / 10) * 10 != 10)  // examples: 12th, 111th, 213th will not execute this block
+       int last2digits = interval % 100;
+
+       // numbers ending with 11, 12 and 13 don't follow the standard pattern
+       if (last2digits < 4 || last2digits > 20)
        {
-               // otherwise, check normally for 1st,2nd,3rd insertions
-               switch (interval % 10)
+               switch (last2digits % 10)
                {
                        case 1: return sprintf(_("%dst"), interval);
                        case 2: return sprintf(_("%dnd"), interval);
                        case 3: return sprintf(_("%drd"), interval);
-                       default: return sprintf(_("%dth"), interval);
                }
        }
-       else { return sprintf(_("%dth"), interval); }
 
-       return "";
+       return sprintf(_("%dth"), interval);
 }
 
 ERASEABLE
index 12be0dbaa479c099cc2df23c376a21a1924b43c7..ccf6751171f82522181d75e529d103ac5b848847 100644 (file)
@@ -277,6 +277,9 @@ NET_HANDLE(ENT_CLIENT_MODEL, bool isnew)
                this.csqcmodel_teleported = 1;
        }
 
+       if(sf & BIT(3))
+               this.alpha = this.m_alpha;
+
        if(sf & BIT(14))
                viewloc_SetTags(this);
 
index b5d9f8bd361fff927dc54f70a5632300a64d4360..6211868445b7b65d87390eb7549051f228588e55 100644 (file)
@@ -27,7 +27,8 @@
 #define CSQCMODEL_ENDIF
 #define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
        .t f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+       .t f;
        ALLPROPERTIES
 #undef CSQCMODEL_PROPERTY_SCALED
 #undef CSQCMODEL_PROPERTY
index 584bfc23ff6f0901f524f823e0b6e66465944c1d..70e2c1a15e9bf10f6a4a09bf9378a10f724ba5c8 100644 (file)
@@ -48,7 +48,11 @@ bool CSQCModel_Send(entity this, entity to, int sf)
        { \
                w(MSG_ENTITY, this.csqcmodel_##f); \
        }
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+       if(sf & flag) \
+       { \
+               w(MSG_ENTITY, this.csqcmodel_##f); \
+       }
        ALLPROPERTIES
 #undef CSQCMODEL_PROPERTY_SCALED
 #undef CSQCMODEL_PROPERTY
index e963f12a1bf6ac79d9d3e45bf941e10e92927fef..f70ecea88818c8b46d0dc218faec9b0692749e67 100644 (file)
@@ -34,7 +34,9 @@ void CSQCModel_UnlinkEntity(entity e);
 #define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
        .t f; \
        .t csqcmodel_##f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+       .t f; \
+       .t csqcmodel_##f;
        ALLPROPERTIES
 #undef CSQCMODEL_PROPERTY_SCALED
 #undef CSQCMODEL_PROPERTY
index 4e8e09083f7749cb481655d64a0e01665f62b440..a48e83ac1a32593f7ccced9044b55de4308d7b79 100644 (file)
@@ -155,7 +155,7 @@ MACRO_END
 #define REGISTRY_HASH(id) Registry_hash_##id
 
 ERASEABLE
-ACCUMULATE void Registry_check(string r, string server) { }
+ACCUMULATE void Registry_check(string r, string sv) { }
 ERASEABLE
 ACCUMULATE void Registry_send_all() { }
 
@@ -170,9 +170,9 @@ void Registry_send(string id, string hash);
        STATIC_INIT(Registry_check_##id) \
        { \
                /* Note: SHA256 isn't always available, use MD4 instead */ \
-               string s = "", join = ":"; \
-               FOREACH(id, true, s = strcat(s, join, it.registered_id)); \
-               s = substring(s, strlen(join), -1); \
+               string s = ""; \
+               FOREACH(id, true, s = strcat(s, ":", it.registered_id)); \
+               s = substring(s, 1, -1); /* remove initial ":" */ \
                string h = REGISTRY_HASH(id) = strzone(digest_hex("MD4", s)); \
                LOG_DEBUGF(#id ": %s\n[%s]", h, s); \
        } \
index 656989782672e60c948199c0b8deb94f2f10b0a6..a88bde462934134f3585707eff76e81303e8d6c2 100644 (file)
        #define REPLICATE(...) EVAL_REPLICATE(OVERLOAD(REPLICATE, __VA_ARGS__))
        #define EVAL_REPLICATE(...) __VA_ARGS__
 
+       #if defined(SVQC)
        ACCUMULATE void ReplicateVars(entity this, entity store, string thisname, int i) {}
+       #elif defined(CSQC)
+       ACCUMULATE void ReplicateVars(bool would_destroy) {}
+       #endif
 
        #define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, )
        #define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func)
-       #define REPLICATE_string(fld, var, func) \
-               REPLICATE_7(fld, string, var, , \
-       { strcpy(field, it); }, \
-       { strfree(field); }, \
-       { \
-               /* also initialize to the default value of func when requesting cvars */ \
-               string s = func(field); \
-               if (s != field) \
+       #if defined(SVQC)
+               #define REPLICATE_string(fld, var, func) \
+                       REPLICATE_7(fld, string, var, , \
+               { strcpy(field, it); }, \
+               { strfree(field); }, \
                { \
-                   strcpy(field, s); \
-               } \
-       })
-       #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func,  { field = stof(it); },          , )
-       #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func,   { field = boolean(stoi(it)); }, , )
-       #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func,    { field = stoi(it); },          , )
+                       /* also initialize to the default value of func when requesting cvars */ \
+                       string s = func(field); \
+                       if (s != field) \
+                       { \
+                               strcpy(field, s); \
+                       } \
+               })
+               #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func,  { field = stof(it); },          , )
+               #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func,   { field = boolean(stoi(it)); }, , )
+               #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func,    { field = stoi(it); },          , )
 
-       #if defined(SVQC)
                #define REPLICATE_7(fld, type, var, func, create, destroy, after) \
                        void ReplicateVars(entity this, entity store, string thisname, int i) \
                        { \
                                        } \
                                        else \
                                        { \
-                                               stuffcmd(this, "cl_cmd sendcvar " var "\n"); \
+                                               stuffcmd(this, strcat("cl_cmd sendcvar ", var, "\n")); \
                                        } \
                                        if (current) { after } \
                                } \
                                store.fld = field; \
                        }
        #elif defined(CSQC)
-               // TODO
-               #define REPLICATE_7(fld, type, var, func, create, destroy, after)
+               float ReplicateVars_time;
+               #define ReplicateVars_NOT_SENDING() (time > ReplicateVars_time)
+               #define ReplicateVars_DELAY(t) ReplicateVars_time = time + t
+               #define ReplicateVars_DELAY_1FRAME() ReplicateVars_time = time
+               #define REPLICATE_string(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar_string(var)), { strcpy(fld, cvar_string(var)); }, { strfree(fld); })
+               #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
+               #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
+               #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
+
+               #define REPLICATE_7(fld, type, var, func, check, update, destroy) \
+                       void ReplicateVars(bool would_destroy) \
+                       { \
+                               if (would_destroy) { destroy } \
+                               else if (ReplicateVars_NOT_SENDING() && check) \
+                               { \
+                                       localcmd(strcat("cl_cmd sendcvar ", var, "\n")); \
+                                       ReplicateVars_DELAY_1FRAME(); \
+                                       update \
+                                       return; \
+                               } \
+                       }
+
+               #define REPLICATE_SIMPLE(field, cvarname) MACRO_BEGIN \
+                       if (ReplicateVars_NOT_SENDING() && field != cvar(cvarname)) \
+                       { \
+                               localcmd(strcat("cl_cmd sendcvar ", cvarname, "\n")); \
+                               ReplicateVars_DELAY_1FRAME(); \
+                               field = cvar(cvarname); \
+                               return; \
+                       } \
+               MACRO_END
        #endif
 
 #endif
index e2a25cbc76ef3ec1b8e2f674b1793f0d2eccc744..bcc1f2c693fdc7a14b07f54fbff14f62f36c8c34 100644 (file)
@@ -146,12 +146,14 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, health) \
                FIELD_SCALAR(fld, height) \
                FIELD_SCALAR(fld, impulse) \
+               FIELD_SCALAR(fld, item_pickupsound) \
                FIELD_SCALAR(fld, killtarget) \
                FIELD_SCALAR(fld, lerpfrac) \
                FIELD_SCALAR(fld, light_lev) \
                FIELD_SCALAR(fld, lip) \
                FIELD_SCALAR(fld, loddistance1) \
                FIELD_SCALAR(fld, lodmodel1) \
+               FIELD_SCALAR(fld, lodmodel2) \
                FIELD_SCALAR(fld, ltime) \
                FIELD_SCALAR(fld, map) \
                FIELD_SCALAR(fld, max_health) \
@@ -200,8 +202,12 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, target_range) \
                FIELD_SCALAR(fld, team) \
                FIELD_SCALAR(fld, trigger_reverse) \
+               FIELD_SCALAR(fld, turret_scale_aim) \
+               FIELD_SCALAR(fld, turret_scale_ammo) \
+               FIELD_SCALAR(fld, turret_scale_damage) \
                FIELD_SCALAR(fld, turret_scale_health) \
                FIELD_SCALAR(fld, turret_scale_range) \
+               FIELD_SCALAR(fld, turret_scale_refire) \
                FIELD_SCALAR(fld, turret_scale_respawn) \
                FIELD_SCALAR(fld, volume) \
                FIELD_SCALAR(fld, wait) \
index 7f8b0cdc837258a7bb5547d984afbcd960430baa..df1ab6b806bf91e3b6d84e337d51fcee99dad8f2 100644 (file)
@@ -29,7 +29,10 @@ void WarpZone_Touch(entity this, entity toucher);
 NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
 {
        if(!warpzone_warpzones_exist)
+       {
                cvar_settemp("r_water", "1"); // HACK for DarkPlaces: always enable reflections when a map has warpzones
+               cvar_settemp("r_water_resolutionmultiplier", "1"); // HACK for DarkPlaces: enforce full quality so entities can be seen clearly through warpzones
+       }
        warpzone_warpzones_exist = 1;
        if (!this.enemy)
        {
@@ -87,7 +90,10 @@ NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
 NET_HANDLE(ENT_CLIENT_WARPZONE_CAMERA, bool isnew)
 {
        if(!warpzone_cameras_exist)
+       {
                cvar_settemp("r_water", "1"); // HACK for DarkPlaces: always enable reflections when a map has cameras
+               cvar_settemp("r_water_resolutionmultiplier", "1"); // HACK for DarkPlaces: enforce full quality so entities can be seen clearly through warpzones
+       }
        warpzone_cameras_exist = 1;
        this.classname = "func_warpzone_camera";
 
index 82d3a50719356083ae96fbb18d691dfc2b9f83df..b70e938fe7e987ee9dded47a2e721b151bd9d10d 100644 (file)
@@ -792,7 +792,7 @@ bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher)
 
 void WarpZoneLib_MoveOutOfSolid_Expand(entity e, vector by)
 {
-       float eps = 0.0625;
+       const float eps = 0.0625;
        tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
        if (trace_startsolid)
                return;
index 3889b341b795c1893c81afb2b43c15136c1053db..54f6283b80bb9033a2883d106bd46aabc61781f5 100644 (file)
@@ -1,4 +1,4 @@
-#if 0
+/*
 "Perl code to convert this to a skinvalues.txt file.";
 print "title Generic\n";
 print "author Morphed\n";
@@ -32,7 +32,7 @@ while(<DATA>)
        }
 }
 __DATA__
-#endif
+*/
 SKINBEGIN
        // font sizes (used for everything)
        SKINFLOAT(FONTSIZE_NORMAL, 12);
index 00a9e5403fcd22236a8f2bd77fef45c095eb9b1b..3f324ba397318c3cfd23ddef2915a07c15e21dae 100644 (file)
@@ -59,6 +59,7 @@
 #include <menu/xonotic/dialog_sandboxtools.qc>
 #include <menu/xonotic/dialog_settings.qc>
 #include <menu/xonotic/dialog_settings_audio.qc>
+#include <menu/xonotic/dialog_settings_bindings_reset.qc>
 #include <menu/xonotic/dialog_settings_effects.qc>
 #include <menu/xonotic/dialog_settings_game.qc>
 #include <menu/xonotic/dialog_settings_game_crosshair.qc>
@@ -70,7 +71,6 @@
 #include <menu/xonotic/dialog_settings_game_weapons.qc>
 #include <menu/xonotic/dialog_settings_input.qc>
 #include <menu/xonotic/dialog_settings_input_userbind.qc>
-#include <menu/xonotic/dialog_settings_bindings_reset.qc>
 #include <menu/xonotic/dialog_settings_misc.qc>
 #include <menu/xonotic/dialog_settings_misc_cvars.qc>
 #include <menu/xonotic/dialog_settings_misc_reset.qc>
index 5d72a56171fdb2a1cd0be51d79416815878b6303..1b3e09081aab1c6075b26eb94b2e704e2ad6b31a 100644 (file)
@@ -59,6 +59,7 @@
 #include <menu/xonotic/dialog_sandboxtools.qh>
 #include <menu/xonotic/dialog_settings.qh>
 #include <menu/xonotic/dialog_settings_audio.qh>
+#include <menu/xonotic/dialog_settings_bindings_reset.qh>
 #include <menu/xonotic/dialog_settings_effects.qh>
 #include <menu/xonotic/dialog_settings_game.qh>
 #include <menu/xonotic/dialog_settings_game_crosshair.qh>
@@ -70,7 +71,6 @@
 #include <menu/xonotic/dialog_settings_game_weapons.qh>
 #include <menu/xonotic/dialog_settings_input.qh>
 #include <menu/xonotic/dialog_settings_input_userbind.qh>
-#include <menu/xonotic/dialog_settings_bindings_reset.qh>
 #include <menu/xonotic/dialog_settings_misc.qh>
 #include <menu/xonotic/dialog_settings_misc_cvars.qh>
 #include <menu/xonotic/dialog_settings_misc_reset.qh>
index 8b6dd4b731512cec3da19fe489dc512a04245108..33fe3575a8bde07be1326970f232e4087667cf6d 100644 (file)
@@ -251,7 +251,7 @@ void XonoticMutatorsDialog_fill(entity me)
        for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
        {
                w = Weapons_from(i);
-               if(w.spawnflags & WEP_FLAG_HIDDEN)
+               if (w.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK))
                        continue;
                if ((j % 3) == 0)
                {
index afde0914a48b981db347492f8db456e31ae4da64..08730511217002e2b2e4db884532e68b1d5bce53 100644 (file)
@@ -39,6 +39,7 @@ void XonoticScreenshotBrowserTab_fill(entity me)
 
        me.gotoRC(me, 0, 3.1);
                me.TD(me, 1, 1.9, e = makeXonoticCheckBoxEx(2, 1, "cl_autoscreenshot", _("Auto screenshot scoreboard")));
+                       e.sendCvars = true;
                me.TD(me, 1, 1, e = makeXonoticButton(_("Refresh"), '0 0 0'));
                        e.onClick = ScreenshotList_Refresh_Click;
                        e.onClickEntity = slist;
index 8705e5ff7f7df8e5d3d17b5a67ee43af18ce7f02..4405d98de7d3f34be00cd3ce8fce0ca8c1d655da 100644 (file)
@@ -40,8 +40,6 @@ void XonoticProfileTab_fill(entity me)
                "name \"$_cl_name\";"
                "playermodel $_cl_playermodel;"
                "playerskin $_cl_playerskin;"
-               "sendcvar cl_allow_uidtracking;"
-               "sendcvar cl_allow_uid2name;"
                , COMMANDBUTTON_APPLY);
        profileApplyButton.disableOnClick = true;
 
@@ -127,13 +125,18 @@ void XonoticProfileTab_fill(entity me)
        me.TR(me);
                me.TDempty(me, 0.25);
                me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_allow_uidtracking", _("Allow player statistics to track your client")));
-                       e.applyButton = profileApplyButton;
+                       e.sendCvars = true;
        me.TR(me);
                me.TDempty(me, 0.25);
                me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_allow_uid2name", _("Allow player statistics to use your nickname")));
-                       e.applyButton = profileApplyButton;
+                       e.sendCvars = true;
+                       setDependent(e, "cl_allow_uidtracking", 1, 1);
+       me.TR(me);
+               me.TDempty(me, 0.25);
+               me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_allow_uidranking", _("Allow player statistics to rank you in leaderboards")));
+                       e.sendCvars = true;
                        setDependent(e, "cl_allow_uidtracking", 1, 1);
-       me.gotoRC(me, 4, 3.1); // TOP RIGHT
+       me.gotoRC(me, 4.5, 3.1); // TOP RIGHT
        //me.gotoRC(me, 12.5, 3.1); // BOTTOM RIGHT
        //me.gotoRC(me, 12.5, 0); // BOTTOM LEFT
                me.TDempty(me, 0.25);
index c1caddd7d4def04098368961477a35ba6eaa1e90..0b3a9ff6c4402253b2a30fb8ab277ab41b6a3c3d 100644 (file)
@@ -65,6 +65,7 @@ void XonoticGameViewSettingsTab_fill(entity me)
        me.TR(me);
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_clippedspectating", _("Allow passing through walls while spectating")));
+                       e.sendCvars = true;
 
        me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Field of view:")));
index 1d75ecb49b39b0b2ba58293137c3d88051e53b32..8eac7301abc705df0d96c214107ddb7683b5957a 100644 (file)
@@ -23,9 +23,7 @@ void XonoticGameWeaponsSettingsTab_fill(entity me)
 {
        entity e;
        entity weaponsApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0',
-               "sendcvar cl_autoswitch;"
                "sendcvar cl_weaponpriority;"
-               "sendcvar cl_weaponimpulsemode;"
                , COMMANDBUTTON_APPLY);
        weaponsApplyButton.disableOnClick = true;
 
@@ -51,12 +49,12 @@ void XonoticGameWeaponsSettingsTab_fill(entity me)
                        _("Make use of the list above when cycling through weapons with the mouse wheel")));
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_weaponimpulsemode", _("Cycle through only usable weapon selections")));
-                       e.applyButton = weaponsApplyButton;
+                       e.sendCvars = true;
        me.TR(me);
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox_T(0, "cl_autoswitch", _("Auto switch weapons on pickup"),
                        _("Automatically switch to newly picked up weapons if they are better than what you are carrying")));
-                       e.applyButton = weaponsApplyButton;
+                       e.sendCvars = true;
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_unpress_attack_on_weapon_switch", _("Release attack buttons when you switch weapons")));
        me.TR(me);
index 1c7da72919d68934749d76034cef11cd00ae3b97..ca812d30415bd23c46802c36c0359cc41e0e3bd2 100644 (file)
@@ -36,8 +36,8 @@ void XonoticMiscSettingsTab_fill(entity me)
                        _("Specify your network speed")));
                        e.addValue(e, _("56k"), "4000");
                        e.addValue(e, _("ISDN"), "7000");
-                       e.addValue(e, _("Slow ADSL"), "15000");
-                       e.addValue(e, _("Fast ADSL"), "20000");
+                       e.addValue(e, _("Slow ADSL"), "20000");
+                       e.addValue(e, _("Fast ADSL"), "40000");
                        e.addValue(e, _("Broadband"), "66666");
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
@@ -87,15 +87,13 @@ void XonoticMiscSettingsTab_fill(entity me)
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Maximum:")));
                me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_maxfps"));
                        ADDVALUE_FPS(30);
-                       ADDVALUE_FPS(40);
-                       ADDVALUE_FPS(50);
                        ADDVALUE_FPS(60);
-                       ADDVALUE_FPS(70);
-                       ADDVALUE_FPS(80);
                        ADDVALUE_FPS(100);
                        ADDVALUE_FPS(125);
                        ADDVALUE_FPS(150);
                        ADDVALUE_FPS(200);
+                       ADDVALUE_FPS(250);
+                       ADDVALUE_FPS(400);
                        e.addValue(e, ZCTX(_("MAXFPS^Unlimited")), "0");
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
@@ -103,14 +101,13 @@ void XonoticMiscSettingsTab_fill(entity me)
                me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_minfps"));
                        e.addValue(e, ZCTX(_("TRGT^Disabled")), "0");
                        ADDVALUE_FPS(30);
-                       ADDVALUE_FPS(40);
-                       ADDVALUE_FPS(50);
                        ADDVALUE_FPS(60);
-                       ADDVALUE_FPS(80);
                        ADDVALUE_FPS(100);
                        ADDVALUE_FPS(125);
                        ADDVALUE_FPS(150);
                        ADDVALUE_FPS(200);
+                       ADDVALUE_FPS(250);
+                       ADDVALUE_FPS(400);
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Idle limit:")));
index 27d6d4a82ec3a143f93ececce635ac37fba1892e..5e5b707faed5fd4d216b23a1348693d7bc2e712d 100644 (file)
@@ -17,8 +17,6 @@ entity makeXonoticUserSettingsTab()
 void XonoticUserSettingsTab_fill(entity me)
 {
        entity e, sk;
-       entity userApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_gentle;", COMMANDBUTTON_APPLY);
-       userApplyButton.disableOnClick = true;
 
        me.TR(me);
                me.TDempty(me, 0.25);
@@ -73,9 +71,5 @@ void XonoticUserSettingsTab_fill(entity me)
        me.gotoRC(me, 11.5, 3.25); me.setFirstColumn(me, me.currentColumn);
                me.TD(me, 1, 2.5, e = makeXonoticCheckBox_T(0, "cl_gentle", _("Disable gore effects and harsh language"),
                        _("Replace blood and gibs with content that does not have any gore effects")));
-                       e.applyButton = userApplyButton;
-
-       me.gotoRC(me, me.rows - 1, 0);
-               me.TD(me, 1, 6, userApplyButton);
-
+                       e.sendCvars = true;
 }
index 20984034db9c8887cf186ace4ba7be84e0e47a6f..dc39346aa61f962f323964e81b05eccec083dc4f 100644 (file)
@@ -11,7 +11,6 @@ void InstantAction_LoadMap(entity btn, entity dummy)
        float pmin = 2, pmax = 16, pstep = 1;
 
        cvar_set("timelimit_override", "10");
-       cvar_set("g_lms_lives_override", "9");
 
        if(random() < 0.4) // 40% are DM
        {
index 7f6424bfce34156201ef4bdcca93befc48813ef8..4f6e4a04a6dbe3201e43430975b00ede72e53c6b 100644 (file)
@@ -68,9 +68,9 @@ void KeyBinds_Read()
        for(int imp = 1; imp <= 9; ++imp)
        {
                string w_list = "";
-               ADD_TO_W_LIST(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_HIDDEN) && !(it.spawnflags & WEP_FLAG_SUPERWEAPON));
+               ADD_TO_W_LIST(!(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK | WEP_FLAG_SUPERWEAPON)));
                ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_SUPERWEAPON) && !(it.spawnflags & WEP_FLAG_HIDDEN));
-               ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_HIDDEN));
+               ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)));
                if(w_list)
                        KEYBIND_DEF(strcat("weapon_group_", itos(imp)), substring(w_list, 0, -4));
                if(imp == 0)
@@ -122,6 +122,7 @@ void KeyBinds_Read()
        KEYBIND_DEF("kill"                                  , _("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();
 
index 2c600b6f5289e6d92a03569a0c2dabf03cab3ca7..7d19516cf01673cfd38f150a63ab4678de6612ca 100644 (file)
@@ -41,12 +41,11 @@ string XonoticStatsList_convertDate(string input)
                default: return input; // failed, why?
        }
 
-       return sprintf(
-               "%s %s, %d",
-               monthname,
-               count_ordinal(stof(substring(input, 8, 2))),
-               stof(substring(input, 0, 4))
-       );
+       string date = ZCTX(_("DATE^%m %d, %Y"));
+       date = strreplace("%Y", substring(input, 0, 4), date);
+       date = strreplace("%d", ftos(stof(substring(input, 8, 2))), date); // ftos-stof removes leading 0
+       date = strreplace("%m", monthname, date);
+       return date;
 }
 
 void XonoticStatsList_getStats(entity me)
index c6e26e09e8fdbf77e641a6f9937e1ade5e60ac24..93ca6acf93eba5b7204c3dd0d4353a5b4a9901dd 100644 (file)
@@ -148,6 +148,16 @@ void antilag_restore_all(entity ignore)
        });
 }
 
+float antilag_getlag(entity e)
+{
+       float lag = ((IS_REAL_CLIENT(e)) ? ANTILAG_LATENCY(e) : 0);
+       bool noantilag = ((IS_CLIENT(e)) ? CS(e).cvar_cl_noantilag : false);
+       if(autocvar_g_antilag == 0 || noantilag || lag < 0.001)
+               lag = 0;
+
+       return lag;
+}
+
 /*
 ==================
 traceline_antilag
index c3be5553a946837a3f8e7960121fdc0d0681cb66..f02803387dd179c7cb3d8fa9857024bcb3e297b3 100644 (file)
@@ -9,6 +9,8 @@ void antilag_clear(entity e, entity store);
 void antilag_takeback_all(entity ignore, float lag);
 void antilag_restore_all(entity ignore);
 
+float antilag_getlag(entity e); // returns antilag latency for clients, plus any modifiers (such as noantilag)
+
 .float antilag_debug;
 
 #define ANTILAG_LATENCY(e) min(0.4, CS(e).ping * 0.001)
index a763b97267b5a69dcec8883b66a4a8c71127bf70..19f76c4f0f2531e777286ee3cc97a7d9f854ba2b 100644 (file)
@@ -91,7 +91,8 @@ float autocvar_g_balance_selfdamagepercent;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
 float autocvar_g_ballistics_mindistance;
-bool autocvar_g_ballistics_penetrate_clips;
+bool autocvar_g_ballistics_penetrate_clips = true;
+float autocvar_g_ballistics_solidpenetration_exponent = 0.25;
 float autocvar_g_ban_default_bantime;
 float autocvar_g_ban_default_masksize;
 float autocvar_g_ban_sync_interval;
@@ -156,6 +157,8 @@ string autocvar_g_maplist_votable_screenshot_dir;
 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_bots = true;
 int autocvar_g_maxplayers;
 float autocvar_g_maxplayers_spectator_blocktime;
 float autocvar_g_maxpushtime;
@@ -179,6 +182,7 @@ float autocvar_g_items_maxdist;
 int autocvar_g_pickup_items;
 float autocvar_g_player_alpha;
 float autocvar_g_player_brightness;
+float autocvar_g_player_damageforcescale = 2;
 bool autocvar_g_playerclip_collisions;
 int autocvar_g_powerups;
 int autocvar_g_projectiles_damage;
@@ -252,7 +256,6 @@ int autocvar_leadlimit_and_fraglimit;
 int autocvar_leadlimit_override;
 int autocvar_minplayers;
 int autocvar_minplayers_per_team;
-int autocvar_name_maxlength;
 string autocvar_nextmap;
 string autocvar_quit_and_redirect;
 float autocvar_quit_and_redirect_timer;
@@ -287,6 +290,7 @@ string autocvar_sv_defaultplayermodel_pink;
 string autocvar_sv_defaultplayermodel_red;
 string autocvar_sv_defaultplayermodel_yellow;
 int autocvar_sv_defaultplayerskin;
+bool autocvar_sv_doors_always_open;
 bool autocvar_sv_doublejump;
 bool autocvar_sv_eventlog;
 bool autocvar_sv_eventlog_console;
@@ -297,7 +301,7 @@ string autocvar_sv_eventlog_files_namesuffix;
 bool autocvar_sv_eventlog_files_timestamps;
 float autocvar_sv_friction_on_land;
 var float autocvar_sv_friction_slick = 0.5;
-float autocvar_sv_gameplayfix_q2airaccelerate;
+float autocvar_sv_gameplayfix_q2airaccelerate = 1;
 int autocvar_sv_gentle;
 #define autocvar_sv_gravity cvar("sv_gravity")
 string autocvar_sv_intermission_cdtrack;
@@ -315,6 +319,7 @@ float autocvar_sv_mapchange_delay;
 float autocvar_sv_maxairspeed;
 float autocvar_sv_maxspeed;
 string autocvar_sv_motd;
+int autocvar_sv_name_maxlength = 64;
 bool autocvar_sv_precacheplayermodels;
 bool autocvar_sv_q3acompat_machineshotgunswap;
 bool autocvar_sv_servermodelsonly;
@@ -370,8 +375,8 @@ float autocvar_timelimit_overtime;
 int autocvar_timelimit_overtimes;
 float autocvar_timelimit_suddendeath;
 #define autocvar_utf8_enable cvar("utf8_enable")
-float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
-bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
+bool autocvar_sv_gameplayfix_gravityunaffectedbyticrate = true;
+bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag = true;
 float autocvar_g_trueaim_minrange;
 float autocvar_g_grab_range;
 int autocvar_g_max_info_autoscreenshot;
index 3f434dbecc7ab529dcc0794ba514e31c60e4eb68..f8285f634d82f0b920ead3a79c3af60712a778f6 100644 (file)
@@ -7,16 +7,22 @@
 const int WAYPOINTFLAG_GENERATED = BIT(23);
 const int WAYPOINTFLAG_ITEM = BIT(22);
 const int WAYPOINTFLAG_TELEPORT = BIT(21); // teleports, warpzones and jumppads
-const int WAYPOINTFLAG_NORELINK = BIT(20);
+//const int WAYPOINTFLAG_NORELINK = BIT(20); // deprecated, see explanation below. Do not recycle this bit.
 const int WAYPOINTFLAG_PERSONAL = BIT(19);
 const int WAYPOINTFLAG_PROTECTED = BIT(18);  // Useless WP detection never kills these.
 const int WAYPOINTFLAG_USEFUL = BIT(17);  // Useless WP detection temporary flag.
 const int WAYPOINTFLAG_DEAD_END = BIT(16);  // Useless WP detection temporary flag.
 const int WAYPOINTFLAG_LADDER = BIT(15);
 const int WAYPOINTFLAG_JUMP = BIT(14);
+const int WAYPOINTFLAG_CUSTOM_JP = BIT(13);  // jumppad with different destination waypoint (changed in the editor)
+const int WAYPOINTFLAG_CROUCH = BIT(12);
+const int WAYPOINTFLAG_SUPPORT = BIT(11);
 
-entity kh_worldkeylist;
-.entity kh_worldkeynext;
+// removed WAYPOINTFLAG_NORELINK since it breaks backward compatibility
+// e.g. support waypoints would have no outgoing links in old Xonotic versions
+// In general, old Xonotic versions should spawn a normal waypoint for each unknown waypoint type
+const int WAYPOINTFLAG_NORELINK__DEPRECATED = BIT(20);
+const int WPFLAGMASK_NORELINK = (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER | WAYPOINTFLAG_JUMP | WAYPOINTFLAG_CUSTOM_JP | WAYPOINTFLAG_SUPPORT);
 
 float bot_custom_weapon;
 float bot_weapons_close[Weapons_MAX];
@@ -51,8 +57,8 @@ float skill;
 .float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
 .float wpconsidered;
 .float wpcost;
-.float wphardwired;
 .int wpflags;
+.entity wphw00, wphw01, wphw02, wphw03, wphw04, wphw05, wphw06, wphw07;
 
 bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity);
 void bot_aim_reset(entity this);
@@ -101,6 +107,7 @@ void navigation_goalrating_timeout_set(entity this);
 void navigation_goalrating_timeout_force(entity this);
 void navigation_goalrating_timeout_expire(entity this, float seconds);
 bool navigation_goalrating_timeout(entity this);
+void navigation_goalrating_timeout_extend_if_needed(entity this, float seconds);
 bool navigation_goalrating_timeout_can_be_anticipated(entity this);
 void navigation_markroutes(entity this, entity fixed_source_waypoint);
 void navigation_markroutes_inverted(entity fixed_source_waypoint);
@@ -121,9 +128,11 @@ void waypoint_spawnforitem(entity e);
 void waypoint_spawnforitem_force(entity e, vector org);
 void waypoint_spawnforteleporter(entity e, vector destination, float timetaken, entity tracetest_ent);
 void waypoint_spawnforteleporter_wz(entity e, entity tracetest_ent);
-void waypoint_spawn_fromeditor(entity pl);
+void waypoint_spawn_fromeditor(entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp);
 entity waypoint_spawn(vector m1, vector m2, float f);
 void waypoint_unreachable(entity pl);
+void waypoint_start_hardwiredlink(entity pl, bool at_crosshair);
+void waypoint_lock(entity pl);
 
 void waypoint_getSymmetricalOrigin_cmd(entity caller, bool save, int arg_idx);
 void waypoint_getSymmetricalAxis_cmd(entity caller, bool save, int arg_idx);
index 90338d20214e1e0ec3132f7af1c3b597bba4f4a3..40afed17990b7e93c40e41e194b5893054c54911 100644 (file)
@@ -580,6 +580,7 @@ void bot_calculate_stepheightvec()
        stepheightvec = autocvar_sv_stepheight * '0 0 1';
        jumpheight_vec = (autocvar_sv_jumpvelocity ** 2) / (2 * autocvar_sv_gravity) * '0 0 1';
        jumpstepheightvec = stepheightvec + jumpheight_vec * 0.85; // reduce it a bit to make the jumps easy
+       jumpheight_time = autocvar_sv_jumpvelocity / autocvar_sv_gravity;
 }
 
 bool bot_fixcount()
@@ -756,7 +757,7 @@ void bot_serverframe()
                if(botframe_cachedwaypointlinks)
                {
                        if(!botframe_loadedforcedlinks)
-                               waypoint_load_links_hardwired();
+                               waypoint_load_hardwiredlinks();
                }
                else
                {
index 57b4c310e37ed33760c7500f81c5fa1d8089d7f3..4e32ce99a0c415927749afa9f89b672f6e2a6c49 100644 (file)
@@ -1,5 +1,7 @@
 #include "havocbot.qh"
 
+#include "roles.qh"
+
 #include <server/defs.qh>
 #include <server/miscfunctions.qh>
 #include "../cvars.qh"
@@ -24,8 +26,6 @@
 
 #include <lib/warpzone/common.qh>
 
-.float speed;
-
 void havocbot_ai(entity this)
 {
        if(this.draggedby)
@@ -89,6 +89,9 @@ void havocbot_ai(entity this)
                bot_strategytoken_taken = true;
        }
 
+       if (this.goalcurrent && wasfreed(this.goalcurrent))
+               navigation_clearroute(this);
+
        if(IS_DEAD(this) || STAT(FROZEN, this))
        {
                if (this.goalcurrent)
@@ -193,93 +196,85 @@ void havocbot_ai(entity this)
 
 void havocbot_keyboard_movement(entity this, vector destorg)
 {
-       vector keyboard;
+       if(time <= this.havocbot_keyboardtime)
+               return;
 
-       if (time > this.havocbot_keyboardtime)
+       float sk = skill + this.bot_moveskill;
+       this.havocbot_keyboardtime =
+               max(
+                       this.havocbot_keyboardtime
+                               + 0.05 / max(1, sk + this.havocbot_keyboardskill)
+                               + random() * 0.025 / max(0.00025, skill + this.havocbot_keyboardskill)
+               , time);
+       vector keyboard = CS(this).movement / autocvar_sv_maxspeed;
+
+       float trigger = autocvar_bot_ai_keyboard_threshold;
+
+       // categorize forward movement
+       // at skill < 1.5 only forward
+       // at skill < 2.5 only individual directions
+       // at skill < 4.5 only individual directions, and forward diagonals
+       // at skill >= 4.5, all cases allowed
+       if (keyboard.x > trigger)
        {
-               float sk = skill + this.bot_moveskill;
-               this.havocbot_keyboardtime =
-                       max(
-                               this.havocbot_keyboardtime
-                                       + 0.05 / max(1, sk + this.havocbot_keyboardskill)
-                                       + random() * 0.025 / max(0.00025, skill + this.havocbot_keyboardskill)
-                       , time);
-               keyboard = CS(this).movement / autocvar_sv_maxspeed;
-
-               float trigger = autocvar_bot_ai_keyboard_threshold;
-
-               // categorize forward movement
-               // at skill < 1.5 only forward
-               // at skill < 2.5 only individual directions
-               // at skill < 4.5 only individual directions, and forward diagonals
-               // at skill >= 4.5, all cases allowed
-               if (keyboard.x > trigger)
-               {
-                       keyboard.x = 1;
-                       if (sk < 2.5)
-                               keyboard.y = 0;
-               }
-               else if (keyboard.x < -trigger && sk > 1.5)
-               {
-                       keyboard.x = -1;
-                       if (sk < 4.5)
-                               keyboard.y = 0;
-               }
-               else
-               {
-                       keyboard.x = 0;
-                       if (sk < 1.5)
-                               keyboard.y = 0;
-               }
+               keyboard.x = 1;
+               if (sk < 2.5)
+                       keyboard.y = 0;
+       }
+       else if (keyboard.x < -trigger && sk > 1.5)
+       {
+               keyboard.x = -1;
                if (sk < 4.5)
-                       keyboard.z = 0;
-
-               if (keyboard.y > trigger)
-                       keyboard.y = 1;
-               else if (keyboard.y < -trigger)
-                       keyboard.y = -1;
-               else
                        keyboard.y = 0;
+       }
+       else
+       {
+               keyboard.x = 0;
+               if (sk < 1.5)
+                       keyboard.y = 0;
+       }
+       if (sk < 4.5)
+               keyboard.z = 0;
 
-               if (keyboard.z > trigger)
-                       keyboard.z = 1;
-               else if (keyboard.z < -trigger)
-                       keyboard.z = -1;
-               else
-                       keyboard.z = 0;
+       if (keyboard.y > trigger)
+               keyboard.y = 1;
+       else if (keyboard.y < -trigger)
+               keyboard.y = -1;
+       else
+               keyboard.y = 0;
+
+       if (keyboard.z > trigger)
+               keyboard.z = 1;
+       else if (keyboard.z < -trigger)
+               keyboard.z = -1;
+       else
+               keyboard.z = 0;
 
-               // make sure bots don't get stuck if havocbot_keyboardtime is very high
-               if (keyboard == '0 0 0')
-                       this.havocbot_keyboardtime = min(this.havocbot_keyboardtime, time + 0.2);
+       // make sure bots don't get stuck if havocbot_keyboardtime is very high
+       if (keyboard == '0 0 0')
+               this.havocbot_keyboardtime = min(this.havocbot_keyboardtime, time + 0.2);
 
-               this.havocbot_keyboard = keyboard * autocvar_sv_maxspeed;
-               if (this.havocbot_ducktime > time)
-                       PHYS_INPUT_BUTTON_CROUCH(this) = true;
+       this.havocbot_keyboard = keyboard * autocvar_sv_maxspeed;
+       if (this.havocbot_ducktime > time)
+               PHYS_INPUT_BUTTON_CROUCH(this) = true;
 
-               keyboard = this.havocbot_keyboard;
-               float blend = bound(0, vlen(destorg - this.origin) / autocvar_bot_ai_keyboard_distance, 1); // When getting close move with 360 degree
-               //dprint("movement ", vtos(CS(this).movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
-               CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
-       }
+       keyboard = this.havocbot_keyboard;
+       float blend = bound(0, vlen(destorg - this.origin) / autocvar_bot_ai_keyboard_distance, 1); // When getting close move with 360 degree
+       //dprint("movement ", vtos(CS(this).movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
+       CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
 }
 
 void havocbot_bunnyhop(entity this, vector dir)
 {
-       float bunnyhopdistance;
-       vector deviation;
-       float maxspeed;
-
        // Don't jump when attacking
        if(this.aistatus & AI_STATUS_ATTACKING)
                return;
 
-       if(IS_PLAYER(this.goalcurrent))
+       if (!this.goalcurrent || IS_PLAYER(this.goalcurrent))
                return;
 
-       maxspeed = autocvar_sv_maxspeed;
-
-       if(this.aistatus & AI_STATUS_RUNNING && vdist(this.velocity, <, autocvar_sv_maxspeed * 0.75)
-               || this.aistatus & AI_STATUS_DANGER_AHEAD)
+       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;
@@ -288,7 +283,7 @@ void havocbot_bunnyhop(entity this, vector dir)
                return;
        }
 
-       if(this.waterlevel > WATERLEVEL_WETFEET)
+       if(this.waterlevel > WATERLEVEL_WETFEET || IS_DUCKED(this))
        {
                this.aistatus &= ~AI_STATUS_RUNNING;
                return;
@@ -300,116 +295,88 @@ void havocbot_bunnyhop(entity this, vector dir)
                this.bot_timelastseengoal = 0;
        }
 
-       vector gco = get_closer_dest(this.goalcurrent, this.origin);
-       bunnyhopdistance = vlen(this.origin - gco);
-
        // Run only to visible goals
        if(IS_ONGROUND(this))
-       if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running
+       if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
        if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
        {
-                       this.bot_lastseengoal = this.goalcurrent;
+               this.bot_lastseengoal = this.goalcurrent;
 
-                       // seen it before
-                       if(this.bot_timelastseengoal)
+               // 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)
                        {
-                               // for a period of time
-                               if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
-                               {
-                                       float checkdistance;
-                                       checkdistance = true;
+                               bool checkdistance = true;
 
-                                       // don't run if it is too close
-                                       if(this.bot_canruntogoal==0)
-                                       {
-                                               if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_startdistance)
-                                                       this.bot_canruntogoal = 1;
-                                               else
-                                                       this.bot_canruntogoal = -1;
-                                       }
+                               // 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.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.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)
                                        {
-                                               vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
-                                               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(bunnyhopdistance < vlen(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))
                                                {
-                                                       if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
-                                                       if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
-                                                       {
-                                                               checkdistance = false;
-                                                       }
+                                                       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(bunnyhopdistance > autocvar_bot_ai_bunnyhop_stopdistance + (this.origin.z - gco.z))
-                                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
-                                       }
-                                       else
-                                       {
-                                               this.aistatus |= AI_STATUS_RUNNING;
+                               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 = time;
+               }
        }
        else
        {
                this.bot_timelastseengoal = 0;
        }
-
-#if 0
-       // Release jump button
-       if(!cvar("sv_pogostick"))
-       if((IS_ONGROUND(this)) == 0)
-       {
-               if(this.velocity.z < 0 || vlen(this.velocity)<maxspeed)
-                       PHYS_INPUT_BUTTON_JUMP(this) = false;
-
-               // Strafe
-               if(this.aistatus & AI_STATUS_RUNNING)
-               if(vlen(this.velocity)>maxspeed)
-               {
-                       deviation = vectoangles(dir) - vectoangles(this.velocity);
-                       while (deviation.y < -180) deviation.y = deviation.y + 360;
-                       while (deviation.y > 180) deviation.y = deviation.y - 360;
-
-                       if(fabs(deviation.y)>10)
-                               CS(this).movement_x = 0;
-
-                       if(deviation.y>10)
-                               CS(this).movement_y = maxspeed * -1;
-                       else if(deviation.y<10)
-                               CS(this).movement_y = maxspeed;
-
-               }
-       }
-#endif
 }
 
 // return true when bot isn't getting closer to the current goal
 bool havocbot_checkgoaldistance(entity this, vector gco)
 {
+       if (this.bot_stop_moving_timeout > time)
+               return false;
        float curr_dist_z = max(20, fabs(this.origin.z - gco.z));
        float curr_dist_2d = max(20, vlen(vec2(this.origin - gco)));
        float distance_time = this.goalcurrent_distance_time;
@@ -476,6 +443,8 @@ void havocbot_movetogoal(entity this)
        CS(this).movement = '0 0 0';
        maxspeed = autocvar_sv_maxspeed;
 
+       PHYS_INPUT_BUTTON_CROUCH(this) = boolean(this.goalcurrent.wpflags & WAYPOINTFLAG_CROUCH);
+
        PHYS_INPUT_BUTTON_JETPACK(this) = false;
        // Jetpack navigation
        if(this.navigation_jetpack_goal)
@@ -678,7 +647,8 @@ void havocbot_movetogoal(entity this)
 
                        return;
                }
-               else if(!this.jumppadcount && !this.goalcurrent.wphardwired
+               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())
                {
                        if(this.velocity.z < 0)
@@ -993,7 +963,26 @@ void havocbot_movetogoal(entity this)
                        vector flat_diff = vec2(diff);
                        offset = max(32, current_speed * cos(deviation.y * DEG2RAD) * 0.3) * flatdir;
                        vector actual_destorg = this.origin + offset;
-                       if (!this.goalstack01 || this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER))
+                       if (this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP))
+                       {
+                               if (time > this.bot_stop_moving_timeout
+                                       && fabs(deviation.y) > 20 && current_speed > maxspeed * 0.4
+                                       && vdist(vec2(this.origin - this.goalcurrent_prev.origin), <, 50))
+                               {
+                                       this.bot_stop_moving_timeout = time + 0.1;
+                               }
+                               if (current_speed > autocvar_sv_maxspeed * 0.9
+                                       && vlen2(flat_diff) < vlen2(vec2(this.goalcurrent_prev.origin - destorg))
+                                       && vdist(vec2(this.origin - this.goalcurrent_prev.origin), >, 50)
+                                       && vdist(vec2(this.origin - this.goalcurrent_prev.origin), <, 150)
+                               )
+                               {
+                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                       // avoid changing route while bot is jumping a gap
+                                       navigation_goalrating_timeout_extend_if_needed(this, 1.5);
+                               }
+                       }
+                       else if (!this.goalstack01 || (this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER)))
                        {
                                if (vlen2(flat_diff) < vlen2(offset))
                                {
@@ -1029,10 +1018,20 @@ void havocbot_movetogoal(entity this)
                                turning = true;
                        }
 
-                       LABEL(jump_check);
+                       LABEL(jumpobstacle_check);
                        dir = flatdir = normalize(actual_destorg - this.origin);
 
-                       if (turning || fabs(deviation.y) < 50) // don't even try to jump if deviation is too high
+                       bool jump_forbidden = false;
+                       if (!turning && fabs(deviation.y) > 50)
+                               jump_forbidden = true;
+                       else if (IS_DUCKED(this))
+                       {
+                               tracebox(this.origin, PL_MIN_CONST, PL_MAX_CONST, this.origin, false, this);
+                               if (trace_startsolid)
+                                       jump_forbidden = true;
+                       }
+
+                       if (!jump_forbidden)
                        {
                                tracebox(this.origin, this.mins, this.maxs, actual_destorg, false, this);
                                if (trace_fraction < 1 && trace_plane_normal.z < 0.7)
@@ -1048,7 +1047,7 @@ void havocbot_movetogoal(entity this)
                                                        actual_destorg = destorg;
                                                        turning = false;
                                                        this.bot_tracewalk_time = time + 0.25;
-                                                       goto jump_check;
+                                                       goto jumpobstacle_check;
                                                }
                                                s = trace_fraction;
                                                // don't artificially reduce max jump height in real-time
@@ -1112,7 +1111,9 @@ void havocbot_movetogoal(entity this)
 
                        bool unreachable = false;
                        s = CONTENT_SOLID;
-                       if(trace_fraction == 1 && this.jumppadcount == 0 && !this.goalcurrent.wphardwired )
+                       if (trace_fraction == 1 && !this.jumppadcount
+                               && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
+                               && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
                        if((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || (this.aistatus & AI_STATUS_ROAMING) || PHYS_INPUT_BUTTON_JUMP(this))
                        {
                                // Look downwards
@@ -1159,7 +1160,7 @@ void havocbot_movetogoal(entity this)
                        }
 
                        // slow down if bot is in the air and goal is under it
-                       if (!this.goalcurrent.wphardwired
+                       if (!waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
                                && vdist(flat_diff, <, 250) && this.origin.z - destorg.z > 120
                                && (!IS_ONGROUND(this) || vdist(vec2(this.velocity), >, maxspeed * 0.3)))
                        {
@@ -1254,9 +1255,7 @@ void havocbot_movetogoal(entity this)
                havocbot_keyboard_movement(this, destorg);
 
        // Bunnyhop!
-       //if(this.aistatus & AI_STATUS_ROAMING)
-       if(!bunnyhop_forbidden && this.goalcurrent)
-       if(skill+this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
+       if (!bunnyhop_forbidden && 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))
index 2ec6316917f73f32c74ccedaf8ce28d4b4774044..d1a36a117260027569b229cb291cc78e2cd0a70a 100644 (file)
@@ -51,9 +51,6 @@ float havocbot_moveto_refresh_route(entity this);
 
 vector havocbot_dodge(entity this);
 
-.void(entity this) havocbot_role;
-.void(entity this) havocbot_previous_role;
-
 void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_items;
 void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
 
index b72153c95cb0bc371c5e9808b544b785861be7de..84c597329ea5fda0eb0930dfec079be15e7edb22 100644 (file)
 #include "../bot.qh"
 #include "../navigation.qh"
 
-.float bot_ratingscale;
-.float bot_ratingscale_time;
-.float max_armorvalue;
-.float havocbot_role_timeout;
-
-.void(entity this) havocbot_previous_role;
-.void(entity this) havocbot_role;
-
 void havocbot_goalrating_waypoints(entity this, float ratingscale, vector org, float sradius)
 {
        // rate waypoints only if there's no alternative goal
@@ -68,10 +60,10 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en
        if(!teamplay)
                return true;
 
-       // actually these variables hold the squared distances in order to optimize code
-       float friend_distance = FLOAT_MAX;
-       float enemy_distance = FLOAT_MAX;
-       float dist;
+       // these variables hold squared distances in order to optimize code
+       float friend_dist2 = FLOAT_MAX;
+       float enemy_dist2 = FLOAT_MAX;
+       float dist2;
 
        FOREACH_CLIENT(IS_PLAYER(it) && it != this && !(IS_DEAD(it) || STAT(FROZEN, it)),
        {
@@ -80,13 +72,13 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en
                        if (!IS_REAL_CLIENT(it))
                                continue;
 
-                       dist = vlen2(it.origin - item_org);
-                       if(dist > friend_distance)
+                       dist2 = vlen2(it.origin - item_org);
+                       if (dist2 > friend_dist2)
                                continue;
 
                        if(havocbot_goalrating_item_can_be_left_to_teammate(this, it, item))
                        {
-                               friend_distance = dist;
+                               friend_dist2 = dist2;
                                continue;
                        }
                }
@@ -94,25 +86,23 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en
                {
                        // If enemy only track distances
                        // TODO: track only if visible ?
-                       dist = vlen2(it.origin - item_org);
-                       if(dist < enemy_distance)
-                               enemy_distance = dist;
+                       dist2 = vlen2(it.origin - item_org);
+                       if (dist2 < enemy_dist2)
+                               enemy_dist2 = dist2;
                }
        });
 
        // Rate the item only if no one needs it, or if an enemy is closer to it
-       dist = vlen2(item_org - org);
-       if ((enemy_distance < friend_distance && dist < enemy_distance) ||
-               (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ** 2) ||
-               (dist < friend_distance && dist < 200 ** 2))
+       dist2 = vlen2(item_org - org);
+       if ((enemy_dist2 < friend_dist2 && dist2 < enemy_dist2)
+               || (friend_dist2 > autocvar_bot_ai_friends_aware_pickup_radius ** 2)
+               || (dist2 < friend_dist2 && dist2 < 200 ** 2))
                return true;
        return false;
 };
 
 void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius)
 {
-       float rating;
-       vector o;
        ratingscale = ratingscale * 0.0001;
 
        IL_EACH(g_items, it.bot_pickup,
@@ -144,7 +134,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
 
                        it.bot_pickup_respawning = true;
                }
-               o = (it.absmin + it.absmax) * 0.5;
+               vector o = (it.absmin + it.absmax) * 0.5;
                if(vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
                        continue;
 
@@ -175,25 +165,23 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
 
                it.bot_ratingscale_time = time;
                it.bot_ratingscale = ratingscale;
-               rating = it.bot_pickupevalfunc(this, it);
+               float rating = it.bot_pickupevalfunc(this, it);
                if(rating > 0)
                        navigation_routerating(this, it, rating * ratingscale, 2000);
        });
 }
 
-#define BOT_RATING_ENEMY 2500
 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
 {
        if (autocvar_bot_nofire)
                return;
 
        // don't chase players if we're under water
-       if(this.waterlevel>WATERLEVEL_WETFEET)
+       if(this.waterlevel > WATERLEVEL_WETFEET)
                return;
 
        ratingscale = ratingscale * 0.0001;
 
-       float t;
        FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), {
                // TODO: Merge this logic with the bot_shouldattack function
                if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
@@ -208,7 +196,7 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
                        continue;
                */
 
-               t = ((GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR)) - (GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR))) / 150;
+               float t = ((GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR)) - (GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR))) / 150;
                t = bound(0, 1 + t, 3);
                if (skill > 3)
                {
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..23a23759a98a9588fb7e693cbef4f8b45588b7fd 100644 (file)
@@ -1 +1,10 @@
 #pragma once
+
+const float BOT_RATING_ENEMY = 2500;
+
+.float bot_ratingscale;
+.float bot_ratingscale_time;
+.float havocbot_role_timeout;
+
+.void(entity this) havocbot_previous_role;
+.void(entity this) havocbot_role;
index d63e158781ea6e2c6bdf83214484a5fc32aa3609..d53922f589a7277e8d30fefe578c9a19097e4016 100644 (file)
@@ -47,6 +47,11 @@ bool navigation_goalrating_timeout(entity this)
        return this.bot_strategytime < time;
 }
 
+void navigation_goalrating_timeout_extend_if_needed(entity this, float seconds)
+{
+       this.bot_strategytime = max(this.bot_strategytime, time + seconds);
+}
+
 #define MAX_CHASE_DISTANCE 700
 bool navigation_goalrating_timeout_can_be_anticipated(entity this)
 {
@@ -917,7 +922,7 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
        vector pm2 = ent.origin + ent.maxs;
 
        // do two scans, because box test is cheaper
-       IL_EACH(g_waypoints, it != ent && it != except && !(it.wpflags & WAYPOINTFLAG_TELEPORT),
+       IL_EACH(g_waypoints, it != ent && it != except && !(it.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_JUMP)),
        {
                if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
                {
@@ -948,7 +953,7 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
                waypoint_clearlinks(ent); // initialize wpXXmincost fields
                IL_EACH(g_waypoints, it != ent,
                {
-                       if(walkfromwp && (it.wpflags & WAYPOINTFLAG_NORELINK))
+                       if (walkfromwp && (it.wpflags & WPFLAGMASK_NORELINK))
                                continue;
 
                        set_tracewalk_dest(ent, it.origin, false);
@@ -964,7 +969,7 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
        // box check failed, try walk
        IL_EACH(g_waypoints, it != ent,
        {
-               if(walkfromwp && (it.wpflags & WAYPOINTFLAG_NORELINK))
+               if (walkfromwp && (it.wpflags & WPFLAGMASK_NORELINK))
                        continue;
                v = it.origin;
 
@@ -1335,7 +1340,7 @@ void navigation_routerating(entity this, entity e, float f, float rangebias)
                        LOG_DEBUG("jetpack ai: required fuel ", ftos(fuel), ", have ", ftos(GetResource(this, RES_FUEL)));
 
                        // enough fuel ?
-                       if(GetResource(this, RES_FUEL) > fuel || (this.items & IT_UNLIMITED_WEAPON_AMMO))
+                       if(GetResource(this, RES_FUEL) > fuel || (this.items & IT_UNLIMITED_AMMO))
                        {
                                // Estimate cost
                                // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
@@ -1577,7 +1582,7 @@ bool navigation_shortenpath(entity this)
 
        next = this.goalstack01;
        // if for some reason the bot is closer to the next goal, pop the current one
-       if (!IS_MOVABLE(next) // already checked in the previous case
+       if (!IS_MOVABLE(next) && !(this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_JUMP))
                && vlen2(this.goalcurrent.origin - next.origin) > vlen2(next.origin - this.origin)
                && checkpvs(this.origin + this.view_ofs, next))
        {
@@ -1771,7 +1776,7 @@ entity navigation_get_really_close_waypoint(entity this)
        if(vdist(wp.origin - this.origin, >, 50))
        {
                wp = NULL;
-               IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_TELEPORT),
+               IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_JUMP)),
                {
                        if(vdist(it.origin - this.origin, <, 50))
                        {
index d002ae29db21e138d8632af79056d9c285409cf1..026d326b9e6fba8524b95a73862eb284e3f06d86 100644 (file)
@@ -10,6 +10,7 @@ float navigation_testtracewalk;
 vector jumpstepheightvec;
 vector stepheightvec;
 vector jumpheight_vec;
+float jumpheight_time;
 
 entity navigation_bestgoal;
 
@@ -29,6 +30,8 @@ entity navigation_bestgoal;
 .float goalcurrent_distance_2d;
 .float goalcurrent_distance_time;
 
+// final goal (item, object or player) is also saved in this field
+.entity goalentity;
 .float goalentity_lock_timeout;
 .bool goalentity_shouldbefrozen;
 
index d69a89400f53be33f8f2079627df8f8ff51f850e..7a40f18e8df56f6e1eacf6e0f242b08b316ee9e6 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <common/constants.qh>
 #include <common/debug.qh>
+#include <common/mapobjects/trigger/jumppads.qh>
 #include <common/net_linked.qh>
 #include <common/physics/player.qh>
 
@@ -259,6 +260,99 @@ vector waypoint_getSymmetricalPoint(vector org, int ctf_flags)
        return new_org;
 }
 
+void crosshair_trace_waypoints(entity pl);
+void waypoint_lock(entity pl)
+{
+       crosshair_trace_waypoints(pl);
+       pl.wp_locked = trace_ent;
+}
+
+bool waypoint_has_hardwiredlinks(entity wp)
+{
+       if (!wp)
+               return false;
+       return (wp.wphw00 != NULL);
+}
+
+bool waypoint_is_hardwiredlink(entity wp_from, entity wp_to)
+{
+       if (!(wp_from && wp_to))
+               return false;
+
+       if (!wp_from.wphw00) return false; else if (wp_from.wphw00 == wp_to) return true;
+       if (!wp_from.wphw01) return false; else if (wp_from.wphw01 == wp_to) return true;
+       if (!wp_from.wphw02) return false; else if (wp_from.wphw02 == wp_to) return true;
+       if (!wp_from.wphw03) return false; else if (wp_from.wphw03 == wp_to) return true;
+       if (!wp_from.wphw04) return false; else if (wp_from.wphw04 == wp_to) return true;
+       if (!wp_from.wphw05) return false; else if (wp_from.wphw05 == wp_to) return true;
+       if (!wp_from.wphw06) return false; else if (wp_from.wphw06 == wp_to) return true;
+       if (!wp_from.wphw07) return false; else if (wp_from.wphw07 == wp_to) return true;
+
+       return false;
+}
+
+void waypoint_setupmodel(entity wp);
+void waypoint_mark_hardwiredlink(entity wp_from, entity wp_to)
+{
+       if (!(wp_from && wp_to))
+               return;
+
+       if (!wp_from.wphw00 || wp_from.wphw00 == wp_to) { wp_from.wphw00 = wp_to; waypoint_setupmodel(wp_from); return; }
+       if (!wp_from.wphw01 || wp_from.wphw01 == wp_to) { wp_from.wphw01 = wp_to; return; }
+       if (!wp_from.wphw02 || wp_from.wphw02 == wp_to) { wp_from.wphw02 = wp_to; return; }
+       if (!wp_from.wphw03 || wp_from.wphw03 == wp_to) { wp_from.wphw03 = wp_to; return; }
+       if (!wp_from.wphw04 || wp_from.wphw04 == wp_to) { wp_from.wphw04 = wp_to; return; }
+       if (!wp_from.wphw05 || wp_from.wphw05 == wp_to) { wp_from.wphw05 = wp_to; return; }
+       if (!wp_from.wphw06 || wp_from.wphw06 == wp_to) { wp_from.wphw06 = wp_to; return; }
+       if (!wp_from.wphw07 || wp_from.wphw07 == wp_to) { wp_from.wphw07 = wp_to; return; }
+
+       return;
+}
+
+void waypoint_unmark_hardwiredlink(entity wp_from, entity wp_to)
+{
+       if (!(wp_from && wp_to))
+               return;
+
+       int removed = -1;
+       if (removed < 0 && wp_from.wphw00 == wp_to) removed = 0;
+       if (removed < 0 && wp_from.wphw01 == wp_to) removed = 1;
+       if (removed < 0 && wp_from.wphw02 == wp_to) removed = 2;
+       if (removed < 0 && wp_from.wphw03 == wp_to) removed = 3;
+       if (removed < 0 && wp_from.wphw04 == wp_to) removed = 4;
+       if (removed < 0 && wp_from.wphw05 == wp_to) removed = 5;
+       if (removed < 0 && wp_from.wphw06 == wp_to) removed = 6;
+       if (removed < 0 && wp_from.wphw07 == wp_to) removed = 7;
+
+       if (removed >= 0)
+       {
+               if (removed <= 0) wp_from.wphw00 = wp_from.wphw01;
+               if (removed <= 1) wp_from.wphw01 = wp_from.wphw02;
+               if (removed <= 2) wp_from.wphw02 = wp_from.wphw03;
+               if (removed <= 3) wp_from.wphw03 = wp_from.wphw04;
+               if (removed <= 4) wp_from.wphw04 = wp_from.wphw05;
+               if (removed <= 5) wp_from.wphw05 = wp_from.wphw06;
+               if (removed <= 6) wp_from.wphw06 = wp_from.wphw07;
+               if (removed <= 7) wp_from.wphw07 = NULL;
+               if (!wp_from.wphw00)
+                       waypoint_setupmodel(wp_from);
+       }
+
+       return;
+}
+
+void waypoint_restore_hardwiredlinks(entity wp)
+{
+       if (wp.wphw00) waypoint_addlink(wp, wp.wphw00);
+       if (wp.wphw01) waypoint_addlink(wp, wp.wphw01);
+       if (wp.wphw02) waypoint_addlink(wp, wp.wphw02);
+       if (wp.wphw03) waypoint_addlink(wp, wp.wphw03);
+       if (wp.wphw04) waypoint_addlink(wp, wp.wphw04);
+       if (wp.wphw05) waypoint_addlink(wp, wp.wphw05);
+       if (wp.wphw06) waypoint_addlink(wp, wp.wphw06);
+       if (wp.wphw07) waypoint_addlink(wp, wp.wphw07);
+}
+
 void waypoint_setupmodel(entity wp)
 {
        if (autocvar_g_waypointeditor)
@@ -270,11 +364,23 @@ void waypoint_setupmodel(entity wp)
                setsize(wp, m1, m2);
                wp.effects = EF_LOWPRECISION;
                if (wp.wpflags & WAYPOINTFLAG_ITEM)
-                       wp.colormod = '1 0 0';
+                       wp.colormod = '1 0 0'; // red
                else if (wp.wpflags & WAYPOINTFLAG_GENERATED)
-                       wp.colormod = '1 1 0';
-               else if (wp.wphardwired)
-                       wp.colormod = '0.5 0 1';
+                       wp.colormod = '1 1 0'; // yellow
+               else if (wp.wpflags & WAYPOINTFLAG_SUPPORT)
+                       wp.colormod = '0 1 0'; // green
+               else if (wp.wpflags & WAYPOINTFLAG_CUSTOM_JP)
+                       wp.colormod = '1 0.5 0'; // orange
+               else if (wp.wpflags & WAYPOINTFLAG_TELEPORT)
+                       wp.colormod = '1 0.5 0'; // orange
+               else if (wp.wpflags & WAYPOINTFLAG_LADDER)
+                       wp.colormod = '1 0.5 0'; // orange
+               else if (wp.wpflags & WAYPOINTFLAG_JUMP)
+                       wp.colormod = '1 0.5 0'; // orange
+               else if (wp.wpflags & WAYPOINTFLAG_CROUCH)
+                       wp.colormod = '0 1 1'; // cyan
+               else if (waypoint_has_hardwiredlinks(wp))
+                       wp.colormod = '0.5 0 1'; // purple
                else
                        wp.colormod = '1 1 1';
        }
@@ -282,21 +388,54 @@ void waypoint_setupmodel(entity wp)
                wp.model = "";
 }
 
+string waypoint_get_type_name(entity wp)
+{
+       if (wp.wpflags & WAYPOINTFLAG_ITEM) return "^1Item waypoint";
+       else if (wp.wpflags & WAYPOINTFLAG_CROUCH) return "^5Crouch waypoint";
+       else if (wp.wpflags & WAYPOINTFLAG_JUMP) return "^xf80Jump waypoint";
+       else if (wp.wpflags & WAYPOINTFLAG_SUPPORT) return "^2Support waypoint";
+       else if (waypoint_has_hardwiredlinks(wp)) return "^x80fHardwired waypoint";
+       else if (wp.wpflags & WAYPOINTFLAG_LADDER) return "^3Ladder waypoint";
+       else if (wp.wpflags & WAYPOINTFLAG_TELEPORT)
+       {
+               if (!wp.wpisbox) return "^3Warpzone waypoint";
+               else if (wp.wpflags & WAYPOINTFLAG_CUSTOM_JP) return "^3Custom jumppad waypoint";
+               else
+               {
+                       IL_EACH(g_jumppads, boxesoverlap(wp.absmin, wp.absmax, it.absmin, it.absmax),
+                               { return "^3Jumppad waypoint"; });
+                       return "^3Teleport waypoint";
+               }
+       }
+
+       return "^7Waypoint";
+}
+
+entity waypoint_get(vector m1, vector m2)
+{
+       if (m1 == m2)
+       {
+               m1 -= '8 8 8';
+               m2 += '8 8 8';
+       }
+       IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax), { return it; });
+
+       return NULL;
+}
+
+.float createdtime;
 entity waypoint_spawn(vector m1, vector m2, float f)
 {
        if(!(f & (WAYPOINTFLAG_PERSONAL | WAYPOINTFLAG_GENERATED)) && m1 == m2)
        {
-               vector em1 = m1 - '8 8 8';
-               vector em2 = m2 + '8 8 8';
-               IL_EACH(g_waypoints, boxesoverlap(em1, em2, it.absmin, it.absmax),
-               {
-                       return it;
-               });
+               entity wp_found = waypoint_get(m1, m2);
+               if (wp_found)
+                       return wp_found;
        }
        // spawn only one destination waypoint for teleports teleporting player to the exact same spot
        // otherwise links loaded from file would be applied only to the first destination
        // waypoint since link format doesn't specify waypoint entities but just positions
-       if((f & WAYPOINTFLAG_GENERATED) && !(f & (WAYPOINTFLAG_NORELINK | WAYPOINTFLAG_PERSONAL)) && m1 == m2)
+       if((f & WAYPOINTFLAG_GENERATED) && !(f & (WPFLAGMASK_NORELINK | WAYPOINTFLAG_PERSONAL)) && m1 == m2)
        {
                IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax),
                {
@@ -309,6 +448,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
        w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
        w.wpflags = f;
        w.solid = SOLID_TRIGGER;
+       w.createdtime = time;
        setorigin(w, (m1 + m2) * 0.5);
        setsize(w, m1 - w.origin, m2 - w.origin);
        if (w.size)
@@ -316,7 +456,10 @@ entity waypoint_spawn(vector m1, vector m2, float f)
 
        if(!w.wpisbox)
        {
-               setsize(w, PL_MIN_CONST - '1 1 0', PL_MAX_CONST + '1 1 0');
+               if (f & WAYPOINTFLAG_CROUCH)
+                       setsize(w, PL_CROUCH_MIN_CONST - '1 1 0', PL_CROUCH_MAX_CONST + '1 1 0');
+               else
+                       setsize(w, PL_MIN_CONST - '1 1 0', PL_MAX_CONST + '1 1 0');
                if(!move_out_of_solid(w))
                {
                        if(!(f & WAYPOINTFLAG_GENERATED))
@@ -345,10 +488,114 @@ entity waypoint_spawn(vector m1, vector m2, float f)
        return w;
 }
 
-void waypoint_spawn_fromeditor(entity pl)
+float trigger_push_get_push_time(entity this, vector endpos);
+void waypoint_addlink_for_custom_jumppad(entity wp_from, entity wp_to)
+{
+       entity jp = NULL;
+       IL_EACH(g_jumppads, boxesoverlap(wp_from.absmin, wp_from.absmax, it.absmin, it.absmax),
+       {
+               jp = it;
+               break;
+       });
+       if (!jp)
+               return;
+
+       float cost = trigger_push_get_push_time(jp, wp_to.origin);
+       wp_from.wp00 = wp_to;
+       wp_from.wp00mincost = cost;
+       jp.nearestwaypoint = wp_from;
+       jp.nearestwaypointtimeout = -1;
+}
+
+bool start_wp_is_spawned;
+vector start_wp_origin;
+bool start_wp_is_hardwired;
+bool start_wp_is_support;
+
+void waypoint_clear_start_wp_globals(entity pl, bool warn)
+{
+       start_wp_is_spawned = false;
+       start_wp_origin = '0 0 0';
+       pl.wp_locked = NULL;
+       start_wp_is_hardwired = false;
+       start_wp_is_support = false;
+       if (warn)
+               LOG_INFO("^xf80Start waypoint has been cleared.\n");
+}
+
+void waypoint_start_hardwiredlink(entity pl, bool at_crosshair)
+{
+       entity wp = pl.nearestwaypoint;
+       if (at_crosshair)
+       {
+               crosshair_trace_waypoints(pl);
+               wp = trace_ent;
+       }
+       string err = "";
+       if (start_wp_is_spawned && !start_wp_is_hardwired)
+               err = "can't hardwire while in the process of creating a special link";
+       else if (!wp)
+       {
+               if (at_crosshair)
+                       err = "couldn't find any waypoint at crosshair";
+               else
+                       err = "couldn't find any waypoint nearby";
+       }
+       else if (wp.wpflags & WPFLAGMASK_NORELINK)
+               err = "can't hardwire a waypoint with special links";
+
+       if (err == "")
+       {
+               start_wp_is_hardwired = true;
+               start_wp_is_spawned = true;
+               start_wp_origin = wp.origin;
+               pl.wp_locked = wp;
+               LOG_INFOF("^x80fWaypoint %s marked as hardwired link origin.\n", vtos(wp.origin));
+       }
+       else
+       {
+               start_wp_is_hardwired = false;
+               LOG_INFO("Error: ", err, "\n");
+       }
+}
+
+void waypoint_spawn_fromeditor(entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp)
 {
-       entity e;
+       if (WAYPOINT_VERSION < waypoint_version_loaded)
+       {
+               LOG_INFOF("^1Editing waypoints with a higher version number (%f) is not allowed.\n"
+                       "Update Xonotic to make them editable.", waypoint_version_loaded);
+               return;
+       }
+
+       entity e = NULL, jp = NULL;
        vector org = pl.origin;
+       if (at_crosshair)
+       {
+               crosshair_trace_waypoints(pl);
+               org = trace_endpos;
+               if (!trace_ent)
+                       org.z -= PL_MIN_CONST.z;
+               if (!(start_wp_is_hardwired || start_wp_is_support))
+                       IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
+                       {
+                               jp = it;
+                               break;
+                       });
+               if (!jp && !start_wp_is_spawned && trace_ent)
+               {
+                       if (trace_ent.wpflags & (WAYPOINTFLAG_JUMP))
+                               is_jump_wp = true;
+                       else if (trace_ent.wpflags & (WAYPOINTFLAG_SUPPORT))
+                               is_support_wp = true;
+               }
+       }
+       if (jp || is_jump_wp || is_support_wp)
+       {
+               if (start_wp_is_spawned)
+                       start_wp_is_spawned = false;
+               LOG_INFO("^xf80Spawning start waypoint...\n");
+       }
        int ctf_flags = havocbot_symmetry_origin_order;
        bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2)
                   || (autocvar_g_waypointeditor_symmetrical < 0));
@@ -358,7 +605,7 @@ void waypoint_spawn_fromeditor(entity pl)
                ctf_flags = 2;
        int wp_num = ctf_flags;
 
-       if(!PHYS_INPUT_BUTTON_CROUCH(pl))
+       if(!PHYS_INPUT_BUTTON_CROUCH(pl) && !at_crosshair && !is_jump_wp && !is_support_wp)
        {
                // snap waypoint to item's origin if close enough
                IL_EACH(g_items, true,
@@ -373,18 +620,169 @@ void waypoint_spawn_fromeditor(entity pl)
                });
        }
 
+       vector start_org = '0 0 0';
+       if (start_wp_is_spawned)
+       {
+               if (!start_wp_is_hardwired)
+                       LOG_INFO("^xf80Spawning destination waypoint...\n");
+               start_org = start_wp_origin;
+       }
+
+       // save org as it can be modified spawning symmetrycal waypoints
+       vector initial_origin = '0 0 0';
+       bool initial_origin_is_set = false;
+
        LABEL(add_wp);
-       e = waypoint_spawn(org, org, 0);
+
+       if (jp)
+       {
+               e = NULL;
+               IL_EACH(g_waypoints, (it.wpflags & WPFLAGMASK_NORELINK)
+                       && boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
+               {
+                       e = it; break;
+               });
+               if (!e)
+                       e = waypoint_spawn(jp.absmin - PL_MAX_CONST + '1 1 1', jp.absmax - PL_MIN_CONST + '-1 -1 -1', WAYPOINTFLAG_TELEPORT);
+               if (!pl.wp_locked)
+                       pl.wp_locked = e;
+       }
+       else if (is_jump_wp || is_support_wp)
+       {
+               int type_flag = (is_jump_wp) ? WAYPOINTFLAG_JUMP : WAYPOINTFLAG_SUPPORT;
+
+               entity wp_found = waypoint_get(org, org);
+               if (wp_found && !(wp_found.wpflags & type_flag))
+               {
+                       LOG_INFOF("Error: can't spawn a %s waypoint over an existent waypoint of a different type\n", (is_jump_wp) ? "Jump" : "Support");
+                       return;
+               }
+               e = waypoint_spawn(org, org, type_flag);
+               if (!pl.wp_locked)
+                       pl.wp_locked = e;
+       }
+       else
+               e = waypoint_spawn(org, org, (is_crouch_wp) ? WAYPOINTFLAG_CROUCH : 0);
        if(!e)
        {
                LOG_INFOF("Couldn't spawn waypoint at %v\n", org);
+               if (start_wp_is_spawned)
+                       waypoint_clear_start_wp_globals(pl, true);
                return;
        }
-       waypoint_schedulerelink(e);
-       bprint(strcat("Waypoint spawned at ", vtos(e.origin), "\n"));
-       if(sym)
+
+       if (!initial_origin_is_set)
+       {
+               initial_origin = e.origin;
+               initial_origin_is_set = true;
+       }
+
+       entity start_wp = NULL;
+       if (start_wp_is_spawned)
+       {
+               IL_EACH(g_waypoints, (start_wp_is_hardwired || (it.wpflags & WPFLAGMASK_NORELINK))
+                       && boxesoverlap(start_org, start_org, it.absmin, it.absmax),
+               {
+                       start_wp = it; break;
+               });
+               if(!start_wp)
+               {
+                       // should not happen
+                       LOG_INFOF("Couldn't find start waypoint at %v\n", start_org);
+                       waypoint_clear_start_wp_globals(pl, true);
+                       return;
+               }
+               if (start_wp_is_hardwired)
+               {
+                       if (waypoint_is_hardwiredlink(start_wp, e))
+                       {
+                               waypoint_unmark_hardwiredlink(start_wp, e);
+                               waypoint_removelink(start_wp, e);
+                               string s = strcat(vtos(start_wp.origin), "*", vtos(e.origin));
+                               LOG_INFOF("^x80fRemoved hardwired link %s.\n", s);
+                       }
+                       else
+                       {
+                               if (e.createdtime == time)
+                               {
+                                       LOG_INFO("Error: hardwired links can be created only between 2 existing (and unconnected) waypoints.\n");
+                                       waypoint_remove(e);
+                                       waypoint_clear_start_wp_globals(pl, true);
+                                       waypoint_spawn_fromeditor(pl, at_crosshair, is_jump_wp, is_crouch_wp, is_support_wp);
+                                       return;
+                               }
+                               if (start_wp == e)
+                               {
+                                       LOG_INFO("Error: start and destination waypoints coincide.\n");
+                                       waypoint_clear_start_wp_globals(pl, true);
+                                       return;
+                               }
+                               if (waypoint_islinked(start_wp, e))
+                               {
+                                       LOG_INFO("Error: waypoints are already linked.\n");
+                                       waypoint_clear_start_wp_globals(pl, true);
+                                       return;
+                               }
+                               waypoint_addlink(start_wp, e);
+                               waypoint_mark_hardwiredlink(start_wp, e);
+                               string s = strcat(vtos(start_wp.origin), "*", vtos(e.origin));
+                               LOG_INFOF("^x80fAdded hardwired link %s.\n", s);
+                       }
+               }
+               else
+               {
+                       if (start_wp_is_support)
+                       {
+                               if (e.SUPPORT_WP)
+                               {
+                                       LOG_INFOF("Waypoint %v has already a support waypoint, delete it first.\n", e.origin);
+                                       waypoint_clear_start_wp_globals(pl, true);
+                                       return;
+                               }
+                               // clear all links to e
+                               IL_EACH(g_waypoints, it != e,
+                               {
+                                       if (waypoint_islinked(it, e) && !waypoint_is_hardwiredlink(it, e))
+                                               waypoint_removelink(it, e);
+                               });
+                       }
+                       waypoint_addlink(start_wp, e);
+               }
+       }
+
+       if (!(jp || is_jump_wp || is_support_wp || start_wp_is_hardwired))
+               waypoint_schedulerelink(e);
+
+       string wp_type_str = waypoint_get_type_name(e);
+
+       bprint(strcat(wp_type_str, "^7 spawned at ", vtos(e.origin), "\n"));
+
+       if (start_wp_is_spawned)
+       {
+               pl.wp_locked = NULL;
+               if (!start_wp_is_hardwired)
+                       waypoint_schedulerelink(start_wp);
+               if (start_wp.wpflags & WAYPOINTFLAG_TELEPORT)
+               {
+                       if (start_wp.wp00_original == start_wp.wp00)
+                               start_wp.wpflags &= ~WAYPOINTFLAG_CUSTOM_JP;
+                       else
+                               start_wp.wpflags |= WAYPOINTFLAG_CUSTOM_JP;
+               }
+       }
+
+       if (sym)
        {
-               org = waypoint_getSymmetricalPoint(e.origin, ctf_flags);
+               org = waypoint_getSymmetricalPoint(org, ctf_flags);
+               if (jp)
+               {
+                       IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
+                       {
+                               jp = it; break;
+                       });
+               }
+               if (start_wp_is_spawned)
+                       start_org = waypoint_getSymmetricalPoint(start_org, ctf_flags);
                if (vdist(org - pl.origin, >, 32))
                {
                        if(wp_num > 2)
@@ -394,20 +792,52 @@ void waypoint_spawn_fromeditor(entity pl)
                        goto add_wp;
                }
        }
+       if (jp || is_jump_wp || is_support_wp)
+       {
+               if (!start_wp_is_spawned)
+               {
+                       // we've just created a custom jumppad waypoint
+                       // the next one created by the user will be the destination waypoint
+                       start_wp_is_spawned = true;
+                       start_wp_origin = initial_origin;
+                       if (is_support_wp)
+                               start_wp_is_support = true;
+               }
+       }
+       else if (start_wp_is_spawned)
+       {
+               waypoint_clear_start_wp_globals(pl, false);
+       }
 }
 
 void waypoint_remove(entity wp)
 {
        IL_EACH(g_waypoints, it != wp,
        {
+               if (it.SUPPORT_WP == wp)
+               {
+                       it.SUPPORT_WP = NULL;
+                       waypoint_schedulerelink(it); // restore incoming links
+               }
                if (waypoint_islinked(it, wp))
+               {
+                       if (waypoint_is_hardwiredlink(it, wp))
+                               waypoint_unmark_hardwiredlink(it, wp);
                        waypoint_removelink(it, wp);
+               }
        });
        delete(wp);
 }
 
 void waypoint_remove_fromeditor(entity pl)
 {
+       if (WAYPOINT_VERSION < waypoint_version_loaded)
+       {
+               LOG_INFOF("^1Editing waypoints with a higher version number (%f) is not allowed.\n"
+                       "Update Xonotic to make them editable.", waypoint_version_loaded);
+               return;
+       }
+
        entity e = navigation_findnearestwaypoint(pl, false);
 
        int ctf_flags = havocbot_symmetry_origin_order;
@@ -421,11 +851,17 @@ void waypoint_remove_fromeditor(entity pl)
 
        LABEL(remove_wp);
        if (!e) return;
-       if (e.wpflags & WAYPOINTFLAG_GENERATED) return;
 
-       if (e.wphardwired)
+       if (e.wpflags & WAYPOINTFLAG_GENERATED)
        {
-               LOG_INFO("^1Warning: ^7Removal of hardwired waypoints is not allowed in the editor. Please remove links from/to this waypoint (", vtos(e.origin), ") by hand from maps/", mapname, ".waypoints.hardwired\n");
+               if (start_wp_is_spawned)
+                       waypoint_clear_start_wp_globals(pl, true);
+               return;
+       }
+
+       if (waypoint_has_hardwiredlinks(e))
+       {
+               LOG_INFO("Can't remove a waypoint with hardwired links, remove links with \"wpeditor hardwire\" first\n");
                return;
        }
 
@@ -443,6 +879,7 @@ void waypoint_remove_fromeditor(entity pl)
        }
 
        bprint(strcat("Waypoint removed at ", vtos(e.origin), "\n"));
+       te_explosion(e.origin);
        waypoint_remove(e);
 
        if (sym && wp_sym)
@@ -454,11 +891,14 @@ void waypoint_remove_fromeditor(entity pl)
                        sym = false;
                goto remove_wp;
        }
+
+       if (start_wp_is_spawned)
+               waypoint_clear_start_wp_globals(pl, true);
 }
 
 void waypoint_removelink(entity from, entity to)
 {
-       if (from == to || (from.wpflags & WAYPOINTFLAG_NORELINK))
+       if (from == to || ((from.wpflags & WPFLAGMASK_NORELINK) && !(from.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT))))
                return;
 
        entity fromwp31_prev = from.wp31;
@@ -567,12 +1007,18 @@ float waypoint_getlinearcost(float dist)
                return dist / (autocvar_sv_maxspeed * 1.25);
        return dist / autocvar_sv_maxspeed;
 }
+
 float waypoint_getlinearcost_underwater(float dist)
 {
        // NOTE: underwater speed factor is hardcoded in the engine too, see SV_WaterMove
        return dist / (autocvar_sv_maxspeed * 0.7);
 }
 
+float waypoint_getlinearcost_crouched(float dist)
+{
+       return dist / (autocvar_sv_maxspeed * 0.5);
+}
+
 float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent)
 {
        bool submerged_from = navigation_check_submerged_state(from_ent, from);
@@ -581,19 +1027,32 @@ float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_
        if (submerged_from && submerged_to)
                return waypoint_getlinearcost_underwater(vlen(to - from));
 
+       if ((from_ent.wpflags & WAYPOINTFLAG_CROUCH) && (to_ent.wpflags & WAYPOINTFLAG_CROUCH))
+               return waypoint_getlinearcost_crouched(vlen(to - from));
+
        float c = waypoint_getlinearcost(vlen(to - from));
 
        float height = from.z - to.z;
        if(height > jumpheight_vec.z && autocvar_sv_gravity > 0)
        {
-               float height_cost = sqrt(height / (autocvar_sv_gravity / 2));
+               float height_cost; // fall cost
+               if (from_ent.wpflags & WAYPOINTFLAG_JUMP)
+                       height_cost = jumpheight_time + sqrt((height + jumpheight_vec.z) / (autocvar_sv_gravity / 2));
+               else
+                       height_cost = sqrt(height / (autocvar_sv_gravity / 2));
                c = waypoint_getlinearcost(vlen(vec2(to - from))); // xy distance cost
                if(height_cost > c)
                        c = height_cost;
        }
 
+       // consider half path underwater
        if (submerged_from || submerged_to)
                return (c + waypoint_getlinearcost_underwater(vlen(to - from))) / 2;
+
+       // consider half path crouched
+       if ((from_ent.wpflags & WAYPOINTFLAG_CROUCH) || (to_ent.wpflags & WAYPOINTFLAG_CROUCH))
+               return (c + waypoint_getlinearcost_crouched(vlen(to - from))) / 2;
+
        return c;
 }
 
@@ -624,7 +1083,7 @@ void waypoint_addlink_customcost(entity from, entity to, float c)
 {
        if (from == to || waypoint_islinked(from, to))
                return;
-       if (c == -1 && (from.wpflags & WAYPOINTFLAG_NORELINK))
+       if (c == -1 && (from.wpflags & WPFLAGMASK_NORELINK) && !(from.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT)))
                return;
 
        if(c == -1)
@@ -667,7 +1126,13 @@ void waypoint_addlink_customcost(entity from, entity to, float c)
 
 void waypoint_addlink(entity from, entity to)
 {
-       waypoint_addlink_customcost(from, to, -1);
+       if ((from.wpflags & WPFLAGMASK_NORELINK) && !(from.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT)))
+               waypoint_addlink_for_custom_jumppad(from, to);
+       else
+               waypoint_addlink_customcost(from, to, -1);
+
+       if (from.wpflags & WAYPOINTFLAG_SUPPORT)
+               to.SUPPORT_WP = from;
 }
 
 // relink this spawnfunc_waypoint
@@ -690,8 +1155,10 @@ void waypoint_think(entity this)
        {
                if (boxesoverlap(this.absmin, this.absmax, it.absmin, it.absmax))
                {
-                       waypoint_addlink(this, it);
-                       waypoint_addlink(it, this);
+                       if (!(this.wpflags & WPFLAGMASK_NORELINK))
+                               waypoint_addlink(this, it);
+                       if (!(it.wpflags & WPFLAGMASK_NORELINK))
+                               waypoint_addlink(it, this);
                }
                else
                {
@@ -711,7 +1178,22 @@ void waypoint_think(entity this)
 
                        dv = ev - sv;
                        dv.z = 0;
-                       if(vdist(dv, >=, 1050)) // max search distance in XY
+                       int maxdist = 1050;
+                       vector m1 = PL_MIN_CONST;
+                       vector m2 = PL_MAX_CONST;
+
+                       if ((this.wpflags & WAYPOINTFLAG_CROUCH) || (it.wpflags & WAYPOINTFLAG_CROUCH))
+                       {
+                               m1 = PL_CROUCH_MIN_CONST;
+                               m2 = PL_CROUCH_MAX_CONST;
+                               // links from crouch wp to normal wp (and viceversa) are very short to avoid creating many links
+                               // that would be wasted due to rough travel cost calculation (the longer link is, the higher cost is)
+                               // links from crouch wp to crouch wp can be as long as normal links
+                               if (!((this.wpflags & WAYPOINTFLAG_CROUCH) && (it.wpflags & WAYPOINTFLAG_CROUCH)))
+                                       maxdist = 100;
+                       }
+
+                       if (vdist(dv, >=, maxdist)) // max search distance in XY
                        {
                                ++relink_lengthculled;
                                continue;
@@ -721,30 +1203,45 @@ void waypoint_think(entity this)
 
                        //traceline(this.origin, it.origin, false, NULL);
                        //if (trace_fraction == 1)
-                       if (this.wpisbox)
+                       if (this.wpisbox || (this.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT)) // forbid outgoing links
+                               || it.SUPPORT_WP) // forbid incoming links
+                       {
                                relink_walkculled += 0.5;
+                       }
                        else
                        {
-                               if (tracewalk(this, sv, PL_MIN_CONST, PL_MAX_CONST, ev2, ev2_height, MOVE_NOMONSTERS))
+                               if (tracewalk(this, sv, m1, m2, ev2, ev2_height, MOVE_NOMONSTERS))
                                        waypoint_addlink(this, it);
                                else
                                        relink_walkculled += 0.5;
                        }
 
-                       if (it.wpisbox)
+                       // reverse direction
+                       if (it.wpisbox || (it.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT)) // forbid incoming links
+                               || this.SUPPORT_WP) // forbid outgoing links
+                       {
                                relink_walkculled += 0.5;
+                       }
                        else
                        {
-                               if (tracewalk(this, ev, PL_MIN_CONST, PL_MAX_CONST, sv2, sv2_height, MOVE_NOMONSTERS))
+                               if (tracewalk(this, ev, m1, m2, sv2, sv2_height, MOVE_NOMONSTERS))
                                        waypoint_addlink(it, this);
                                else
                                        relink_walkculled += 0.5;
                        }
                }
        });
+
+       // waypoint_clearlinks preserves references to old hardwired links (.wphwXX links)
+       // so they can be restored here when a wp is spawned over an existing one
+       waypoint_restore_hardwiredlinks(this);
+
        navigation_testtracewalk = 0;
        this.wplinked = true;
        this.dphitcontentsmask = dphitcontentsmask_save;
+
+       setthink(this, func_null);
+       this.nextthink = 0;
 }
 
 void waypoint_clearlinks(entity wp)
@@ -761,6 +1258,8 @@ void waypoint_clearlinks(entity wp)
        wp.wp16mincost = wp.wp17mincost = wp.wp18mincost = wp.wp19mincost = wp.wp20mincost = wp.wp21mincost = wp.wp22mincost = wp.wp23mincost = f;
        wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f;
 
+       // don't remove references to hardwired links (.wphwXX fields)
+
        wp.wplinked = false;
 }
 
@@ -775,7 +1274,7 @@ void waypoint_schedulerelink(entity wp)
        wp.enemy = NULL;
        if (!(wp.wpflags & WAYPOINTFLAG_PERSONAL))
                wp.owner = NULL;
-       if (!(wp.wpflags & WAYPOINTFLAG_NORELINK))
+       if (!(wp.wpflags & WPFLAGMASK_NORELINK))
                waypoint_clearlinks(wp);
        // schedule an actual relink on next frame
        setthink(wp, waypoint_think);
@@ -803,7 +1302,7 @@ void waypoint_schedulerelinkall()
        {
                waypoint_schedulerelink(it);
        });
-       waypoint_load_links_hardwired();
+       waypoint_load_hardwiredlinks();
 }
 
 #define GET_GAMETYPE_EXTENSION() ((g_race) ? ".race" : "")
@@ -933,6 +1432,8 @@ bool waypoint_load_links()
 
                ++c;
                waypoint_addlink(wp_from, wp_to);
+               if (wp_from.wp00_original && wp_from.wp00_original != wp_from.wp00)
+                       wp_from.wpflags |= WAYPOINTFLAG_CUSTOM_JP;
        }
 
        fclose(file);
@@ -955,7 +1456,7 @@ bool waypoint_load_links()
        return true;
 }
 
-void waypoint_load_or_remove_links_hardwired(bool removal_mode)
+void waypoint_load_hardwiredlinks()
 {
        string s;
        float file, tokens, c = 0, found;
@@ -978,11 +1479,11 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode)
 
        if (file < 0)
        {
-               if(!removal_mode)
-                       LOG_TRACE("waypoint links load from ", filename, " failed");
+               LOG_TRACE("waypoint links load from ", filename, " failed");
                return;
        }
 
+       bool is_special = false;
        while ((s = fgets(file)))
        {
                if(substring(s, 0, 2)=="//")
@@ -991,6 +1492,14 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode)
                if(substring(s, 0, 1)=="#")
                        continue;
 
+               // special links start with *, so old xonotic versions don't load them
+               is_special = false;
+               if (substring(s, 0, 1) == "*")
+               {
+                       is_special = true;
+                       s = substring(s, 1, -1);
+               }
+
                tokens = tokenizebyseparator(s, "*");
 
                if (tokens!=2)
@@ -1017,8 +1526,8 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode)
 
                        if(!found)
                        {
-                               if(!removal_mode)
-                                       LOG_INFO("NOTICE: Can not find origin waypoint for the hardwired link ", s, ". Path skipped");
+                               s = strcat(((is_special) ? "special link " : "hardwired link "), s);
+                               LOG_INFO("NOTICE: Can not find origin waypoint of the ", s, ". Path skipped");
                                continue;
                        }
                }
@@ -1039,29 +1548,28 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode)
 
                if(!found)
                {
-                       if(!removal_mode)
-                               LOG_INFO("NOTICE: Can not find destination waypoint for the hardwired link ", s, ". Path skipped");
+                       s = strcat(((is_special) ? "special link " : "hardwired link "), s);
+                       LOG_INFO("NOTICE: Can not find destination waypoint of the ", s, ". Path skipped");
                        continue;
                }
 
                ++c;
-               if(removal_mode)
+
+               if (!is_special)
                {
-                       waypoint_removelink(wp_from, wp_to);
-                       continue;
+                       waypoint_addlink(wp_from, wp_to);
+                       waypoint_mark_hardwiredlink(wp_from, wp_to);
+               } else if (wp_from.wpflags & WPFLAGMASK_NORELINK
+                       && ((wp_from.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT))
+                               || (wp_from.wpisbox && wp_from.wpflags & WAYPOINTFLAG_TELEPORT)))
+               {
+                       waypoint_addlink(wp_from, wp_to);
                }
-
-               waypoint_addlink(wp_from, wp_to);
-               wp_from.wphardwired = true;
-               wp_to.wphardwired = true;
-               waypoint_setupmodel(wp_from);
-               waypoint_setupmodel(wp_to);
        }
 
        fclose(file);
 
-       LOG_TRACE(((removal_mode) ? "unloaded " : "loaded "),
-               ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired");
+       LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired");
 }
 
 entity waypoint_get_link(entity w, float i)
@@ -1104,12 +1612,63 @@ entity waypoint_get_link(entity w, float i)
        }
 }
 
+// Save all hardwired waypoint links to a file
+void waypoint_save_hardwiredlinks()
+{
+       string gt_ext = GET_GAMETYPE_EXTENSION();
+
+       string filename = sprintf("maps/%s.waypoints.hardwired", strcat(mapname, gt_ext));
+       int file = fopen(filename, FILE_WRITE);
+       if (file < 0)
+       {
+               LOG_TRACE("waypoint hardwired links ", filename, " creation failed");
+               return;
+       }
+
+       // write hardwired links to file
+       int count = 0;
+       fputs(file, "// HARDWIRED LINKS\n");
+       IL_EACH(g_waypoints, waypoint_has_hardwiredlinks(it),
+       {
+               for (int j = 0; j < 32; ++j)
+               {
+                       entity link = waypoint_get_link(it, j);
+                       if (waypoint_is_hardwiredlink(it, link))
+                       {
+                               // NOTE: vtos rounds vector components to 1 decimal place
+                               string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n");
+                               fputs(file, s);
+                               ++count;
+                       }
+               }
+       });
+
+       // write special links to file
+       int count2 = 0;
+       fputs(file, "\n// SPECIAL LINKS\n");
+       IL_EACH(g_waypoints, it.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT | WAYPOINTFLAG_CUSTOM_JP),
+       {
+               for (int j = 0; j < 32; ++j)
+               {
+                       entity link = waypoint_get_link(it, j);
+                       if (link)
+                       {
+                               // NOTE: vtos rounds vector components to 1 decimal place
+                               string s = strcat("*", vtos(it.origin), "*", vtos(link.origin), "\n");
+                               fputs(file, s);
+                               ++count2;
+                       }
+               }
+       });
+
+       fclose(file);
+
+       LOG_INFOF("saved %d hardwired links and %d special links to %s", count, count2, filename);
+}
+
 // Save all waypoint links to a file
 void waypoint_save_links()
 {
-       // temporarily remove hardwired links so they don't get saved among normal links
-       waypoint_remove_links_hardwired();
-
        string gt_ext = GET_GAMETYPE_EXTENSION();
 
        string filename = sprintf("maps/%s.waypoints.cache", strcat(mapname, gt_ext));
@@ -1125,12 +1684,12 @@ void waypoint_save_links()
                fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
 
        int c = 0;
-       IL_EACH(g_waypoints, true,
+       IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT | WAYPOINTFLAG_CUSTOM_JP)),
        {
                for(int j = 0; j < 32; ++j)
                {
                        entity link = waypoint_get_link(it, j);
-                       if(link)
+                       if (link && !waypoint_is_hardwiredlink(it, link))
                        {
                                // NOTE: vtos rounds vector components to 1 decimal place
                                string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n");
@@ -1144,13 +1703,17 @@ void waypoint_save_links()
        botframe_cachedwaypointlinks = true;
 
        LOG_INFOF("saved %d waypoint links to %s", c, filename);
-
-       waypoint_load_links_hardwired();
 }
 
 // save waypoints to gamedir/data/maps/mapname.waypoints
 void waypoint_saveall()
 {
+       if (WAYPOINT_VERSION < waypoint_version_loaded)
+       {
+               LOG_INFOF("^1Overwriting waypoints with a higher version number (%f) is not allowed.\n"
+                       "Update Xonotic to make them editable.", waypoint_version_loaded);
+               return;
+       }
        string gt_ext = GET_GAMETYPE_EXTENSION();
 
        string filename = sprintf("maps/%s.waypoints", strcat(mapname, gt_ext));
@@ -1216,8 +1779,11 @@ void waypoint_saveall()
        });
        fclose(file);
        waypoint_save_links();
+       waypoint_save_hardwiredlinks();
+
        botframe_loadedforcedlinks = false;
 
+       waypoint_version_loaded = WAYPOINT_VERSION;
        LOG_INFOF("saved %d waypoints to %s", c, filename);
 }
 
@@ -1225,7 +1791,7 @@ void waypoint_saveall()
 float waypoint_loadall()
 {
        string s;
-       float file, cwp, cwb, fl;
+       int file, cwp, cwb, fl;
        vector m1, m2;
        cwp = 0;
        cwb = 0;
@@ -1292,6 +1858,7 @@ float waypoint_loadall()
                if (!s)
                        break;
                fl = stof(s);
+               fl &= ~WAYPOINTFLAG_NORELINK__DEPRECATED;
                waypoint_spawn(m1, m2, fl);
                if (m1 == m2)
                        cwp = cwp + 1;
@@ -1299,10 +1866,12 @@ float waypoint_loadall()
                        cwb = cwb + 1;
        }
        fclose(file);
+       waypoint_version_loaded = ver;
        LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints");
 
        if (autocvar_g_waypointeditor && autocvar_g_waypointeditor_symmetrical_allowload)
        {
+               string sym_str = "";
                cvar_set("g_waypointeditor_symmetrical", ftos(sym));
                if (sym == 1 && sym_param3 < 2)
                        cvar_set("g_waypointeditor_symmetrical_order", "0"); // make sure this is reset if not loaded
@@ -1317,19 +1886,25 @@ float waypoint_loadall()
                                cvar_set("g_waypointeditor_symmetrical_origin", params);
                        }
                        cvar_set("g_waypointeditor_symmetrical_order", ftos(sym_param3));
-                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
+                       sym_str = strcat(ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
                }
                else if (sym == -2)
                {
                        string params = strcat(ftos(sym_param1), " ", ftos(sym_param2));
                        cvar_set("g_waypointeditor_symmetrical_axis", params);
-                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with axis ", params);
+                       sym_str = strcat(ftos(sym), " with axis ", params);
                }
                else
-                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym));
+                       sym_str = ftos(sym);
+               if (sym_str != "")
+                       LOG_INFO("Waypoint editor: loaded symmetry ", sym_str);
                LOG_INFO(strcat("g_waypointeditor_symmetrical", " has been set to ", cvar_string("g_waypointeditor_symmetrical")));
        }
 
+       if (WAYPOINT_VERSION < waypoint_version_loaded)
+               LOG_INFOF("^1Editing waypoints with a higher version number (%f) is not allowed.\n"
+                       "Update Xonotic to make them editable.", waypoint_version_loaded);
+
        return cwp + cwb;
 }
 
@@ -1390,9 +1965,10 @@ void waypoint_spawnforteleporter_boxes(entity e, int teleport_flag, vector org1,
 {
        entity w;
        entity dw;
-       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | teleport_flag | WAYPOINTFLAG_NORELINK);
+       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | teleport_flag);
        dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
        // one way link to the destination
+       w.wp00_original = dw;
        w.wp00 = dw;
        w.wp00mincost = timetaken; // this is just for jump pads
        // the teleporter's nearest spawnfunc_waypoint is this one
@@ -1469,7 +2045,7 @@ void waypoint_showlink(entity wp1, entity wp2, int display_type)
        if (!(wp1 && wp2))
                return;
 
-       if (wp1.wphardwired && wp2.wphardwired)
+       if (waypoint_is_hardwiredlink(wp1, wp2) || (wp1.wpflags & (WAYPOINTFLAG_JUMP | WAYPOINTFLAG_SUPPORT | WAYPOINTFLAG_CUSTOM_JP)))
                te_beam(NULL, wp1.origin, wp2.origin);
        else if (display_type == 1)
                te_lightning2(NULL, wp1.origin, wp2.origin);
@@ -1486,22 +2062,22 @@ void waypoint_showlinks_to(entity wp, int display_type)
 
 void waypoint_showlinks_from(entity wp, int display_type)
 {
-       waypoint_showlink(wp.wp00, wp, display_type); waypoint_showlink(wp.wp16, wp, display_type);
-       waypoint_showlink(wp.wp01, wp, display_type); waypoint_showlink(wp.wp17, wp, display_type);
-       waypoint_showlink(wp.wp02, wp, display_type); waypoint_showlink(wp.wp18, wp, display_type);
-       waypoint_showlink(wp.wp03, wp, display_type); waypoint_showlink(wp.wp19, wp, display_type);
-       waypoint_showlink(wp.wp04, wp, display_type); waypoint_showlink(wp.wp20, wp, display_type);
-       waypoint_showlink(wp.wp05, wp, display_type); waypoint_showlink(wp.wp21, wp, display_type);
-       waypoint_showlink(wp.wp06, wp, display_type); waypoint_showlink(wp.wp22, wp, display_type);
-       waypoint_showlink(wp.wp07, wp, display_type); waypoint_showlink(wp.wp23, wp, display_type);
-       waypoint_showlink(wp.wp08, wp, display_type); waypoint_showlink(wp.wp24, wp, display_type);
-       waypoint_showlink(wp.wp09, wp, display_type); waypoint_showlink(wp.wp25, wp, display_type);
-       waypoint_showlink(wp.wp10, wp, display_type); waypoint_showlink(wp.wp26, wp, display_type);
-       waypoint_showlink(wp.wp11, wp, display_type); waypoint_showlink(wp.wp27, wp, display_type);
-       waypoint_showlink(wp.wp12, wp, display_type); waypoint_showlink(wp.wp28, wp, display_type);
-       waypoint_showlink(wp.wp13, wp, display_type); waypoint_showlink(wp.wp29, wp, display_type);
-       waypoint_showlink(wp.wp14, wp, display_type); waypoint_showlink(wp.wp30, wp, display_type);
-       waypoint_showlink(wp.wp15, wp, display_type); waypoint_showlink(wp.wp31, wp, display_type);
+       waypoint_showlink(wp, wp.wp00, display_type); waypoint_showlink(wp, wp.wp16, display_type);
+       waypoint_showlink(wp, wp.wp01, display_type); waypoint_showlink(wp, wp.wp17, display_type);
+       waypoint_showlink(wp, wp.wp02, display_type); waypoint_showlink(wp, wp.wp18, display_type);
+       waypoint_showlink(wp, wp.wp03, display_type); waypoint_showlink(wp, wp.wp19, display_type);
+       waypoint_showlink(wp, wp.wp04, display_type); waypoint_showlink(wp, wp.wp20, display_type);
+       waypoint_showlink(wp, wp.wp05, display_type); waypoint_showlink(wp, wp.wp21, display_type);
+       waypoint_showlink(wp, wp.wp06, display_type); waypoint_showlink(wp, wp.wp22, display_type);
+       waypoint_showlink(wp, wp.wp07, display_type); waypoint_showlink(wp, wp.wp23, display_type);
+       waypoint_showlink(wp, wp.wp08, display_type); waypoint_showlink(wp, wp.wp24, display_type);
+       waypoint_showlink(wp, wp.wp09, display_type); waypoint_showlink(wp, wp.wp25, display_type);
+       waypoint_showlink(wp, wp.wp10, display_type); waypoint_showlink(wp, wp.wp26, display_type);
+       waypoint_showlink(wp, wp.wp11, display_type); waypoint_showlink(wp, wp.wp27, display_type);
+       waypoint_showlink(wp, wp.wp12, display_type); waypoint_showlink(wp, wp.wp28, display_type);
+       waypoint_showlink(wp, wp.wp13, display_type); waypoint_showlink(wp, wp.wp29, display_type);
+       waypoint_showlink(wp, wp.wp14, display_type); waypoint_showlink(wp, wp.wp30, display_type);
+       waypoint_showlink(wp, wp.wp15, display_type); waypoint_showlink(wp, wp.wp31, display_type);
 }
 
 void crosshair_trace_waypoints(entity pl)
@@ -1512,15 +2088,18 @@ void crosshair_trace_waypoints(entity pl)
                        setsize(it, '-16 -16 -16', '16 16 16');
        });
 
-       crosshair_trace(pl);
+       WarpZone_crosshair_trace(pl);
 
        IL_EACH(g_waypoints, true, {
                it.solid = SOLID_TRIGGER;
                if (!it.wpisbox)
                        setsize(it, '0 0 0', '0 0 0');
        });
+
        if (trace_ent.classname != "waypoint")
                trace_ent = NULL;
+       else if (!trace_ent.wpisbox)
+               trace_endpos = trace_ent.origin;
 }
 
 void botframe_showwaypointlinks()
@@ -1535,8 +2114,6 @@ void botframe_showwaypointlinks()
                        it.wp_aimed = NULL;
                if (wasfreed(it.wp_locked))
                        it.wp_locked = NULL;
-               if (PHYS_INPUT_BUTTON_USE(it))
-                       it.wp_locked = it.wp_aimed;
                entity head = it.wp_locked;
                if (!head)
                        head = navigation_findnearestwaypoint(it, false);
@@ -1544,7 +2121,7 @@ void botframe_showwaypointlinks()
                it.nearestwaypointtimeout = time + 2; // while I'm at it...
                if (IS_ONGROUND(it) || it.waterlevel > WATERLEVEL_NONE || it.wp_locked)
                        display_type = 1; // default
-               else if(head && (head.wphardwired))
+               else if(waypoint_has_hardwiredlinks(head))
                        display_type = 2; // only hardwired
 
                if (display_type)
@@ -1571,13 +2148,14 @@ void botframe_showwaypointlinks()
                                wp = trace_ent;
                                if (wp != it.wp_aimed)
                                {
-                                       str = sprintf("\necho ^2WP info^7: entity: %d, flags: %d, origin: '%s'\n", etof(wp), wp.wpflags, vtos(wp.origin));
+                                       string wp_type_str = waypoint_get_type_name(wp);
+                                       str = sprintf("\necho Entity %d: %s^7, flags: %d, origin: %s\n", etof(wp), wp_type_str, wp.wpflags, vtos(wp.origin));
                                        if (wp.wpisbox)
-                                               str = strcat(str, sprintf("echo \" absmin: '%s', absmax: '%s'\"\n", vtos(wp.absmin), vtos(wp.absmax)));
+                                               str = strcat(str, sprintf("echo \" absmin: %s, absmax: %s\"\n", vtos(wp.absmin), vtos(wp.absmax)));
                                        stuffcmd(it, str);
-                                       str = sprintf("entity: %d\nflags: %d\norigin: \'%s\'", etof(wp), wp.wpflags, vtos(wp.origin));
+                                       str = sprintf("Entity %d: %s^7\nflags: %d\norigin: %s", etof(wp), wp_type_str, wp.wpflags, vtos(wp.origin));
                                        if (wp.wpisbox)
-                                               str = strcat(str, sprintf(" \nabsmin: '%s'\nabsmax: '%s'", vtos(wp.absmin), vtos(wp.absmax)));
+                                               str = strcat(str, sprintf(" \nabsmin: %s\nabsmax: %s", vtos(wp.absmin), vtos(wp.absmax)));
                                        debug_text_3d(wp.origin, str, 0, 7, '0 0 0');
                                }
                        }
@@ -1645,7 +2223,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                }
 
                float bestdist = maxdist;
-               IL_EACH(g_waypoints, it != wp && !(it.wpflags & WAYPOINTFLAG_NORELINK),
+               IL_EACH(g_waypoints, it != wp && !(it.wpflags & WPFLAGMASK_NORELINK),
                {
                        float d = vlen(wp.origin - it.origin) + vlen(it.origin - porg);
                        if(d < bestdist)
index 0b69dcbb8bca3e80fa9d543c5fcab6305e1f3b8c..25356446a4d1c05d40ece80c5e6f81f64cbfab7e 100644 (file)
@@ -6,7 +6,8 @@
 // increase by 0.01 when changes require only waypoint relinking
 // increase by 1 when changes require to manually edit waypoints
 // max 2 decimal places, always specified
-const float WAYPOINT_VERSION = 1.02;
+const float WAYPOINT_VERSION = 1.04;
+float waypoint_version_loaded;
 string waypoint_time;
 
 // fields you can query using prvm_global server to get some statistics about waypoint linking culling
@@ -21,23 +22,42 @@ float botframe_cachedwaypointlinks;
 .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;
 
+// used by jumppads to store original destination wp, used in case it gets changed in the editor
+.entity wp00_original;
+
 .float wp00mincost, wp01mincost, wp02mincost, wp03mincost, wp04mincost, wp05mincost, wp06mincost, wp07mincost;
 .float wp08mincost, wp09mincost, wp10mincost, wp11mincost, wp12mincost, wp13mincost, wp14mincost, wp15mincost;
 .float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost;
 .float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
 
-.float wpfire, wpcost, wpconsidered, wpisbox, wplinked, wphardwired;
+// hardwired links are saved to the .wpXX fields among normal links
+// AND to the supporting .wphwXX fields to allow identifying them precisely
+// these links are not sorted, unlike normal links
+.entity wphw00, wphw01, wphw02, wphw03, wphw04, wphw05, wphw06, wphw07;
+
+.float wpcost;
+.int wpfire, wpconsidered, wpisbox, wplinked;
 .int wpflags;
 .entity wp_aimed;
 .entity wp_locked;
 
 .vector wpnearestpoint;
 
+// holds reference to the support waypoint, if any
+.entity goalentity;
+#define SUPPORT_WP goalentity
+
 /*
  * Functions
  */
 
 spawnfunc(waypoint);
+
+bool waypoint_has_hardwiredlinks(entity wp);
+bool waypoint_is_hardwiredlink(entity wp_from, entity wp_to);
+void waypoint_mark_hardwiredlink(entity wp_from, entity wp_to);
+void waypoint_unmark_hardwiredlink(entity wp_from, entity wp_to);
+
 void waypoint_removelink(entity from, entity to);
 int waypoint_getlinknum(entity from, entity to);
 bool waypoint_islinked(entity from, entity to);
@@ -66,11 +86,9 @@ void botframe_showwaypointlinks();
 
 float waypoint_loadall();
 bool waypoint_load_links();
-#define waypoint_load_links_hardwired() waypoint_load_or_remove_links_hardwired(false)
-#define waypoint_remove_links_hardwired() waypoint_load_or_remove_links_hardwired(true)
-void waypoint_load_or_remove_links_hardwired(bool removal_mode);
+void waypoint_load_hardwiredlinks();
 
-void waypoint_spawn_fromeditor(entity pl);
+void waypoint_spawn_fromeditor(entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp);
 entity waypoint_spawn(vector m1, vector m2, float f);
 entity waypoint_spawnpersonal(entity this, vector position);
 
index bdca146c2e549128e2e208fec27f8b118e091af4..a7f8e99f1d7cb7bdc9c9cc6780aae9f5d4fd4883 100644 (file)
@@ -39,6 +39,6 @@ void waypoint_spawnforitem(entity e) { }
 void waypoint_spawnforitem_force(entity e, vector org) { }
 void waypoint_spawnforteleporter(entity e, vector destination, float timetaken, entity tracetest_ent) { }
 void waypoint_spawnforteleporter_wz(entity e, entity tracetest_ent) { }
-void waypoint_spawn_fromeditor(entity pl) { }
+void waypoint_spawn_fromeditor(entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp) { }
 entity waypoint_spawn(vector m1, vector m2, float f) { return NULL; }
 #endif
index c2dbb741137651e6d9136febd727661abd765c8b..1acab9c00535d647e18a26f1ba35ff55d0ba7cf2 100644 (file)
@@ -161,6 +161,8 @@ float CheatImpulse(entity this, int imp)
                        SetResource(this.personal, RES_HEALTH, max(1, GetResource(this, RES_HEALTH)));
                        SetResource(this.personal, RES_ARMOR, GetResource(this, RES_ARMOR));
                        STAT(WEAPONS, this.personal) = STAT(WEAPONS, this);
+                       STAT(BUFFS, this.personal) = STAT(BUFFS, this);
+                       STAT(BUFF_TIME, this.personal) = STAT(BUFF_TIME, this);
                        this.personal.items = this.items;
                        this.personal.pauserotarmor_finished = this.pauserotarmor_finished;
                        this.personal.pauserothealth_finished = this.pauserothealth_finished;
@@ -220,6 +222,8 @@ float CheatImpulse(entity this, int imp)
                                SetResource(this, RES_HEALTH, GetResource(this.personal, RES_HEALTH));
                                SetResource(this, RES_ARMOR, GetResource(this.personal, RES_ARMOR));
                                STAT(WEAPONS, this) = STAT(WEAPONS, this.personal);
+                               STAT(BUFFS, this) = STAT(BUFFS, this.personal);
+                               STAT(BUFF_TIME, this) = STAT(BUFF_TIME, this.personal);
                                this.items = this.personal.items;
                                this.pauserotarmor_finished = time + this.personal.pauserotarmor_finished - this.personal.teleport_time;
                                this.pauserothealth_finished = time + this.personal.pauserothealth_finished - this.personal.teleport_time;
index 639717a901920b53c96339daebbeae95465b7511..98616a76341f76ac901e838fdd7b81cb39478911 100644 (file)
@@ -40,6 +40,7 @@
 #include "../common/mapobjects/teleporters.qh"
 #include "../common/mapobjects/target/spawnpoint.qh"
 #include <common/mapobjects/trigger/counter.qh>
+#include <common/mapobjects/trigger/swamp.qh>
 
 #include "../common/vehicles/all.qh"
 
@@ -604,7 +605,7 @@ void PutPlayerInServer(entity this)
                this.pauseregen_finished += f;
        }
 
-       this.damageforcescale = 2;
+       this.damageforcescale = autocvar_g_player_damageforcescale;
        this.death_time = 0;
        this.respawn_flags = 0;
        this.respawn_time = 0;
@@ -640,6 +641,10 @@ void PutPlayerInServer(entity this)
        STAT(REVIVE_PROGRESS, this) = 0;
        this.revival_time = 0;
 
+       // TODO: we can't set these in the PlayerSpawn hook since the target code is called before it!
+       STAT(BUFFS, this) = 0;
+       STAT(BUFF_TIME, this) = 0;
+
        this.air_finished = time + 12;
        this.waterlevel = WATERLEVEL_NONE;
        this.watertype = CONTENT_EMPTY;
@@ -678,6 +683,9 @@ void PutPlayerInServer(entity this)
        if(this.conveyor)
                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;
        STAT(HUD, this) = HUD_NORMAL;
 
        this.event_damage = PlayerDamage;
@@ -1034,7 +1042,6 @@ string getwelcomemessage(entity this)
 
        string versionmessage = GetClientVersionMessage(this);
        string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
-       s = strcat(s, "^8\nCurrent map: ^2", GetMapname(), "^8\n");
 
        if(modifications != "")
                s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
@@ -1610,7 +1617,7 @@ void player_regen(entity this)
                        this.event_damage(this, this, this, 1, DEATH_ROT.m_id, DMG_NOWEP, this.origin, '0 0 0');
        }
 
-       if (!(this.items & IT_UNLIMITED_WEAPON_AMMO))
+       if (!(this.items & IT_UNLIMITED_AMMO))
        {
                float minf, maxf, limitf;
 
@@ -1676,6 +1683,7 @@ void SpectateCopy(entity this, entity spectatee)
        this.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
        SetResourceExplicit(this, RES_HEALTH, GetResource(spectatee, RES_HEALTH));
        CS(this).impulse = 0;
+       this.disableclientprediction = 1; // no need to run prediction on a spectator
        this.items = spectatee.items;
        STAT(LAST_PICKUP, this) = STAT(LAST_PICKUP, spectatee);
        STAT(HIT_TIME, this) = STAT(HIT_TIME, spectatee);
@@ -2045,12 +2053,21 @@ void PrintWelcomeMessage(entity this)
        {
                if(PHYS_INPUT_BUTTON_INFO(this)) // BUTTON_INFO hides initial MOTD
                        CS(this).motd_actived_time = -2; // wait until BUTTON_INFO gets released
-               else if(CS(this).motd_actived_time == -2 || IS_PLAYER(this) || IS_SPEC(this))
+               else if (CS(this).motd_actived_time == -2)
                {
                        // instantly hide MOTD
                        CS(this).motd_actived_time = 0;
                        Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
                }
+               else if (IS_PLAYER(this) || IS_SPEC(this))
+               {
+                       // FIXME occasionally for some reason MOTD never goes away
+                       // delay MOTD removal a little bit in the hope it fixes this bug
+                       if (CS(this).motd_actived_time == -1) // MOTD marked to fade away as soon as client becomes player or spectator
+                               CS(this).motd_actived_time = -(5 + floor(random() * 10)); // add small delay
+                       else //if (CS(this).motd_actived_time < -2)
+                               CS(this).motd_actived_time++;
+               }
        }
 }
 
@@ -2178,6 +2195,8 @@ bool PlayerThink(entity this)
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
+                       if(WEP_CVAR(vortex, charge_always))
+                               W_Vortex_Charge(this, weaponentity, frametime);
                        W_WeaponFrame(this, weaponentity);
                }
 
@@ -2393,11 +2412,11 @@ void PlayerPreThink (entity this)
        if (this.netname == "" || this.netname != CS(this).netname_previous)
        {
                bool assume_unchanged = (CS(this).netname_previous == "");
-               if (autocvar_name_maxlength > 0 && strlennocol(this.netname) > autocvar_name_maxlength)
+               if (autocvar_sv_name_maxlength > 0 && strlennocol(this.netname) > autocvar_sv_name_maxlength)
                {
-                       int new_length = textLengthUpToLength(this.netname, autocvar_name_maxlength, strlennocol);
+                       int new_length = textLengthUpToLength(this.netname, autocvar_sv_name_maxlength, strlennocol);
                        this.netname = strzone(strcat(substring(this.netname, 0, new_length), "^7"));
-                       sprint(this, sprintf("Warning: your name is longer than %d characters, it has been truncated.\n", autocvar_name_maxlength));
+                       sprint(this, sprintf("Warning: your name is longer than %d characters, it has been truncated.\n", autocvar_sv_name_maxlength));
                        assume_unchanged = false;
                        // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
                }
index 012e040f813da992f89ad999ac09aa4733d822bc..b20a8af93cdd5a72539e334adaefabf7b47ae3ac 100644 (file)
@@ -98,7 +98,7 @@ CLASS(Client, Object)
     ATTRIB(Client, zoomstate, bool, this.zoomstate);
     ATTRIB(Client, just_joined, bool, this.just_joined);
     ATTRIB(Client, race_completed, bool, this.race_completed);
-    ATTRIBARRAY(Client, msg_choice_choices, int, 50); // TODO: actually NOTIF_CHOICE_MAX
+    ATTRIBARRAY(Client, msg_choice_choices, int, 20); // TODO: actually NOTIF_CHOICE_MAX
     ATTRIB(Client, latency_sum, float, this.latency_sum);
     ATTRIB(Client, latency_cnt, int, this.latency_cnt);
     ATTRIB(Client, latency_time, float, this.latency_time);
@@ -139,6 +139,7 @@ CLASS(Client, Object)
     ATTRIB(Client, cvar_cl_weaponimpulsemode, int, this.cvar_cl_weaponimpulsemode);
     ATTRIB(Client, cvar_g_xonoticversion, string, this.cvar_g_xonoticversion);
     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_multijump, bool, this.cvar_cl_multijump);
     ATTRIB(Client, cvar_cl_accuracy_data_share, bool, this.cvar_cl_accuracy_data_share);
index 1395986b97bd3a463ab33c16e8508da381f992ca..4606638f621ac1240078f0149b2e27ef5cb17c78 100644 (file)
@@ -184,10 +184,11 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                        {
                                if (argv(1) == "spawn")
                                {
+                                       string s = argv(2);
                                        if (!IS_PLAYER(caller))
                                                sprint(caller, "ERROR: this command works only if you are player\n");
                                        else
-                                               waypoint_spawn_fromeditor(caller);
+                                               waypoint_spawn_fromeditor(caller, (s == "crosshair"), (s == "jump"), (s == "crouch"), (s == "support"));
                                        return;
                                }
                                else if (argv(1) == "remove")
@@ -198,6 +199,17 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                                                waypoint_remove_fromeditor(caller);
                                        return;
                                }
+                               else if (argv(1) == "hardwire")
+                               {
+                                       string s = argv(2);
+                                       waypoint_start_hardwiredlink(caller, (s == "crosshair"));
+                                       return;
+                               }
+                               else if (argv(1) == "lock")
+                               {
+                                       waypoint_lock(caller);
+                                       return;
+                               }
                                else if (argv(1) == "unreachable")
                                {
                                        if (!IS_PLAYER(caller))
@@ -240,13 +252,28 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                case CMD_REQUEST_USAGE:
                {
                        sprint(caller, "\nUsage:^3 cmd wpeditor action\n");
-                       sprint(caller, "  Where 'action' can be: spawn, remove, unreachable, saveall, relinkall,\n");
-                       sprint(caller, "   symorigin get|set\n");
-                       sprint(caller, "   symorigin get|set p1 p2 ... pX\n");
-                       sprint(caller, "   symaxis get|set p1 p2\n");
-                       sprint(caller, "    where p1 p2 ... pX are positions \"x y z\" (z can be omitted)\n");
-                       sprint(caller, " symorigin and symaxis commands are useful to determine origin/axis of symmetry"
-                                                       " on maps without ctf flags or where flags aren't perfectly symmetrical\n");
+                       sprint(caller, "  Where 'action' can be:\n");
+                       sprint(caller, "   ^5spawn^7: spawns a waypoint at player's position\n");
+                       sprint(caller, "   ^5remove^7: removes player's nearest waypoint\n");
+                       sprint(caller, "   ^5unreachable^7: reveals waypoints and items unreachable from the current position and spawnpoints without a nearest waypoint\n");
+                       sprint(caller, "   ^5saveall^7: saves all waypoints and links to file\n");
+                       sprint(caller, "   ^5relinkall^7: relinks all waypoints as if they were respawned\n");
+                       sprint(caller, "   ^5spawn crosshair^7: spawns a waypoint at crosshair's position\n");
+                       sprint(caller, "   ^7 in general useful to create special and hardwired links with ease from existing waypoints\n");
+                       sprint(caller, "   ^7 in particular it's the only way to create custom jumppad waypoints (spawn another waypoint to create destination))\n");
+                       sprint(caller, "   ^5spawn jump^7: spawns a jump waypoint (place it at least 60 qu before jump start, spawn another waypoint to create destination)\n");
+                       sprint(caller, "   ^5spawn crouch^7: spawns a crouch waypoint (it links only to very close waypoints)\n");
+                       sprint(caller, "   ^5spawn support^7: spawns a support waypoint (spawn another waypoint to create destination from which all incoming links are removed)\n");
+                       sprint(caller, "   ^7 useful to replace links to problematic jumppad/teleport waypoints\n");
+                       sprint(caller, "   ^5hardwire^7: marks the nearest waypoint as origin of a new hardwired link (spawn another waypoint over an existing one to create destination)\n");
+                       sprint(caller, "   ^5hardwire crosshair^7: marks the waypoint at crosshair instead of the nearest waypoint\n");
+                       sprint(caller, "   ^5lock^7: locks link display of the aimed waypoint (unlocks if no waypoint is found at crosshair's position)\n");
+                       sprint(caller, "   ^5symorigin get|set\n");
+                       sprint(caller, "   ^5symorigin get|set p1 p2 ... pX\n");
+                       sprint(caller, "   ^5symaxis get|set p1 p2\n");
+                       sprint(caller, "   ^7 where p1 p2 ... pX are positions (\"x y z\", z can be omitted) that you know are perfectly symmetrical"
+                                                               " so you can determine origin/axis of symmetry of maps without ctf flags or where flags aren't perfectly symmetrical\n");
+                       sprint(caller, "  See 'wpeditor_menu' for a selectable list of various commands and useful settings to edit waypoints.\n");
                        return;
                }
        }
@@ -328,7 +355,7 @@ void ClientCommand_physics(entity caller, int request, int argc)
 
                        if (Physics_Valid(command) || command == "default")
                        {
-                               stuffcmd(caller, strcat("\nseta cl_physics ", command, "\nsendcvar cl_physics\n"));
+                               stuffcmd(caller, strcat("\nseta cl_physics ", command, "\n"));
                                sprint(caller, strcat("^2Physics set successfully changed to ^3", command, "\n"));
                                return;
                        }
@@ -735,6 +762,12 @@ void ClientCommand_voice(entity caller, int request, int argc, string command)
                                        sprint(caller, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
                                        return;
                                }
+                               if (IS_DEAD(caller))
+                               {
+                                       // don't warn the caller when trying to taunt while dead, just don't play any sounds!
+                                       // we still allow them to see warnings if it's invalid, so a dead player can find out the sounds in peace
+                                       return;
+                               }
                                string msg = "";
                                if (argc >= 3)
                                        msg = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
@@ -883,6 +916,7 @@ void SV_ParseClientCommand(entity this, string command)
                case "prespawn": break;                            // handled by engine in host_cmd.c
                case "sentcvar": break;                            // handled by server in this file
                case "spawn": break;                               // handled by engine in host_cmd.c
+               case "color": case "topcolor": case "bottomcolor": if(teamplay) return; else break; // handled by engine in host_cmd.c
                case "c2s": Net_ClientCommand(this, command); return; // handled by net.qh
 
                default:
index e8fc1b13f1bbd5b5e897060ebd402ae5eec457da..5ff2d3472ae22ebbf2d3d898e0ecbd5f4ae4c910 100644 (file)
@@ -1274,50 +1274,61 @@ void GameCommand_setbots(int request, int argc)
        }
 }
 
+void shuffleteams()
+{
+       if (!teamplay)
+       {
+               LOG_INFO("Can't shuffle teams when currently not playing a team game.");
+               return;
+       }
+
+       FOREACH_CLIENT(IS_PLAYER(it) || it.caplayer, {
+               if (Player_HasRealForcedTeam(it)) {
+                       // we could theoretically assign forced players to their teams
+                       // and shuffle the rest to fill the empty spots but in practise
+                       // either all players or none are gonna have forced teams
+                       LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
+                       return;
+               }
+       });
+
+       int number_of_teams = 0;
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if (TeamBalance_IsTeamAllowed(balance, i))
+               {
+                       number_of_teams = max(i, number_of_teams);
+               }
+       }
+       TeamBalance_Destroy(balance);
+
+       int team_index = 0;
+       FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, {
+               int target_team_index = team_index + 1;
+               if (Entity_GetTeamIndex(it) != target_team_index)
+               {
+                       MoveToTeam(it, target_team_index, 6);
+               }
+               team_index = (team_index + 1) % number_of_teams;
+       });
+
+       bprint("Successfully shuffled the players around randomly.\n");
+}
+
 void GameCommand_shuffleteams(int request)
 {
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
                {
-                       if (!teamplay)
+                       if (shuffleteams_on_reset_map)
                        {
-                               LOG_INFO("Can't shuffle teams when currently not playing a team game.");
-                               return;
+                               bprint("Players will be shuffled when this round is over.\n");
+                               shuffleteams_on_reset_map = true;
                        }
-
-                       FOREACH_CLIENT(IS_PLAYER(it) || it.caplayer, {
-                               if (Player_HasRealForcedTeam(it)) {
-                                       // we could theoretically assign forced players to their teams
-                                       // and shuffle the rest to fill the empty spots but in practise
-                                       // either all players or none are gonna have forced teams
-                                       LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
-                                       return;
-                               }
-                       });
-
-                       int number_of_teams = 0;
-                       entity balance = TeamBalance_CheckAllowedTeams(NULL);
-                       for (int i = 1; i <= NUM_TEAMS; ++i)
-                       {
-                               if (TeamBalance_IsTeamAllowed(balance, i))
-                               {
-                                       number_of_teams = max(i, number_of_teams);
-                               }
-                       }
-                       TeamBalance_Destroy(balance);
-
-                       int team_index = 0;
-                       FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, {
-                               int target_team_index = team_index + 1;
-                               if (Entity_GetTeamIndex(it) != target_team_index)
-                               {
-                                       MoveToTeam(it, target_team_index, 6);
-                               }
-                               team_index = (team_index + 1) % number_of_teams;
-                       });
-
-                       bprint("Successfully shuffled the players around randomly.\n");
+                       else
+                               shuffleteams();
                        return;
                }
 
index 00e216c921855757b9a5aa87c23cfe5362fdbf9b..bf0dafa9cfffe0698723624f29088e4fc2c37c74 100644 (file)
@@ -4,6 +4,9 @@
 //  Declarations for server side game commands
 // =================================================
 
+bool shuffleteams_on_reset_map;
+void shuffleteams();
+
 string GotoMap(string m);
 
 void race_deleteTime(string map, float pos);
index 51cf55ce3a1de3ee3c83cc027348ae803f7e072e..a5cc7383404d0f3bc4d179f2be0e1ad4631dfa49 100644 (file)
@@ -345,6 +345,11 @@ void reset_map(bool dorespawn)
                        round_handler_Reset(game_starttime);
        }
 
+       if (shuffleteams_on_reset_map)
+       {
+               shuffleteams();
+               shuffleteams_on_reset_map = false;
+       }
        MUTATOR_CALLHOOK(reset_map_global);
 
        FOREACH_ENTITY_FLOAT_ORDERED(pure_data, false,
@@ -435,6 +440,8 @@ void ReadyRestart_force()
        restart_mapalreadyrestarted = false; // reset this var, needed when cvar sv_ready_restart_repeatable is in use
 
        // disable the warmup global for the server
+       if(warmup_stage)
+               localcmd("\nsv_hook_warmupend\n");
        warmup_stage = 0;                // once the game is restarted the game is in match stage
 
        // reset the .ready status of all players (also spectators)
index 112a7f039d95cee3c5ab34820011a0a1a7dd20d4..8205b81284d2811d618b38e6c8675aca3942482b 100644 (file)
@@ -7,6 +7,8 @@
 #include <common/t_items.qh>
 #include <common/mapobjects/triggers.qh>
 #include <common/mapobjects/trigger/counter.qh>
+#include <common/mutators/mutator/buffs/buffs.qh>
+#include <common/notifications/all.qh>
 #include <common/weapons/_all.qh>
 
 //***********************
@@ -119,7 +121,16 @@ void target_init_use(entity this, entity actor, entity trigger)
        {
                actor.strength_finished = 0;
                actor.invincible_finished = 0;
-               STAT(BUFFS, actor) = 0;
+               if(STAT(BUFFS, actor)) // TODO: make a dropbuffs function to handle this
+               {
+                       int buffid = buff_FirstFromFlags(STAT(BUFFS, actor)).m_id;
+                       Send_Notification(NOTIF_ONE, actor, MSG_MULTI, ITEM_BUFF_DROP, buffid);
+                       sound(actor, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
+                       if(!IS_INDEPENDENT_PLAYER(actor))
+                               Send_Notification(NOTIF_ALL_EXCEPT, actor, MSG_INFO, INFO_ITEM_BUFF_LOST, actor.netname, buffid);
+                       STAT(BUFFS, actor) = 0;
+                       STAT(BUFF_TIME, actor) = 0;
+               }
        }
 
        if (!(this.spawnflags & 16))
@@ -169,6 +180,12 @@ void target_give_init(entity this)
                        SetResourceExplicit(this, RES_ARMOR, 100);
                else if (it.classname == "item_health_mega")
                        SetResourceExplicit(this, RES_HEALTH, 200);
+               else if (it.classname == "item_buff") {
+                       entity buff = buff_FirstFromFlags(STAT(BUFFS, it));
+                       this.netname = cons(this.netname, buff.netname);
+                       STAT(BUFF_TIME, this) = it.count;
+               }
+
                //remove(it); // removing ents in init functions causes havoc, workaround:
         setthink(it, SUB_Remove);
         it.nextthink = time;
index f98d586fb504cf389b764fb704360713d5a2148f..62a15f680c1cb8117c68385a5f6e4119a50c16d3 100644 (file)
@@ -10,9 +10,9 @@ const int FL_PICKUPITEMS = BIT(19);
 
 const int SVC_SETVIEW = 5;
 
-const int RESPAWN_FORCE = 1;
-const int RESPAWN_SILENT = 2;
-const int RESPAWN_DENY = 4;
+const int RESPAWN_FORCE = BIT(0);
+const int RESPAWN_SILENT = BIT(1);
+const int RESPAWN_DENY = BIT(2);
 
 #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT)
 
index 28a61cf1cd4120e270bd8fa491049d9f9e2e8f21..b1d73f6a3124c87110d254d1f2bc73f739003d38 100644 (file)
@@ -163,6 +163,7 @@ float default_player_alpha;
 float default_weapon_alpha;
 
 .float cvar_cl_handicap;
+.int cvar_cl_gunalign;
 .float cvar_cl_clippedspectating;
 .float cvar_cl_autoscreenshot;
 .float cvar_cl_jetpack_jump;
@@ -181,6 +182,7 @@ float default_weapon_alpha;
 
 .float cvar_cl_allow_uid2name;
 .float cvar_cl_allow_uidtracking;
+.bool cvar_cl_allow_uidranking;
 .string stored_netname;
 
 string gamemode_name;
@@ -190,9 +192,6 @@ string W_Apply_Weaponreplace(string in);
 void FixIntermissionClient(entity e);
 void FixClientCvars(entity e);
 
-// WEAPONTODO: remove this
-//WepSet weaponsInMap;
-
 .float respawn_countdown; // next number to count
 
 float bot_waypoints_for_items;
@@ -298,11 +297,6 @@ string matchid;
 
 bool radar_showennemies;
 
-#ifdef PROFILING
-float client_cefc_accumulator;
-float client_cefc_accumulatortime;
-#endif
-
 .float weapon_load[Weapons_MAX];
 .int ammo_none; // used by the reloading system, must always be 0
 .int clip_load;
@@ -338,7 +332,7 @@ string deathmessage;
 .float cvar_cl_weaponimpulsemode;
 .int selectweapon; // last selected weapon of the player
 
-.float ballistics_density; // wall piercing factor, larger = bullet can pass through more
+.float ballistics_density;
 
 //const int FROZEN_NOT                         = 0;
 const int FROZEN_NORMAL                                = 1;
index 0901ab44780555d28da3646ef409a62741981321..e14ecd6ce7808ebeeca7dd436dc1aa4d41db2127 100644 (file)
@@ -74,8 +74,6 @@ void GiveFrags(entity attacker, entity targ, float f, int deathtype, .entity wea
                UpdateFrags(attacker, f);
 }
 
-.entity kh_next;
-
 string AppendItemcodes(string s, entity player)
 {
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
@@ -91,12 +89,11 @@ string AppendItemcodes(string s, entity player)
                s = strcat(s, "S");
        if(time < player.invincible_finished)
                s = strcat(s, "I");
-       if(player.flagcarried != NULL)
-               s = strcat(s, "F");
        if(PHYS_INPUT_BUTTON_CHAT(player))
                s = strcat(s, "T");
-       if(player.kh_next)
-               s = strcat(s, "K");
+       // TODO: include these codes as a flag on the item itself
+       MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
+       s = M_ARGV(1, string);
        return s;
 }
 
@@ -865,7 +862,7 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
 }
 
 float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
-                                                               float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
+                                                               float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity)
        // Returns total damage applies to creatures
 {
        entity  targ;
@@ -952,8 +949,10 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
                                        force = force * (finaldmg / coredamage) * forceintensity;
                                        hitloc = nearest;
 
-                                       if(deathtype & WEP_BLASTER.m_id)
-                                               force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale);
+                                       // apply special scaling along the z axis if set
+                                       // NOTE: 0 value is not allowed for compatibility, in the case of weapon cvars not being set
+                                       if(forcezscale)
+                                               force.z *= forcezscale;
 
                                        if(targ != directhitentity)
                                        {
@@ -1056,7 +1055,8 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
 
 float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
 {
-       return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity);
+       return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, 
+                                                                       cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
 }
 
 bool Heal(entity targ, entity inflictor, float amount, float limit)
index efe6b2e1b306af9a6903638f8681579f411532fa..a99846c734f7dd916d3b54ecc5b8b597425a1371 100644 (file)
@@ -91,7 +91,7 @@ void Unfreeze(entity targ, bool reset_health);
 void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
 
 float RadiusDamage_running;
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity);
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity);
        // Returns total damage applies to creatures
 
 float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity);
index 453cfc1e70d3664d1725e795c685c36c1e00cb69..b2b91bc02baf71cea1adf089e8236eea2a397667 100644 (file)
@@ -21,8 +21,6 @@
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/server.qh"
 
-.int state;
-
 /*============================================
 
       Wazat's Xonotic Grappling Hook
@@ -72,8 +70,6 @@ And you should be done!
 
 ============================================*/
 
-.float hook_length;
-
 void RemoveGrapplingHooks(entity pl)
 {
        if(pl.move_movetype == MOVETYPE_FLY)
index c0df31662a7d5cea6c95584dd7a13bfd7d969dad..1ed78e2745d9d4a4cdfff18792f9399af50fb7e6 100644 (file)
@@ -8,12 +8,16 @@ void RemoveHook(entity this);
 // (note: you can change the hook impulse #'s to whatever you please)
 .float hook_time;
 
+.float hook_length;
+
 const float HOOK_FIRING = BIT(0);
 const float HOOK_REMOVING = BIT(1);
 const float HOOK_PULLING = BIT(2);
 const float HOOK_RELEASING = BIT(3);
 const float HOOK_WAITING_FOR_RELEASE = BIT(4);
 .float hook_state;
+.int state;
 
 void GrappleHookInit();
 vector hook_shotorigin[4];
+
index 9ef72ae832352149d3dce0b2dc11253774218bbf..30ed368f3a8ecbf4592a9d62b13e8bc563c5dbe2 100644 (file)
@@ -266,6 +266,7 @@ void cvar_changes_init()
                BADCVAR("g_domination");
                BADCVAR("g_domination_default_teams");
                BADCVAR("g_duel");
+               BADCVAR("g_duel_not_dm_maps");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
                BADCVAR("g_invasion_teams");
@@ -283,8 +284,10 @@ void cvar_changes_init()
                BADCVAR("g_race_qualifying_timelimit");
                BADCVAR("g_race_qualifying_timelimit_override");
                BADCVAR("g_runematch");
+               BADCVAR("g_shootfromeye");
                BADCVAR("g_snafu");
                BADCVAR("g_tdm");
+               BADCVAR("g_tdm_on_dm_maps");
                BADCVAR("g_tdm_teams");
                BADCVAR("g_vip");
                BADCVAR("leadlimit");
@@ -292,6 +295,8 @@ void cvar_changes_init()
                BADCVAR("teamplay");
                BADCVAR("timelimit");
                BADCVAR("g_mapinfo_ignore_warnings");
+               BADCVAR("g_maplist_ignore_sizes");
+               BADCVAR("g_maplist_sizes_count_bots");
 
                // long
                BADCVAR("hostname");
@@ -320,6 +325,7 @@ void cvar_changes_init()
                BADCVAR("captureleadlimit_override");
                BADCVAR("condump_stripcolors");
                BADCVAR("gameversion");
+               BADCVAR("fs_gamedir");
                BADCVAR("g_allow_oldvortexbeam");
                BADCVAR("g_balance_kill_delay");
                BADCVAR("g_buffs_pickup_anyway");
@@ -339,10 +345,12 @@ void cvar_changes_init()
                BADCVAR("g_jump_grunt");
                BADCVAR("g_keyhunt_point_leadlimit");
                BADCVAR("g_nexball_goalleadlimit");
+               BADCVAR("g_new_toys_autoreplace");
                BADCVAR("g_new_toys_use_pickupsound");
                BADCVAR("g_physics_predictall");
                BADCVAR("g_piggyback");
                BADCVAR("g_playerclip_collisions");
+               BADCVAR("g_spawn_alloweffects");
                BADCVAR("g_tdm_point_leadlimit");
                BADCVAR("g_tdm_point_limit");
                BADCVAR("leadlimit_and_fraglimit");
@@ -402,6 +410,7 @@ void cvar_changes_init()
                BADCVAR("g_ban_sync_uri");
                BADCVAR("g_buffs");
                BADCVAR("g_ca_teams_override");
+               BADCVAR("g_ctf_fullbrightflags");
                BADCVAR("g_ctf_ignore_frags");
                BADCVAR("g_ctf_leaderboard");
                BADCVAR("g_domination_point_limit");
@@ -421,6 +430,9 @@ void cvar_changes_init()
                BADCVAR("g_physics_clientselect");
                BADCVAR("g_pinata");
                BADCVAR("g_powerups");
+               BADCVAR("g_player_brightness");
+               BADCVAR("g_rocket_flying");
+               BADCVAR("g_rocket_flying_disabledelays");
                BADCVAR("g_spawnshieldtime");
                BADCVAR("g_start_delay");
                BADCVAR("g_superspectate");
@@ -474,6 +486,18 @@ void cvar_changes_init()
                BADCVAR("g_grappling_hook");
                BADCVAR("g_jetpack");
 
+               // temporary for testing
+               // TODO remove before 0.8.3 release
+               BADCVAR("g_ca_weaponarena");
+               BADCVAR("g_freezetag_weaponarena");
+               BADCVAR("g_lms_weaponarena");
+
+               if(cvar_string("g_mod_balance") == "Testing")
+               {
+                       // (temporary) while using the Testing balance, any weapon balance cvars are allowed to be changed
+                       BADPREFIX("g_balance_");
+               }
+
 #undef BADPRESUFFIX
 #undef BADPREFIX
 #undef BADCVAR
@@ -860,8 +884,14 @@ spawnfunc(worldspawn)
                                        continue;
                                if(argv(0) == "cd")
                                {
+                                       string trackname = argv(2);
                                        LOG_INFO("Found ^1UNSUPPORTED^7 cd loop command in .cfg file; put this line in mapinfo instead:");
-                                       LOG_INFO("  cdtrack ", argv(2));
+                                       LOG_INFO("  cdtrack ", trackname);
+                                       if (cvar_value_issafe(trackname))
+                                       {
+                                               string newstuff = strcat(clientstuff, "cd loop \"", trackname, "\"\n");
+                                               strcpy(clientstuff, newstuff);
+                                       }
                                }
                                else if(argv(0) == "fog")
                                {
@@ -947,7 +977,7 @@ spawnfunc(worldspawn)
        // physics/balance/config changes that count as mod
        if(cvar_string("g_mod_physics") != cvar_defstring("g_mod_physics"))
                modname = cvar_string("g_mod_physics");
-       if(cvar_string("g_mod_balance") != cvar_defstring("g_mod_balance"))
+       if(cvar_string("g_mod_balance") != cvar_defstring("g_mod_balance") && cvar_string("g_mod_balance") != "Testing")
                modname = cvar_string("g_mod_balance");
        if(cvar_string("g_mod_config") != cvar_defstring("g_mod_config"))
                modname = cvar_string("g_mod_config");
@@ -984,22 +1014,27 @@ float Map_Count, Map_Current;
 string Map_Current_Name;
 
 // NOTE: this now expects the map list to be already tokenized and the count in Map_Count
-float GetMaplistPosition()
+int GetMaplistPosition()
 {
-       float pos, idx;
-       string map;
-
-       map = GetMapname();
-       idx = autocvar_g_maplist_index;
+       string map = GetMapname();
+       int idx = autocvar_g_maplist_index;
 
        if(idx >= 0)
+       {
                if(idx < Map_Count)
+               {
                        if(map == argv(idx))
+                       {
                                return idx;
+                       }
+               }
+       }
 
-       for(pos = 0; pos < Map_Count; ++pos)
+       for(int pos = 0; pos < Map_Count; ++pos)
+       {
                if(map == argv(pos))
                        return pos;
+       }
 
        // resume normal maplist rotation if current map is not in g_maplist
        return idx;
@@ -1022,21 +1057,27 @@ bool MapHasRightSize(string map)
                LOG_TRACE(checkwp_msg, ": has waypoints");
        }
 
+       if(autocvar_g_maplist_ignore_sizes)
+               return true;
+
        // open map size restriction file
        string opensize_msg = strcat("opensize ", map);
        float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+       int pcount = player_count;
+       if(!autocvar_g_maplist_sizes_count_bots)
+               pcount -= currentbots;
        if(fh >= 0)
        {
                opensize_msg = strcat(opensize_msg, ": ok, ");
                int mapmin = stoi(fgets(fh));
                int mapmax = stoi(fgets(fh));
                fclose(fh);
-               if(player_count < mapmin)
+               if(pcount < mapmin)
                {
                        LOG_TRACE(opensize_msg, "not enough");
                        return false;
                }
-               if(mapmax && player_count > mapmax)
+               if(mapmax && pcount > mapmax)
                {
                        LOG_TRACE(opensize_msg, "too many");
                        return false;
@@ -1199,18 +1240,25 @@ float MaplistMethod_Shuffle(float exponent) // more clever shuffling
 
 void Maplist_Init()
 {
-       Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
-       float i;
-       for (i = 0; i < Map_Count; ++i)
-               if (Map_Check(i, 2))
-                       break;
+       float i = Map_Count = 0;
+       if(autocvar_g_maplist != "")
+       {
+               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+               for (i = 0; i < Map_Count; ++i)
+               {
+                       if (Map_Check(i, 2))
+                               break;
+               }
+       }
+       
        if (i == Map_Count)
        {
                bprint( "Maplist contains no usable maps!  Resetting it to default map list.\n" );
                cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
                if(autocvar_g_maplist_shuffle)
                        ShuffleMaplist();
-               localcmd("\nmenu_cmd sync\n");
+               if(!server_is_dedicated)
+                       localcmd("\nmenu_cmd sync\n");
                Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
        }
        if(Map_Count == 0)
@@ -1224,10 +1272,8 @@ void Maplist_Init()
 
 string GetNextMap()
 {
-       float nextMap;
-
        Maplist_Init();
-       nextMap = -1;
+       float nextMap = -1;
 
        if(nextMap == -1)
                if(autocvar_g_maplist_shuffle > 0)
@@ -1322,9 +1368,7 @@ void GotoNextMap(float reinit)
                return;
        alreadychangedlevel = true;
 
-       string nextMap;
-
-       nextMap = GetNextMap();
+       string nextMap = GetNextMap();
        if(nextMap == "")
                error("Everything is broken - cannot find a next map. Please report this to the developers.");
        Map_Goto(reinit);
@@ -2021,7 +2065,7 @@ string GotoMap(string m)
                return "Map switch will happen after scoreboard.";
 }
 
-bool autocvar_sv_gameplayfix_multiplethinksperframe;
+bool autocvar_sv_gameplayfix_multiplethinksperframe = true;
 void RunThink(entity this)
 {
        // don't let things stay in the past.
@@ -2050,7 +2094,7 @@ void RunThink(entity this)
 }
 
 bool autocvar_sv_freezenonclients;
-bool autocvar_sv_gameplayfix_delayprojectiles;
+bool autocvar_sv_gameplayfix_delayprojectiles = false;
 void Physics_Frame()
 {
        if(autocvar_sv_freezenonclients)
index 2320eb830ef50db38913df89c96a724ce801080d..49685d49d7ec088c9a3a5a83c993dadbb7f89bbf 100644 (file)
@@ -507,7 +507,7 @@ IMPULSE(waypoint_here_here)
 
 IMPULSE(waypoint_here_crosshair)
 {
-       WarpZone_crosshair_trace(this);
+       WarpZone_crosshair_trace_plusvisibletriggers(this);
        entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, trace_endpos, RADARICON_HERE);
        if (wp) WaypointSprite_Ping(wp);
        sprint(this, "HERE spawned at crosshair\n");
index 7c6fcbafef635c9aff2bddca7ab30ec8c23d45de..9d74477b4846525c3d84dc020a58340c75b2e11e 100644 (file)
@@ -202,12 +202,21 @@ void OnlineBanList_Think(entity this)
        float i, n;
 
        if(autocvar_g_ban_sync_uri == "")
-               goto killme;
+       {
+               delete(this);
+               return;
+       }
        if(autocvar_g_ban_sync_interval == 0) // < 0 is okay, it means "sync on level start only"
-               goto killme;
+       {
+               delete(this);
+               return;
+       }
        argc = tokenize_console(autocvar_g_ban_sync_trusted_servers);
        if(argc == 0)
-               goto killme;
+       {
+               delete(this);
+               return;
+       }
 
        string s = argv(0); for(i = 1; i < argc; ++i) s = strcat(s, ";", argv(i));
        strcpy(OnlineBanList_Servers, s);
@@ -231,14 +240,13 @@ void OnlineBanList_Think(entity this)
                        uri_get(strcat(argv(i), "?", uri), URI_GET_IPBAN + i); // 1000 = "banlist" callback target
        }
 
-       if(autocvar_g_ban_sync_interval > 0)
-               this.nextthink = time + max(60, autocvar_g_ban_sync_interval * 60);
-       else
-               goto killme;
-       return;
+       if(autocvar_g_ban_sync_interval <= 0)
+       {
+               delete(this);
+               return;
+       }
 
-LABEL(killme)
-       delete(this);
+       this.nextthink = time + max(60, autocvar_g_ban_sync_interval * 60);
 }
 
 const float BAN_MAX = 256;
index bc0b49ca027ece50fb41bbccc35723b3252886d7..ded47a6387f97920ce32f2fa41851a7b8ec32dea 100644 (file)
@@ -390,6 +390,8 @@ REPLICATE(autoswitch, bool, "cl_autoswitch");
 
 REPLICATE(cvar_cl_allow_uid2name, bool, "cl_allow_uid2name");
 
+REPLICATE(cvar_cl_allow_uidranking, bool, "cl_allow_uidranking");
+
 REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
 
 REPLICATE(cvar_cl_autotaunt, float, "cl_autotaunt");
@@ -398,6 +400,8 @@ REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
 
 REPLICATE(cvar_cl_handicap, float, "cl_handicap");
 
+REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
+
 REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
 
 REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
@@ -429,6 +433,9 @@ void GetCvars(entity this, entity store, int f)
 {
        string s = string_null;
 
+       if (f == 0)
+               LOG_INFO("Warning: requesting cvar values is deprecated. Client should send them automatically using REPLICATE.\n");
+
        if (f > 0)
                s = strcat1(argv(f));
 
@@ -484,13 +491,12 @@ string playername(entity p, bool team_colorize)
         return p.netname;
 }
 
-float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done?
+float want_weapon(entity weaponinfo, float allguns)
 {
-       int i = weaponinfo.m_id;
        int d = 0;
        bool allow_mutatorblocked = false;
 
-       if(!i)
+       if(!weaponinfo.m_id)
                return 0;
 
        bool mutator_returnvalue = MUTATOR_CALLHOOK(WantWeapon, weaponinfo, d, allguns, allow_mutatorblocked);
@@ -499,7 +505,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne
        allow_mutatorblocked = M_ARGV(3, bool);
 
        if(allguns)
-               d = boolean(weaponinfo.spawnflags & WEP_FLAG_NORMAL);
+               d = boolean((weaponinfo.spawnflags & WEP_FLAG_NORMAL) && !(weaponinfo.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)));
        else if(!mutator_returnvalue)
                d = !(!weaponinfo.weaponstart);
 
@@ -508,7 +514,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne
 
        float t = weaponinfo.weaponstartoverride;
 
-       //print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n"));
+       //LOG_INFOF("want_weapon: %s - d: %d t: %d\n", weaponinfo.netname, d, t);
 
        // bit order in t:
        // 1: want or not
@@ -522,10 +528,90 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne
        return t;
 }
 
+/// Weapons the player normally starts with outside weapon arena.
+WepSet weapons_start()
+{
+       WepSet ret = '0 0 0';
+       FOREACH(Weapons, it != WEP_Null, {
+               int w = want_weapon(it, false);
+               if (w & 1)
+                       ret |= it.m_wepset;
+       });
+       return ret;
+}
+
+WepSet weapons_all()
+{
+       WepSet ret = '0 0 0';
+       FOREACH(Weapons, it != WEP_Null, {
+               if (!(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)))
+                       ret |= it.m_wepset;
+       });
+       return ret;
+}
+
+WepSet weapons_devall()
+{
+       WepSet ret = '0 0 0';
+       FOREACH(Weapons, it != WEP_Null,
+       {
+               ret |= it.m_wepset;
+       });
+       return ret;
+}
+
+WepSet weapons_most()
+{
+       WepSet ret = '0 0 0';
+       FOREACH(Weapons, it != WEP_Null, {
+               if ((it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)))
+                       ret |= it.m_wepset;
+       });
+       return ret;
+}
+
+void weaponarena_available_all_update(entity this)
+{
+       if (weaponsInMapAll)
+       {
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | (weaponsInMapAll & weapons_all());
+       }
+       else
+       {
+               // if no weapons are available on the map, just fall back to all weapons arena
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_all();
+       }
+}
+
+void weaponarena_available_devall_update(entity this)
+{
+       if (weaponsInMapAll)
+       {
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | weaponsInMapAll;
+       }
+       else
+       {
+               // if no weapons are available on the map, just fall back to devall weapons arena
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_devall();
+       }
+}
+
+void weaponarena_available_most_update(entity this)
+{
+       if (weaponsInMapAll)
+       {
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | (weaponsInMapAll & weapons_most());
+       }
+       else
+       {
+               // if no weapons are available on the map, just fall back to most weapons arena
+               start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_most();
+       }
+}
+
 void readplayerstartcvars()
 {
        float i, t;
-       string s;
 
        // initialize starting values for players
        start_weapons = '0 0 0';
@@ -547,7 +633,7 @@ void readplayerstartcvars()
        g_weaponarena = 0;
        g_weaponarena_weapons = '0 0 0';
 
-       s = cvar_string("g_weaponarena");
+       string s = cvar_string("g_weaponarena");
 
        MUTATOR_CALLHOOK(SetWeaponArena, s);
        s = M_ARGV(0, string);
@@ -564,28 +650,43 @@ void readplayerstartcvars()
        {
                g_weaponarena = 1;
                g_weaponarena_list = "All Weapons";
-               FOREACH(Weapons, it != WEP_Null, {
-                       if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
-                               g_weaponarena_weapons |= (it.m_wepset);
-               });
+               g_weaponarena_weapons = weapons_all();
        }
        else if (s == "devall")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "All Weapons"; // TODO: report as more than just all weapons?
-               FOREACH(Weapons, it != WEP_Null,
-               {
-                       g_weaponarena_weapons |= (it.m_wepset);
-               });
+               g_weaponarena_list = "Dev All Weapons";
+               g_weaponarena_weapons = weapons_devall();
        }
        else if (s == "most")
        {
                g_weaponarena = 1;
                g_weaponarena_list = "Most Weapons";
-               FOREACH(Weapons, it != WEP_Null, {
-                       if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && (it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & WEP_FLAG_HIDDEN))
-                               g_weaponarena_weapons |= (it.m_wepset);
-               });
+               g_weaponarena_weapons = weapons_most();
+       }
+       else if (s == "all_available")
+       {
+               g_weaponarena = 1;
+               g_weaponarena_list = "All Available Weapons";
+
+               // this needs to run after weaponsInMapAll is initialized
+               InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET);
+       }
+       else if (s == "devall_available")
+       {
+               g_weaponarena = 1;
+               g_weaponarena_list = "Dev All Available Weapons";
+
+               // this needs to run after weaponsInMapAll is initialized
+               InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET);
+       }
+       else if (s == "most_available")
+       {
+               g_weaponarena = 1;
+               g_weaponarena_list = "Most Available Weapons";
+
+               // this needs to run after weaponsInMapAll is initialized
+               InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET);
        }
        else if (s == "none")
        {
@@ -614,7 +715,7 @@ void readplayerstartcvars()
        {
                g_weapon_stay = 0; // incompatible
                start_weapons = g_weaponarena_weapons;
-               start_items |= IT_UNLIMITED_AMMO;
+               start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
        }
        else
        {
@@ -636,7 +737,7 @@ void readplayerstartcvars()
        if(!cvar("g_use_ammunition"))
                start_items |= IT_UNLIMITED_AMMO;
 
-       if(start_items & IT_UNLIMITED_WEAPON_AMMO)
+       if(start_items & IT_UNLIMITED_AMMO)
        {
                start_ammo_shells = 999;
                start_ammo_nails = 999;
@@ -654,56 +755,48 @@ void readplayerstartcvars()
                start_ammo_plasma = cvar("g_start_ammo_plasma");
                start_ammo_fuel = cvar("g_start_ammo_fuel");
                random_start_weapons_count = cvar("g_random_start_weapons_count");
-               SetResource(random_start_ammo, RES_SHELLS, cvar(
-                       "g_random_start_shells"));
-               SetResource(random_start_ammo, RES_BULLETS, cvar(
-                       "g_random_start_bullets"));
-               SetResource(random_start_ammo, RES_ROCKETS,
-                       cvar("g_random_start_rockets"));
-               SetResource(random_start_ammo, RES_CELLS, cvar(
-                       "g_random_start_cells"));
-               SetResource(random_start_ammo, RES_PLASMA, cvar(
-                       "g_random_start_plasma"));
+               SetResource(random_start_ammo, RES_SHELLS, cvar("g_random_start_shells"));
+               SetResource(random_start_ammo, RES_BULLETS, cvar("g_random_start_bullets"));
+               SetResource(random_start_ammo, RES_ROCKETS,cvar("g_random_start_rockets"));
+               SetResource(random_start_ammo, RES_CELLS, cvar("g_random_start_cells"));
+               SetResource(random_start_ammo, RES_PLASMA, cvar("g_random_start_plasma"));
        }
 
-       if (warmup_stage)
+       warmup_start_ammo_shells = start_ammo_shells;
+       warmup_start_ammo_nails = start_ammo_nails;
+       warmup_start_ammo_rockets = start_ammo_rockets;
+       warmup_start_ammo_cells = start_ammo_cells;
+       warmup_start_ammo_plasma = start_ammo_plasma;
+       warmup_start_ammo_fuel = start_ammo_fuel;
+       warmup_start_health = start_health;
+       warmup_start_armorvalue = start_armorvalue;
+       warmup_start_weapons = start_weapons;
+       warmup_start_weapons_default = start_weapons_default;
+       warmup_start_weapons_defaultmask = start_weapons_defaultmask;
+
+       if (!g_weaponarena)
        {
-               warmup_start_ammo_shells = start_ammo_shells;
-               warmup_start_ammo_nails = start_ammo_nails;
-               warmup_start_ammo_rockets = start_ammo_rockets;
-               warmup_start_ammo_cells = start_ammo_cells;
-               warmup_start_ammo_plasma = start_ammo_plasma;
-               warmup_start_ammo_fuel = start_ammo_fuel;
-               warmup_start_health = start_health;
-               warmup_start_armorvalue = start_armorvalue;
-               warmup_start_weapons = start_weapons;
-               warmup_start_weapons_default = start_weapons_default;
-               warmup_start_weapons_defaultmask = start_weapons_defaultmask;
-
-               if (!g_weaponarena && !g_ca && !g_freezetag)
-               {
-                       warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
-                       warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
-                       warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
-                       warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
-                       warmup_start_ammo_plasma = cvar("g_warmup_start_ammo_plasma");
-                       warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
-                       warmup_start_health = cvar("g_warmup_start_health");
-                       warmup_start_armorvalue = cvar("g_warmup_start_armor");
-                       warmup_start_weapons = '0 0 0';
-                       warmup_start_weapons_default = '0 0 0';
-                       warmup_start_weapons_defaultmask = '0 0 0';
-                       FOREACH(Weapons, it != WEP_Null, {
-                               int w = want_weapon(it, g_warmup_allguns);
-                               WepSet s = (it.m_wepset);
-                               if(w & 1)
-                                       warmup_start_weapons |= s;
-                               if(w & 2)
-                                       warmup_start_weapons_default |= s;
-                               if(w & 4)
-                                       warmup_start_weapons_defaultmask |= s;
-                       });
-               }
+               warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
+               warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
+               warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
+               warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
+               warmup_start_ammo_plasma = cvar("g_warmup_start_ammo_plasma");
+               warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
+               warmup_start_health = cvar("g_warmup_start_health");
+               warmup_start_armorvalue = cvar("g_warmup_start_armor");
+               warmup_start_weapons = '0 0 0';
+               warmup_start_weapons_default = '0 0 0';
+               warmup_start_weapons_defaultmask = '0 0 0';
+               FOREACH(Weapons, it != WEP_Null, {
+                       int w = want_weapon(it, g_warmup_allguns);
+                       WepSet s = it.m_wepset;
+                       if(w & 1)
+                               warmup_start_weapons |= s;
+                       if(w & 2)
+                               warmup_start_weapons_default |= s;
+                       if(w & 4)
+                               warmup_start_weapons_defaultmask |= s;
+               });
        }
 
        if (g_jetpack)
@@ -724,16 +817,16 @@ void readplayerstartcvars()
        start_ammo_cells = max(0, start_ammo_cells);
        start_ammo_plasma = max(0, start_ammo_plasma);
        start_ammo_fuel = max(0, start_ammo_fuel);
-       SetResource(random_start_ammo, RES_SHELLS, max(0,
-               GetResource(random_start_ammo, RES_SHELLS)));
-       SetResource(random_start_ammo, RES_BULLETS, max(0,
-               GetResource(random_start_ammo, RES_BULLETS)));
-       SetResource(random_start_ammo, RES_ROCKETS, max(0,
-               GetResource(random_start_ammo, RES_ROCKETS)));
-       SetResource(random_start_ammo, RES_CELLS, max(0,
-               GetResource(random_start_ammo, RES_CELLS)));
-       SetResource(random_start_ammo, RES_PLASMA, max(0,
-               GetResource(random_start_ammo, RES_PLASMA)));
+       SetResource(random_start_ammo, RES_SHELLS,
+               max(0, GetResource(random_start_ammo, RES_SHELLS)));
+       SetResource(random_start_ammo, RES_BULLETS,
+               max(0, GetResource(random_start_ammo, RES_BULLETS)));
+       SetResource(random_start_ammo, RES_ROCKETS,
+               max(0, GetResource(random_start_ammo, RES_ROCKETS)));
+       SetResource(random_start_ammo, RES_CELLS,
+               max(0, GetResource(random_start_ammo, RES_CELLS)));
+       SetResource(random_start_ammo, RES_PLASMA,
+               max(0, GetResource(random_start_ammo, RES_PLASMA)));
 
        warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
        warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
@@ -748,9 +841,9 @@ void precache_playermodel(string m)
        float globhandle, i, n;
        string f;
 
-       if(substring(m, -9,5) == "_lod1")
+       if(substring(m, -9, 5) == "_lod1")
                return;
-       if(substring(m, -9,5) == "_lod2")
+       if(substring(m, -9, 5) == "_lod2")
                return;
        precache_model(m);
        f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1));
@@ -1103,11 +1196,6 @@ bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher
                        return false; // no checks here
                else if(this.classname == "grapplinghook")
                        RemoveHook(this);
-               else if(this.classname == "spike")
-               {
-                       W_Crylink_Dequeue(this);
-                       delete(this);
-               }
                else
                        delete(this);
                return true;
index f0237b27ee8b8d55d588fe6386d49deb803d7090..a310c6ccadb294c25aad77a6f3900cbb1a96a19a 100644 (file)
@@ -306,6 +306,7 @@ MUTATOR_HOOKABLE(PlayerPreThink, EV_PlayerPreThink);
 MUTATOR_HOOKABLE(GetPressedKeys, EV_GetPressedKeys);
 
 /** is meant to call GetCvars_handle*(get_cvars_s, get_cvars_f, cvarfield, "cvarname") for cvars this mutator needs from the client */
+// NOTE: requesting cvar values (get_cvars_f 0) is deprecated
 #define EV_GetCvars(i, o) \
     /**/ i(float, get_cvars_f) \
     /**/ i(string, get_cvars_s) \
@@ -1222,3 +1223,18 @@ MUTATOR_HOOKABLE(Unfreeze, EV_Unfreeze);
     /**/                            o(int, MUTATOR_ARGV_0_int) \
     /**/
 MUTATOR_HOOKABLE(GetPlayerLimit, EV_GetPlayerLimit);
+
+/** include special item codes for a death to the game log */
+#define EV_LogDeath_AppendItemCodes(i, o) \
+    /** player */         i(entity, MUTATOR_ARGV_0_entity) \
+    /** item codes */     i(string, MUTATOR_ARGV_1_string) \
+    /**/                  o(string, MUTATOR_ARGV_1_string) \
+    /**/
+MUTATOR_HOOKABLE(LogDeath_AppendItemCodes, EV_LogDeath_AppendItemCodes);
+
+/** Allows disabling or enabling rocket jumping independently of balance, use the parameter to force a preferred setting */
+#define EV_AllowRocketJumping(i, o) \
+    /** allow_rocketjump */         i(bool, MUTATOR_ARGV_0_bool) \
+    /**/                            o(bool, MUTATOR_ARGV_0_bool) \
+    /**/
+MUTATOR_HOOKABLE(AllowRocketJumping, EV_AllowRocketJumping);
index b8d3c903c541cab860c1f596bf118037d534d017..9e67050cb654b23c9847c8b2e94bda0f1898b106 100644 (file)
@@ -329,9 +329,8 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                if (time < this.spawnshieldtime && autocvar_g_spawnshield_blockdamage < 1)
                        damage *= 1 - max(0, autocvar_g_spawnshield_blockdamage);
 
-               if(DEATH_ISWEAPON(deathtype, WEP_TUBA))
+               if(deathtype & HITTYPE_SOUND) // sound based attacks cause bleeding from the ears
                {
-                       // tuba causes blood to come out of the ears
                        vector ear1, ear2;
                        vector d;
                        float f;
@@ -399,7 +398,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
        if(sound_allowed(MSG_BROADCAST, attacker))
        {
-               if (save > 10)
+               if (save > 10 && (dh - take) > 0) // don't play armor sound if the attack is fatal
                        sound (this, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
                else if (take > 30)
                        sound (this, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
index b3241838b039ef1523703f759856d86053e8c0b8..9a12a04866c2c251fdd333725f0a22c4af757fff 100644 (file)
 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 
 IntrusiveList g_race_targets;
-STATIC_INIT(g_race_targets) { g_race_targets = IL_NEW(); }
+IntrusiveList g_racecheckpoints;
+STATIC_INIT(g_race)
+{
+       g_race_targets = IL_NEW();
+       g_racecheckpoints = IL_NEW();
+}
 
 void race_InitSpectator()
 {
index 4402e22568ce1f027c26f93e6cba1a0e339f278c..4dafbcf63710615df0b75b9ee07df04f4e9718d6 100644 (file)
@@ -31,9 +31,6 @@ float race_completing;
 .float race_respawn_checkpoint;
 .entity race_respawn_spotref; // try THIS spawn in case you respawn
 
-IntrusiveList g_racecheckpoints;
-STATIC_INIT(g_racecheckpoints) { g_racecheckpoints = IL_NEW(); }
-
 // definitions for functions used outside race.qc
 float race_PreviousCheckpoint(float f);
 float race_NextCheckpoint(float f);
index 03b40c5e12864aa7570c19ff0169c0ec107162b2..730c92884f75b09ddf7ff1cf890a610272ad084e 100644 (file)
@@ -7,6 +7,7 @@
 #include "../common/constants.qh"
 #include <common/net_linked.qh>
 #include "../common/teams.qh"
+#include <common/mapinfo.qh>
 #include "../common/mapobjects/subs.qh"
 #include "../common/mapobjects/target/spawnpoint.qh"
 #include "../common/util.qh"
@@ -262,7 +263,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
                        }
                }
 
-               if(!found)
+               if(!found && !g_cts)
                {
                        LOG_TRACE("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target);
                        return '-1 0 0';
index 92c918f00ca2281d360282312cfc3b3b9e1fc5df..310835c5cedb08b07a1f9e2fdff212c36308f1b8 100644 (file)
@@ -17,7 +17,7 @@
 /**
     Uniform push from a point
 **/
-#define steerlib_push(ent,point) normalize(ent.origin - point)
+#define steerlib_push(ent,point) normalize((ent).origin - point)
 /*
 vector steerlib_push(entity this, vector point)
 {
@@ -29,7 +29,7 @@ vector steerlib_push(entity this, vector point)
 **/
 vector steerlib_arrive(entity this, vector point, float maximal_distance)
 {
-    float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
+    float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
     vector direction = normalize(point - this.origin);
     return  direction * (distance / maximal_distance);
 }
@@ -39,21 +39,21 @@ vector steerlib_arrive(entity this, vector point, float maximal_distance)
 **/
 vector steerlib_attract(entity this, vector point, float maximal_distance)
 {
-    float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
+    float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
     vector direction = normalize(point - this.origin);
 
-    return  direction * (1-(distance / maximal_distance));
+    return  direction * (1 - (distance / maximal_distance));
 }
 
-vector steerlib_attract2(entity this, vector point, float min_influense,float max_distance,float max_influense)
+vector steerlib_attract2(entity this, vector point, float min_influense, float max_distance, float max_influense)
 {
-    float distance  = bound(0.00001,vlen(this.origin - point),max_distance);
+    float distance = bound(0.00001, vlen(this.origin - point), max_distance);
     vector direction = normalize(point - this.origin);
 
     float influense = 1 - (distance / max_distance);
     influense = min_influense + (influense * (max_influense - min_influense));
 
-    return  direction * influense;
+    return direction * influense;
 }
 
 /*
@@ -89,27 +89,21 @@ vector steerlib_attract2(vector point, float maximal_distance,float min_influens
 /**
     Move away from a point.
 **/
-vector steerlib_repell(entity this, vector point,float maximal_distance)
+vector steerlib_repel(entity this, vector point, float maximal_distance)
 {
-    float distance;
-    vector direction;
-
-    distance = bound(0.001,vlen(this.origin - point),maximal_distance);
-    direction = normalize(this.origin - point);
+    float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
+    vector direction = normalize(this.origin - point);
 
-    return  direction * (1-(distance / maximal_distance));
+    return  direction * (1 - (distance / maximal_distance));
 }
 
 /**
     Try to keep at ideal_distance away from point
 **/
-vector steerlib_standoff(entity this, vector point,float ideal_distance)
+vector steerlib_standoff(entity this, vector point, float ideal_distance)
 {
-    float distance;
     vector direction;
-
-    distance = vlen(this.origin - point);
-
+    float distance = vlen(this.origin - point);
 
     if(distance < ideal_distance)
     {
@@ -123,22 +117,22 @@ vector steerlib_standoff(entity this, vector point,float ideal_distance)
 }
 
 /**
-    A random heading in a forward halfcicrle
+    A random heading in a forward semicircle
 
-    use like:
-    this.target = steerlib_wander(256,32,this.target)
+    usage:
+    this.target = steerlib_wander(256, 32, this.target)
 
-    where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
+    where range is the circle radius and threshold is how close we need to be to pick a new heading.
+    Assumes v_forward is set by makevectors
 **/
-vector steerlib_wander(entity this, float range, float tresh, vector oldpoint)
+vector steerlib_wander(entity this, float range, float threshold, vector oldpoint)
 {
-    vector wander_point;
-    wander_point = v_forward - oldpoint;
+    vector wander_point = v_forward - oldpoint;
 
-    if (vdist(wander_point, >, tresh))
+    if (vdist(wander_point, >, threshold))
         return oldpoint;
 
-    range = bound(0,range,1);
+    range = bound(0, range, 1);
 
     wander_point = this.origin + v_forward * 128;
     wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
@@ -147,17 +141,15 @@ vector steerlib_wander(entity this, float range, float tresh, vector oldpoint)
 }
 
 /**
-    Dodge a point. dont work to well.
+    Dodge a point NOTE: doesn't work well
 **/
 vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
 {
-    float distance;
-
-    distance = max(vlen(this.origin - point),min_distance);
+    float distance = max(vlen(this.origin - point), min_distance);
     if (min_distance < distance)
         return '0 0 0';
 
-    return dodge_dir * (min_distance/distance);
+    return dodge_dir * (min_distance / distance);
 }
 
 /**
@@ -165,20 +157,19 @@ vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_dis
     Group will move towards the unified direction while keeping close to eachother.
 **/
 .float flock_id;
-vector steerlib_flock(entity this, float _radius, float standoff,float separation_force,float flock_force)
+vector steerlib_flock(entity this, float _radius, float standoff, float separation_force, float flock_force)
 {
-    entity flock_member;
     vector push = '0 0 0', pull = '0 0 0';
-    float ccount = 0;
+    int ccount = 0;
 
-    flock_member = findradius(this.origin, _radius);
+    entity flock_member = findradius(this.origin, _radius);
     while(flock_member)
     {
         if(flock_member != this)
         if(flock_member.flock_id == this.flock_id)
         {
             ++ccount;
-            push = push + (steerlib_repell(this, flock_member.origin,standoff) * separation_force);
+            push = push + (steerlib_repel(this, flock_member.origin,standoff) * separation_force);
             pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
         }
         flock_member = flock_member.chain;
@@ -191,20 +182,19 @@ vector steerlib_flock(entity this, float _radius, float standoff,float separatio
     Group will move towards the unified direction while keeping close to eachother.
     xy only version (for ground movers).
 **/
-vector steerlib_flock2d(entity this, float _radius, float standoff,float separation_force,float flock_force)
+vector steerlib_flock2d(entity this, float _radius, float standoff, float separation_force, float flock_force)
 {
-    entity flock_member;
     vector push = '0 0 0', pull = '0 0 0';
-    float ccount = 0;
+    int ccount = 0;
 
-    flock_member = findradius(this.origin,_radius);
+    entity flock_member = findradius(this.origin,_radius);
     while(flock_member)
     {
         if(flock_member != this)
         if(flock_member.flock_id == this.flock_id)
         {
             ++ccount;
-            push = push + (steerlib_repell(this, flock_member.origin, standoff) * separation_force);
+            push = push + (steerlib_repel(this, flock_member.origin, standoff) * separation_force);
             pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
         }
         flock_member = flock_member.chain;
@@ -218,25 +208,23 @@ vector steerlib_flock2d(entity this, float _radius, float standoff,float separat
 
 /**
     All members want to be in the center, and keep away from eachother.
-    The furtehr form the center the more they want to be there.
+    The further from the center the more they want to be there.
 
     This results in a aligned movement (?!) much like flocking.
 **/
-vector steerlib_swarm(entity this, float _radius, float standoff,float separation_force,float swarm_force)
+vector steerlib_swarm(entity this, float _radius, float standoff, float separation_force, float swarm_force)
 {
-    entity swarm_member;
     vector force = '0 0 0', center = '0 0 0';
-    float ccount = 0;
-
-    swarm_member = findradius(this.origin,_radius);
+    int ccount = 0;
 
+    entity swarm_member = findradius(this.origin,_radius);
     while(swarm_member)
     {
         if(swarm_member.flock_id == this.flock_id)
         {
             ++ccount;
             center = center + swarm_member.origin;
-            force = force + (steerlib_repell(this, swarm_member.origin,standoff) * separation_force);
+            force = force + (steerlib_repel(this, swarm_member.origin,standoff) * separation_force);
         }
         swarm_member = swarm_member.chain;
     }
@@ -252,93 +240,80 @@ vector steerlib_swarm(entity this, float _radius, float standoff,float separatio
     Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
     You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
 **/
-vector steerlib_traceavoid(entity this, float pitch,float length)
+vector steerlib_traceavoid(entity this, float pitch, float length)
 {
-    vector vup_left,vup_right,vdown_left,vdown_right;
-    float fup_left,fup_right,fdown_left,fdown_right;
-    vector upwish,downwish,leftwish,rightwish;
-    vector v_left,v_down;
-
+    vector v_left = v_right * -1;
+    vector v_down = v_up * -1;
 
-    v_left = v_right * -1;
-    v_down = v_up * -1;
-
-    vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
-    traceline(this.origin, this.origin +  vup_left,MOVE_NOMONSTERS,this);
-    fup_left = trace_fraction;
+    vector vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
+    traceline(this.origin, this.origin +  vup_left, MOVE_NOMONSTERS, this);
+    float fup_left = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
 
-    vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
-    traceline(this.origin,this.origin + vup_right ,MOVE_NOMONSTERS,this);
-    fup_right = trace_fraction;
+    vector vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
+    traceline(this.origin, this.origin + vup_right, MOVE_NOMONSTERS, this);
+    float fup_right = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
 
-    vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
-    traceline(this.origin,this.origin + vdown_left,MOVE_NOMONSTERS,this);
-    fdown_left = trace_fraction;
+    vector vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
+    traceline(this.origin, this.origin + vdown_left, MOVE_NOMONSTERS, this);
+    float fdown_left = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
 
-    vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
-    traceline(this.origin,this.origin + vdown_right,MOVE_NOMONSTERS,this);
-    fdown_right = trace_fraction;
+    vector vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
+    traceline(this.origin, this.origin + vdown_right, MOVE_NOMONSTERS, this);
+    float fdown_right = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
-    upwish    = v_up    * (fup_left   + fup_right);
-    downwish  = v_down  * (fdown_left + fdown_right);
-    leftwish  = v_left  * (fup_left   + fdown_left);
-    rightwish = v_right * (fup_right  + fdown_right);
+    vector upwish    = v_up    * (fup_left   + fup_right);
+    vector downwish  = v_down  * (fdown_left + fdown_right);
+    vector leftwish  = v_left  * (fup_left   + fdown_left);
+    vector rightwish = v_right * (fup_right  + fdown_right);
 
-    return (upwish+leftwish+downwish+rightwish) * 0.25;
+    return (upwish + leftwish + downwish + rightwish) * 0.25;
 
 }
 
 /**
     Steer towards the direction least obstructed.
     Run tracelines in a forward trident, bias each direction negative if something is found there.
+    You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
 **/
 vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
 {
-    vector vt_left, vt_right,vt_front;
-    float f_left, f_right,f_front;
-    vector leftwish, rightwish,frontwish, v_left;
+    vector v_left = v_right * -1;
 
-    v_left = v_right * -1;
-
-
-    vt_front = v_forward * length;
+    vector vt_front = v_forward * length;
     traceline(this.origin + vofs, this.origin + vofs + vt_front,MOVE_NOMONSTERS,this);
-    f_front = trace_fraction;
+    float f_front = trace_fraction;
 
-    vt_left = (v_forward + (v_left * pitch)) * length;
+    vector vt_left = (v_forward + (v_left * pitch)) * length;
     traceline(this.origin + vofs, this.origin + vofs + vt_left,MOVE_NOMONSTERS,this);
-    f_left = trace_fraction;
+    float f_left = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
 
-    vt_right = (v_forward + (v_right * pitch)) * length;
+    vector vt_right = (v_forward + (v_right * pitch)) * length;
     traceline(this.origin + vofs, this.origin + vofs + vt_right ,MOVE_NOMONSTERS,this);
-    f_right = trace_fraction;
+    float f_right = trace_fraction;
 
     //te_lightning1(NULL,this.origin, trace_endpos);
 
-    leftwish  = v_left    * f_left;
-    rightwish = v_right   * f_right;
-    frontwish = v_forward * f_front;
+    vector leftwish  = v_left    * f_left;
+    vector rightwish = v_right   * f_right;
+    vector frontwish = v_forward * f_front;
 
     return normalize(leftwish + rightwish + frontwish);
 }
 
 //#define BEAMSTEER_VISUAL
-float beamsweep(entity this, vector from, vector dir,float length, float step,float step_up, float step_down)
+float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
 {
-    float i;
-    vector a, b, u, d;
-
-    u = '0 0 1' * step_up;
-    d = '0 0 1' * step_down;
+    vector u = '0 0 1' * step_up;
+    vector d = '0 0 1' * step_down;
 
     traceline(from + u, from - d,MOVE_NORMAL,this);
     if(trace_fraction == 1.0)
@@ -347,11 +322,11 @@ float beamsweep(entity this, vector from, vector dir,float length, float step,fl
     if(!location_isok(trace_endpos, false, false))
         return 0;
 
-    a = trace_endpos;
-    for(i = 0; i < length; i += step)
+    vector a = trace_endpos;
+    for(int i = 0; i < length; i += step)
     {
 
-        b = a + dir * step;
+        vector b = a + dir * step;
         tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,this);
         if(trace_fraction != 1.0)
             return i / length;
@@ -374,31 +349,27 @@ float beamsweep(entity this, vector from, vector dir,float length, float step,fl
 
 vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
 {
-    float bm_forward, bm_right, bm_left,p;
-    vector vr,vl;
-
     dir.z *= 0.15;
-    vr = vectoangles(dir);
-    //vr_x *= -1;
+    vector vr = vectoangles(dir);
+    //vr.x *= -1;
 
     tracebox(this.origin + '0 0 1' * step_up, this.mins, this.maxs, ('0 0 1' * step_up) + this.origin +  (dir * length), MOVE_NOMONSTERS, this);
     if(trace_fraction == 1.0)
     {
-        //te_lightning1(this,this.origin,this.origin +  (dir * length));
+        //te_lightning1(this,this.origin,this.origin + (dir * length));
         return dir;
     }
 
     makevectors(vr);
-    bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
+    float bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
 
     vr = normalize(v_forward + v_right * 0.125);
-    vl = normalize(v_forward - v_right * 0.125);
+    vector vl = normalize(v_forward - v_right * 0.125);
 
-    bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
-    bm_left  = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
+    float bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
+    float bm_left  = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
 
-
-    p = bm_left + bm_right;
+    float p = bm_left + bm_right;
     if(p == 2)
     {
         //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
@@ -435,5 +406,4 @@ vector steerlib_beamsteer(entity this, vector dir, float length, float step, flo
     vl = vl * bm_left;
 
     return normalize(vr + vl);
-
 }
index 9be3c18f6017183f8d81319e0cdb75e4a2d16e51..54c9744332d5033ccbd5518f4f79b29dca36606c 100644 (file)
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/server.qh"
 
-.float lastground;
-.int state;
-
 void CreatureFrame_hotliquids(entity this)
 {
-       if (this.dmgtime < time)
+       if (this.dmgtime >= time)
        {
-               this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+               return;
+       }
 
-               if (this.flags & FL_PROJECTILE)
-               {
-                       if (this.watertype == CONTENT_LAVA)
-                               Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
-                       else if (this.watertype == CONTENT_SLIME)
-                               Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
-               }
-               else
+       this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+
+       if (this.flags & FL_PROJECTILE)
+       {
+               if (this.watertype == CONTENT_LAVA)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+               else if (this.watertype == CONTENT_SLIME)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+       }
+       else
+       {
+               if (this.watertype == CONTENT_LAVA)
                {
-                       if (this.watertype == CONTENT_LAVA)
+                       if (this.watersound_finished < time)
                        {
-                               if (this.watersound_finished < time)
-                               {
-                                       this.watersound_finished = time + 0.5;
-                                       sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
-                               }
-                               Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
-                               if(autocvar_g_balance_contents_playerdamage_lava_burn)
-                                       Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+                               this.watersound_finished = time + 0.5;
+                               sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
                        }
-                       else if (this.watertype == CONTENT_SLIME)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                       if(autocvar_g_balance_contents_playerdamage_lava_burn)
+                               Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+               }
+               else if (this.watertype == CONTENT_SLIME)
+               {
+                       if (this.watersound_finished < time)
                        {
-                               if (this.watersound_finished < time)
-                               {
-                                       this.watersound_finished = time + 0.5;
-                                       sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
-                               }
-                               Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                               this.watersound_finished = time + 0.5;
+                               sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
                        }
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
                }
        }
 }
@@ -96,35 +95,36 @@ void CreatureFrame_Liquids(entity this)
 
 void CreatureFrame_FallDamage(entity this)
 {
-       if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
-       if(this.velocity || this.oldvelocity) // moving or has moved
+       if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
+               return; // vehicles and projectiles don't receive fall damage
+       if(!(this.velocity || this.oldvelocity))
+               return; // if the entity hasn't moved and isn't moving, then don't do anything
+
+       // check for falling damage
+       float velocity_len = vlen(this.velocity);
+       bool have_hook = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               // check for falling damage
-               float velocity_len = vlen(this.velocity);
-               bool have_hook = false;
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           .entity weaponentity = weaponentities[slot];
+           if(this.(weaponentity).hook && this.(weaponentity).hook.state)
            {
-               .entity weaponentity = weaponentities[slot];
-               if(this.(weaponentity).hook && this.(weaponentity).hook.state)
-               {
-                       have_hook = true;
-                       break;
-               }
+               have_hook = true;
+               break;
            }
-               if(!have_hook)
-               {
-                       float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
-                       if (IS_DEAD(this))
-                               dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
-                       else
-                               dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
-                       if (dm > 0)
-                               Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
-               }
-
-               if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
-                       Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
        }
+       if(!have_hook)
+       {
+               float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+               if (IS_DEAD(this))
+                       dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+               else
+                       dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+               if (dm > 0)
+                       Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
+       }
+
+       if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+               Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
 }
 
 void CreatureFrame_All()
@@ -324,14 +324,17 @@ void SV_OnEntityPreSpawnFunction(entity this)
        if (this.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
        {
-               goto cleanup;
+               delete(this);
+               return;
        }
        if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
-        goto cleanup;
+               delete(this);
+               return;
        }
 
        if (DoesQ3ARemoveThisEntity(this)) {
-               goto cleanup;
+               delete(this);
+               return;
        }
 
        set_movetype(this, this.movetype);
@@ -356,11 +359,9 @@ void SV_OnEntityPreSpawnFunction(entity this)
     #undef X
 
        if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) {
-               goto cleanup;
+               delete(this);
+               return;
        }
-       return;
-LABEL(cleanup)
-    delete(this);
 }
 
 void WarpZone_PostInitialize_Callback()
index 93480cf282ec6c5377ac13197eea0dbe009ddfd2..46284fde2e51f134609dc067532d25428d8de487 100644 (file)
@@ -2,6 +2,11 @@
 
 bool expr_evaluate(string s);
 
+#ifdef PROFILING
+float client_cefc_accumulator;
+float client_cefc_accumulatortime;
+#endif
+
 /*
 ==================
 main
index 7f9c6ad0d76c379481cb3613fe3b322b0d7ecdff..f1866eab089311a0ce2c2a052d6b9b3fbaf00031 100644 (file)
@@ -70,7 +70,7 @@ bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andam
        {
                if (andammo)
                {
-                       if(this.items & IT_UNLIMITED_WEAPON_AMMO)
+                       if(this.items & IT_UNLIMITED_AMMO)
                        {
                                f = 1;
                        }
index ba17d3f1f893bdb2c42a7aa89fa4e674867ba548..23a3ee67d6aa5ab8d2ba95d302f2b7514ecbdc39 100644 (file)
@@ -26,22 +26,21 @@ string W_Apply_Weaponreplace(string in)
        return out;
 }
 
-void weapon_defaultspawnfunc(entity this, Weapon e)
+void weapon_defaultspawnfunc(entity this, Weapon wpn)
 {
-       Weapon wpn = e;
-       e = wpn = wpn.m_spawnfunc_hookreplace(wpn, this);
+       wpn = wpn.m_spawnfunc_hookreplace(wpn, this);
        this.classname = wpn.m_canonical_spawnfunc;
        if (!Item_IsLoot(this) && !this.m_isreplaced)
        {
-               if (e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
+               if (wpn.spawnflags & WEP_FLAG_MUTATORBLOCKED)
                {
                        LOG_WARNF("Attempted to spawn a mutator-blocked weapon rejected: prvm_edict server %i", this);
                        startitem_failed = true;
                        return;
                }
 
-               string s = W_Apply_Weaponreplace(e.netname);
-               MUTATOR_CALLHOOK(SetWeaponreplace, this, e, s);
+               string s = W_Apply_Weaponreplace(wpn.netname);
+               MUTATOR_CALLHOOK(SetWeaponreplace, this, wpn, s);
                s = M_ARGV(2, string);
                if (s == "")
                {
@@ -79,6 +78,9 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
        }
 
+       if(!Item_IsLoot(this))
+               weaponsInMapAll |= WepSet_FromWeapon(wpn);
+
        if (!Item_IsDefinitionAllowed(wpn.m_pickup))
        {
                delete(this);
index 74420b3335b2f5513ff9ac045b626412ddb62d2d..06bebeba2746f09b57e3cc37e6f0c4c95075f5c5 100644 (file)
@@ -213,10 +213,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 
 void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
 {
-       entity pseudoprojectile = NULL;
-
        vector dir = normalize(end - start);
-       //float max_length = vlen(end - start);
        vector force = dir * bforce;
 
        // go a little bit into the wall because we need to hit this wall later
@@ -273,42 +270,31 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector
                it.solid = it.railgunhitsolidbackup;
        });
 
-       // spawn a temporary explosion entity for RadiusDamage calls
-       //explosion = spawn();
-
-       // Find all non-hit players the beam passed close by
-       float length = vlen(trace_endpos - start);
-       if(deathtype == WEP_VAPORIZER.m_id || deathtype == WEP_VORTEX.m_id) // WEAPONTODO
-       {
-               FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
-                       if (!it.railgunhit && !(IS_SPEC(it) && it.enemy == this))
-                       {
-                               // nearest point on the beam
-                               vector beampos = start + dir * bound(0, (it.origin - start) * dir, length);
+       // Find all players the beam passed close by (even those hit)
+       float length = vlen(endpoint - start);
+       entity pseudoprojectile = NULL;
+       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
+               // not when spectating the shooter
+               if (IS_SPEC(it) && it.enemy == this) continue;
 
-                               float f = bound(0, 1 - vlen(beampos - it.origin) / 512, 1);
-                               if(f <= 0)
-                                       continue;
+               // nearest point on the beam
+               vector beampos = start + dir * bound(0, (it.origin - start) * dir, length);
 
-                               if(!pseudoprojectile)
-                                       pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
-                               msg_entity = it;
-                               soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASE * f, ATTEN_NONE);
-                       }
-               });
+               if(!pseudoprojectile)
+                       pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
 
-               if(pseudoprojectile)
-                       delete(pseudoprojectile);
-       }
+               msg_entity = it;
+               // we want this to be very loud when close but fall off quickly -> using max base volume and high attenuation
+               soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASEVOICE, ATTEN_IDLE);
+       });
+       if(pseudoprojectile)
+               delete(pseudoprojectile);
 
        // find all the entities the railgun hit and hurt them
        IL_EACH(g_railgunhit, it.railgunhit,
        {
                // removal from the list is handled below
 
-               // get the details we need to call the damage function
-               vector hitloc = it.railgunhitloc;
-
                float foff = ExponentialFalloff(mindist, maxdist, halflifedist, it.railgundistance);
                float ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, it.railgundistance);
 
@@ -317,11 +303,7 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector
 
                // apply the damage
                if (it.takedamage)
-                       Damage (it, this, this, bdamage * foff, deathtype, weaponentity, hitloc, it.railgunforce * ffs);
-
-               // create a small explosion to throw gibs around (if applicable)
-               //setorigin(explosion, hitloc);
-               //RadiusDamage (explosion, this, 10, 0, 50, NULL, NULL, 300, deathtype);
+                       Damage(it, this, this, bdamage * foff, deathtype, weaponentity, it.railgunhitloc, it.railgunforce * ffs);
 
                it.railgunhitloc = '0 0 0';
                it.railgunhitsolidbackup = SOLID_NOT;
@@ -348,25 +330,19 @@ void fireBullet_trace_callback(vector start, vector hit, vector end)
        fireBullet_last_hit = NULL;
 }
 
-void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect)
+void fireBullet_antilag(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect, bool do_antilag)
 {
-       vector  end;
-
        dir = normalize(dir + randomvec() * spread);
-       end = start + dir * max_shot_distance;
+       vector end = start + dir * max_shot_distance;
 
        fireBullet_last_hit = NULL;
        fireBullet_trace_callback_eff = tracer_effect;
 
-       float solid_penetration_left = 1;
+       float solid_penetration_fraction = 1;
+       float damage_fraction = 1;
        float total_damage = 0;
 
-       float lag = ((IS_REAL_CLIENT(this)) ? ANTILAG_LATENCY(this) : 0);
-       if(lag < 0.001)
-               lag = 0;
-       bool noantilag = ((IS_CLIENT(this)) ? CS(this).cvar_cl_noantilag : false);
-       if(autocvar_g_antilag == 0 || noantilag)
-               lag = 0; // only do hitscan, but no antilag
+       float lag = ((do_antilag) ? antilag_getlag(this) : 0);
        if(lag)
                antilag_takeback_all(this, lag);
 
@@ -379,7 +355,6 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
 
        for (;;)
        {
-               // TODO also show effect while tracing
                WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, false, WarpZone_trace_forent, NULL, fireBullet_trace_callback);
                dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir);
                end = WarpZone_TransformOrigin(WarpZone_trace_transform, end);
@@ -417,7 +392,7 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                        is_weapclip = true;
 
                if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
-                       Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, this);
+                       Damage_DamageInfo(start, damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this);
 
                if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit)  // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug).
                {
@@ -426,13 +401,13 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                        MUTATOR_CALLHOOK(FireBullet_Hit, this, hit, start, end, damage, this.(weaponentity));
                        damage = M_ARGV(4, float);
                        bool gooddamage = accuracy_isgooddamage(this, hit);
-                       Damage(hit, this, this, damage * solid_penetration_left, dtype, weaponentity, start, force * dir * solid_penetration_left);
+                       Damage(hit, this, this, damage * damage_fraction, dtype, weaponentity, start, force * dir * damage_fraction);
                        // calculate hits for ballistic weapons
                        if(gooddamage)
                        {
                                // do not exceed 100%
-                               float added_damage = min(damage - total_damage, damage * solid_penetration_left);
-                               total_damage += damage * solid_penetration_left;
+                               float added_damage = min(damage - total_damage, damage * damage_fraction);
+                               total_damage += damage * damage_fraction;
                                accuracy_add(this, this.(weaponentity).m_weapon, 0, added_damage);
                        }
                }
@@ -454,9 +429,9 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                else if(hitstore.ballistics_density < 0)
                        maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance
                else if(hitstore.ballistics_density == 0)
-                       maxdist = max_solid_penetration * solid_penetration_left;
+                       maxdist = max_solid_penetration * solid_penetration_fraction;
                else
-                       maxdist = max_solid_penetration * solid_penetration_left * hitstore.ballistics_density;
+                       maxdist = max_solid_penetration * solid_penetration_fraction / hitstore.ballistics_density;
 
                if(maxdist <= autocvar_g_ballistics_mindistance)
                        break;
@@ -468,10 +443,10 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                        break;
 
                float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start));
-               // fraction_used_of_what_is_left = dist_taken / maxdist
-               // solid_penetration_left = solid_penetration_left - solid_penetration_left * fraction_used_of_what_is_left
-               solid_penetration_left *= 1 - dist_taken / maxdist;
-               solid_penetration_left = max(solid_penetration_left, 0);
+               float fraction_used_of_what_is_left = dist_taken / maxdist;
+               solid_penetration_fraction -= solid_penetration_fraction * fraction_used_of_what_is_left;
+               solid_penetration_fraction = max(solid_penetration_fraction, 0);
+               damage_fraction = pow(solid_penetration_fraction, autocvar_g_ballistics_solidpenetration_exponent);
 
                // Only show effect when going through a player (invisible otherwise)
                if (hit && (hit.solid != SOLID_BSP))
@@ -481,7 +456,7 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                start = trace_endpos;
 
                if(hit.solid == SOLID_BSP)
-                       Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, this);
+                       Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this);
        }
 
        if(lag)
@@ -491,3 +466,8 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
        if(this)
                this.dphitcontentsmask = oldsolid;
 }
+
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect)
+{
+       fireBullet_antilag(this, weaponentity, start, dir, spread, max_solid_penetration, damage, force, dtype, tracer_effect, true);
+}
index 9e39ecc350aef29a8fe369baaba53ff513aa4a49..5acbda9a5ff98788bd7745426de853ebb4d00f94 100644 (file)
@@ -57,4 +57,5 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector
 entity fireBullet_trace_callback_eff;
 entity fireBullet_last_hit;
 void fireBullet_trace_callback(vector start, vector hit, vector end);
+void fireBullet_antilag(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect, bool do_antilag);
 void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect);
index b75881127a219008f56faaad9d086817d922ab4c..d593658a3d2a5bac7b265ebe06331dfa16f508a4 100644 (file)
@@ -163,6 +163,7 @@ void CL_ExteriorWeaponentity_Think(entity this)
     Weapon wep = this.owner.(weaponentity).m_weapon;
        if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors, this.owner.(weaponentity));
        this.colormap = this.owner.colormap;
+       this.skin = w_ent.skin;
 
        CSQCMODEL_AUTOUPDATE(this);
 }
@@ -223,7 +224,7 @@ void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 .float prevwarntime;
 bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
 {
-       if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
+       if ((actor.items & IT_UNLIMITED_AMMO)) return true;
        bool ammo = false;
        if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
        else ammo = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
@@ -687,7 +688,7 @@ void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector
 void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
 {
        if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity), ammo_use)) return;
-       if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
+       if ((actor.items & IT_UNLIMITED_AMMO) && !wep.reloading_ammo) return;
 
        ammo_use = M_ARGV(2, float);
 
@@ -734,7 +735,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
        w_ent.clip_load = w_ent.old_clip_load;  // restore the ammo counter, in case we still had ammo in the weapon before reloading
 
        // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
-       if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_type == RES_NONE)
+       if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_AMMO) || wpn.ammo_type == RES_NONE)
        {
                w_ent.clip_load = w_ent.reload_ammo_amount;
        }
@@ -790,7 +791,7 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
        {
                if (!GetResource(actor, e.ammo_type) && this.reload_ammo_min)
                {
-                       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+                       if (!(actor.items & IT_UNLIMITED_AMMO))
                        {
                                if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                                {
@@ -808,7 +809,6 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
                        }
                }
        }
-
        if (this)
        {
                if (this.wframe == WFRAME_RELOAD) return;
index 20740d9a86482beef2dfb4c14e375453ffc71ec0..843347eca90813878a3501a4b53a5cf5260742c3 100644 (file)
@@ -7,22 +7,22 @@ exec balance-xdf.cfg
 exec physicsXDF.cfg
 
 // general gameplay
-// set g_jump_grunt 1 // just no
-set g_shootfromcenter 1 // hit where you point at with the crosshair (almost so, no shooteye because it's really ugly)
-set g_balance_kill_antispam 0
-set g_forced_respawn 1
+// g_jump_grunt 1 // just no
+g_shootfromcenter 1 // hit where you point at with the crosshair (almost so, no shooteye because it's really ugly)
+g_balance_kill_antispam 0
+g_forced_respawn 1
 // g_playerclip_collisions 0 // do not check playerclips
-set g_powerups 0  // set to -1 or patch xonotic
-set g_spawnpoints_auto_move_out_of_solid 1
-set g_start_delay 3
-set g_use_ammunition 0 "if set to 0 all weapons have unlimited ammunition"
-set g_weapon_stay 1 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
-set teamplay_mode 2 // friendly fire and self damage
-set sv_vote_nospectators 1
-set timelimit_override 20
-set g_buffs_cooldown_respawn 0.1
+g_powerups 0  // set to -1 or patch xonotic
+g_spawnpoints_auto_move_out_of_solid 1
+g_start_delay 3
+g_use_ammunition 0
+g_weapon_stay 1
+teamplay_mode 2 // friendly fire and self damage
+sv_vote_nospectators 1
+timelimit_override 20
+g_buffs_cooldown_respawn 0.1
+g_buffs_randomize 0
 
 // game mode settings
-set g_cts_finish_kill_delay 2
-set g_cts_respawn_delay 0
-set g_cts_selfdamage 0
+g_cts_finish_kill_delay 2
+g_cts_selfdamage 0
index 67589147b634f9968c2b1e6af4b906c37a3af9c1..817b9f1eafa092c450177aefe8b55b7879da74d0 100644 (file)
@@ -6,23 +6,23 @@ exec xonotic-server.cfg
 exec balance-xpm.cfg
 
 // general gameplay
-set g_norecoil 1
-set g_shootfromeye 1 // hit where you point at with the crosshair (promoders don't care about ugliness)
-set g_balance_kill_antispam 0
-set g_forced_respawn 1
-set teamplay_mode 2 // friendly fire and self damage
-set sv_vote_nospectators 1
-set g_chat_nospectators 2
-set g_warmup 1
-set g_warmup_limit 0
-set g_balance_teams 0
-set g_spawnshieldtime 0
-set g_spawn_furthest 1
-set sv_autoscreenshot 1
-set sv_ready_restart 1
-set sv_ready_restart_after_countdown 1
-set g_monsters 0
-set g_turrets 0
-set g_vehicles 0
-set sv_showspectators 0
-set sv_taunt 0
+g_norecoil 1
+g_shootfromeye 1 // hit where you point at with the crosshair (promoders don't care about ugliness)
+g_balance_kill_antispam 0
+g_forced_respawn 1
+teamplay_mode 2 // friendly fire and self damage
+sv_vote_nospectators 1
+g_chat_nospectators 2
+g_warmup 1
+g_warmup_limit 0
+g_balance_teams 0
+g_spawnshieldtime 0
+g_spawn_furthest 1
+sv_autoscreenshot 1
+sv_ready_restart 1
+sv_ready_restart_after_countdown 1
+g_monsters 0
+g_turrets 0
+g_vehicles 0
+sv_showspectators 0
+sv_taunt 0
index 15086f22a698106da5983dbf0ed02c0865cd0ff4..cb39b2a10ce1a16c1b5cb554be256a42e01c52f5 100644 (file)
@@ -8,31 +8,29 @@ exec physicsOverkill.cfg
 exec randomitems-overkill.cfg
 if_dedicated exec help-overkill.cfg
 
-// general gameplay
-set g_overkill 1
+g_overkill 1
 
 // hack - eventually, we should be able to choose overkill models in menu like for vanilla
-set sv_defaultcharacter 1
-set sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-set sv_defaultplayermodel_red "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
-set sv_defaultplayermodel_blue "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-set sv_defaultplayermodel_yellow "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
-set sv_defaultplayermodel_pink "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-
-set g_respawn_ghosts 0
-
-set g_nades 1
-set g_nades_nade_small 1
-set g_nades_spread 0
-set g_nades_nade_refire 10
-set g_nades_nade_newton_style 2
-
-set g_dodging 1
-set sv_dodging_wall_dodging 1
-
-set g_spawn_near_teammate "!g_assault !g_freezetag"
-set g_spawn_near_teammate_ignore_spawnpoint 1
-set g_spawnshieldtime 0.5
-set g_respawn_delay_forced 2
-
-set g_lms_start_armor 100
+sv_defaultcharacter 1
+sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+sv_defaultplayermodel_red "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
+sv_defaultplayermodel_blue "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+sv_defaultplayermodel_yellow "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
+sv_defaultplayermodel_pink "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+
+g_fullbrightplayers 1
+g_respawn_ghosts 0
+
+g_nades 1
+g_nades_nade_small 1
+g_nades_spread 0
+g_nades_nade_refire 10
+g_nades_nade_newton_style 2
+
+g_dodging 1
+sv_dodging_wall_dodging 1
+
+g_spawn_near_teammate "!g_assault !g_freezetag"
+g_spawn_near_teammate_ignore_spawnpoint 1
+g_spawnshieldtime 0.5
+g_respawn_delay_forced 2
diff --git a/sound/misc/armor1.ogg b/sound/misc/armor1.ogg
new file mode 100644 (file)
index 0000000..b781feb
Binary files /dev/null and b/sound/misc/armor1.ogg differ
diff --git a/sound/misc/armor1.wav b/sound/misc/armor1.wav
deleted file mode 100644 (file)
index 4ee6230..0000000
Binary files a/sound/misc/armor1.wav and /dev/null differ
diff --git a/sound/misc/armor10.ogg b/sound/misc/armor10.ogg
new file mode 100644 (file)
index 0000000..5f8c142
Binary files /dev/null and b/sound/misc/armor10.ogg differ
diff --git a/sound/misc/armor10.wav b/sound/misc/armor10.wav
deleted file mode 100644 (file)
index 7ba2edf..0000000
Binary files a/sound/misc/armor10.wav and /dev/null differ
diff --git a/sound/misc/armor17_5.ogg b/sound/misc/armor17_5.ogg
new file mode 100644 (file)
index 0000000..6931ed7
Binary files /dev/null and b/sound/misc/armor17_5.ogg differ
diff --git a/sound/misc/armor17_5.wav b/sound/misc/armor17_5.wav
deleted file mode 100644 (file)
index eafad59..0000000
Binary files a/sound/misc/armor17_5.wav and /dev/null differ
diff --git a/sound/misc/armor25.ogg b/sound/misc/armor25.ogg
new file mode 100644 (file)
index 0000000..a5a02fa
Binary files /dev/null and b/sound/misc/armor25.ogg differ
diff --git a/sound/misc/armor25.wav b/sound/misc/armor25.wav
deleted file mode 100644 (file)
index 9aea70c..0000000
Binary files a/sound/misc/armor25.wav and /dev/null differ
diff --git a/sound/misc/armorimpact.ogg b/sound/misc/armorimpact.ogg
new file mode 100644 (file)
index 0000000..9f3274d
Binary files /dev/null and b/sound/misc/armorimpact.ogg differ
diff --git a/sound/misc/armorimpact.wav b/sound/misc/armorimpact.wav
deleted file mode 100644 (file)
index 28c18db..0000000
Binary files a/sound/misc/armorimpact.wav and /dev/null differ
diff --git a/sound/misc/footstep01.ogg b/sound/misc/footstep01.ogg
new file mode 100644 (file)
index 0000000..6091a39
Binary files /dev/null and b/sound/misc/footstep01.ogg differ
diff --git a/sound/misc/footstep01.wav b/sound/misc/footstep01.wav
deleted file mode 100644 (file)
index 5627229..0000000
Binary files a/sound/misc/footstep01.wav and /dev/null differ
diff --git a/sound/misc/footstep02.ogg b/sound/misc/footstep02.ogg
new file mode 100644 (file)
index 0000000..1d6b995
Binary files /dev/null and b/sound/misc/footstep02.ogg differ
diff --git a/sound/misc/footstep02.wav b/sound/misc/footstep02.wav
deleted file mode 100644 (file)
index 736746c..0000000
Binary files a/sound/misc/footstep02.wav and /dev/null differ
diff --git a/sound/misc/footstep03.ogg b/sound/misc/footstep03.ogg
new file mode 100644 (file)
index 0000000..d453ad7
Binary files /dev/null and b/sound/misc/footstep03.ogg differ
diff --git a/sound/misc/footstep03.wav b/sound/misc/footstep03.wav
deleted file mode 100644 (file)
index 2137b65..0000000
Binary files a/sound/misc/footstep03.wav and /dev/null differ
diff --git a/sound/misc/footstep04.ogg b/sound/misc/footstep04.ogg
new file mode 100644 (file)
index 0000000..caacad5
Binary files /dev/null and b/sound/misc/footstep04.ogg differ
diff --git a/sound/misc/footstep04.wav b/sound/misc/footstep04.wav
deleted file mode 100644 (file)
index 06ba93c..0000000
Binary files a/sound/misc/footstep04.wav and /dev/null differ
diff --git a/sound/misc/footstep05.ogg b/sound/misc/footstep05.ogg
new file mode 100644 (file)
index 0000000..4075ed9
Binary files /dev/null and b/sound/misc/footstep05.ogg differ
diff --git a/sound/misc/footstep05.wav b/sound/misc/footstep05.wav
deleted file mode 100644 (file)
index e16d6b3..0000000
Binary files a/sound/misc/footstep05.wav and /dev/null differ
diff --git a/sound/misc/footstep06.ogg b/sound/misc/footstep06.ogg
new file mode 100644 (file)
index 0000000..be9e2b4
Binary files /dev/null and b/sound/misc/footstep06.ogg differ
diff --git a/sound/misc/footstep06.wav b/sound/misc/footstep06.wav
deleted file mode 100644 (file)
index fff0370..0000000
Binary files a/sound/misc/footstep06.wav and /dev/null differ
diff --git a/sound/misc/gib.ogg b/sound/misc/gib.ogg
new file mode 100644 (file)
index 0000000..2b29759
Binary files /dev/null and b/sound/misc/gib.ogg differ
diff --git a/sound/misc/gib.wav b/sound/misc/gib.wav
deleted file mode 100644 (file)
index a26e9ad..0000000
Binary files a/sound/misc/gib.wav and /dev/null differ
diff --git a/sound/misc/gib_splat01.ogg b/sound/misc/gib_splat01.ogg
new file mode 100644 (file)
index 0000000..ba8c8c7
Binary files /dev/null and b/sound/misc/gib_splat01.ogg differ
diff --git a/sound/misc/gib_splat01.wav b/sound/misc/gib_splat01.wav
deleted file mode 100644 (file)
index 9c29b67..0000000
Binary files a/sound/misc/gib_splat01.wav and /dev/null differ
diff --git a/sound/misc/gib_splat02.ogg b/sound/misc/gib_splat02.ogg
new file mode 100644 (file)
index 0000000..de5da8d
Binary files /dev/null and b/sound/misc/gib_splat02.ogg differ
diff --git a/sound/misc/gib_splat02.wav b/sound/misc/gib_splat02.wav
deleted file mode 100644 (file)
index 1b86c1f..0000000
Binary files a/sound/misc/gib_splat02.wav and /dev/null differ
diff --git a/sound/misc/gib_splat03.ogg b/sound/misc/gib_splat03.ogg
new file mode 100644 (file)
index 0000000..8e7a2b4
Binary files /dev/null and b/sound/misc/gib_splat03.ogg differ
diff --git a/sound/misc/gib_splat03.wav b/sound/misc/gib_splat03.wav
deleted file mode 100644 (file)
index a71d8ea..0000000
Binary files a/sound/misc/gib_splat03.wav and /dev/null differ
diff --git a/sound/misc/gib_splat04.ogg b/sound/misc/gib_splat04.ogg
new file mode 100644 (file)
index 0000000..7cf3d76
Binary files /dev/null and b/sound/misc/gib_splat04.ogg differ
diff --git a/sound/misc/gib_splat04.wav b/sound/misc/gib_splat04.wav
deleted file mode 100644 (file)
index 3c1b6d7..0000000
Binary files a/sound/misc/gib_splat04.wav and /dev/null differ
index 8cfae10f605247f87c4f241ed3b62b88928a28f7..816dc141f16c589e6b42c5843d79191afb0b04af 100644 (file)
Binary files a/sound/misc/hitground1.ogg and b/sound/misc/hitground1.ogg differ
index 1f8a7441b43561d064a1d88e30f8466959b94e31..744b19e43569bf64e71b619bc12575913ccaa0d9 100644 (file)
Binary files a/sound/misc/hitground2.ogg and b/sound/misc/hitground2.ogg differ
index 73974a4de470f2f3beab0cb9d150ccb178185fe9..2945bb04f9cbd76b8a474f9452c38b44e8af2253 100644 (file)
Binary files a/sound/misc/hitground3.ogg and b/sound/misc/hitground3.ogg differ
index 0c40620d1604eab1b9c87e1361a99be99bb43f70..d2d8f3bf0c99df83d55fb58357b839125e3b475b 100644 (file)
Binary files a/sound/misc/hitground4.ogg and b/sound/misc/hitground4.ogg differ
index e9a780b6d4fc5d33cf08d3be560ca900706969ad..7ef4ac55db592e5c7b2251818303eb9f06b20957 100644 (file)
Binary files a/sound/misc/itempickup.ogg and b/sound/misc/itempickup.ogg differ
index 503620a8c1b96db78b156de4566401fa5ad45d83..518c7e88cea0e09df4350c62aaf7da49d8e81d0a 100644 (file)
Binary files a/sound/misc/itemrespawn.ogg and b/sound/misc/itemrespawn.ogg differ
index f04e8d619ff495bd938613aee8ecb61897851ca0..c5bc17f678067b18085ff7b2242d5c0389a6afc8 100644 (file)
Binary files a/sound/misc/mediumhealth.ogg and b/sound/misc/mediumhealth.ogg differ
index 6b250ebbd60daaf0538675fb4e04fa314b593b79..c142b5602a46db87f68c7675043aa07febbd9568 100644 (file)
Binary files a/sound/misc/megahealth.ogg and b/sound/misc/megahealth.ogg differ
index 03bee01090caef40675d18674328e41df57edf78..d3cdc975e34cb34979edc94e4dded19dd5bca911 100644 (file)
Binary files a/sound/misc/metalhitground1.ogg and b/sound/misc/metalhitground1.ogg differ
index 50f315f274fc0555e71c49550f3b61a7d979f3f6..70395f197c3493ad9f0de0606cf4f1fe6459ed4b 100644 (file)
Binary files a/sound/misc/metalhitground2.ogg and b/sound/misc/metalhitground2.ogg differ
index 0f3edb1060ff4ee9900e005ebf97a5a863fa4ef4..585df2f457e576da351cfee93dc12fa5d095b35c 100644 (file)
Binary files a/sound/misc/metalhitground3.ogg and b/sound/misc/metalhitground3.ogg differ
index ad2b262557ebfbddfc67c8ec4a553bd4d0e29a1d..2045297aa477adbdbfef54c51338ebabe2e78a57 100644 (file)
Binary files a/sound/misc/metalhitground4.ogg and b/sound/misc/metalhitground4.ogg differ
index 502b34a90da54395e9dd1a9d13a7bf9ab3c0153b..f952a8cdf1a97b8975ff4a56cb712a034ee2be26 100644 (file)
Binary files a/sound/misc/minihealth.ogg and b/sound/misc/minihealth.ogg differ
diff --git a/sound/misc/missile_fly.ogg b/sound/misc/missile_fly.ogg
new file mode 100644 (file)
index 0000000..13e43e6
Binary files /dev/null and b/sound/misc/missile_fly.ogg differ
diff --git a/sound/misc/missile_fly.wav b/sound/misc/missile_fly.wav
deleted file mode 100644 (file)
index a2cd056..0000000
Binary files a/sound/misc/missile_fly.wav and /dev/null differ
diff --git a/sound/misc/poweroff.ogg b/sound/misc/poweroff.ogg
new file mode 100644 (file)
index 0000000..983e241
Binary files /dev/null and b/sound/misc/poweroff.ogg differ
diff --git a/sound/misc/poweroff.wav b/sound/misc/poweroff.wav
deleted file mode 100644 (file)
index 0445276..0000000
Binary files a/sound/misc/poweroff.wav and /dev/null differ
index 517f88bbb1ee50dcaab0aa3e7ce433fe11c9a1d2..f4d9488ac092746a824735f4ad112198a59fb519 100644 (file)
Binary files a/sound/misc/powerup.ogg and b/sound/misc/powerup.ogg differ
index 5169fb1e68487a33932cf99341330d0558a6bb8f..4381a2617e9c174de3fa7b9e933414ba1ac46a0b 100644 (file)
Binary files a/sound/misc/powerup_shield.ogg and b/sound/misc/powerup_shield.ogg differ
diff --git a/sound/misc/shield_respawn.ogg b/sound/misc/shield_respawn.ogg
new file mode 100644 (file)
index 0000000..cb45c9f
Binary files /dev/null and b/sound/misc/shield_respawn.ogg differ
diff --git a/sound/misc/shield_respawn.wav b/sound/misc/shield_respawn.wav
deleted file mode 100644 (file)
index fa0ac1f..0000000
Binary files a/sound/misc/shield_respawn.wav and /dev/null differ
index 2b5664aea5b6a5b36f4901647d41bb7f87c41246..6c9210ef299a9178cf910c85b103a61e43c63d5d 100644 (file)
Binary files a/sound/misc/spawn.ogg and b/sound/misc/spawn.ogg differ
diff --git a/sound/misc/strength_respawn.ogg b/sound/misc/strength_respawn.ogg
new file mode 100644 (file)
index 0000000..fcf5725
Binary files /dev/null and b/sound/misc/strength_respawn.ogg differ
diff --git a/sound/misc/strength_respawn.wav b/sound/misc/strength_respawn.wav
deleted file mode 100644 (file)
index 3f7ffa2..0000000
Binary files a/sound/misc/strength_respawn.wav and /dev/null differ
index 8034299a44ca75d10b9fedeb0ae23833ca0a1452..55680f519695dc919a141e2746ee004c16c8d7e0 100644 (file)
Binary files a/sound/misc/teleport.ogg and b/sound/misc/teleport.ogg differ
diff --git a/sound/misc/typehit.ogg b/sound/misc/typehit.ogg
new file mode 100644 (file)
index 0000000..080e1bd
Binary files /dev/null and b/sound/misc/typehit.ogg differ
diff --git a/sound/misc/typehit.wav b/sound/misc/typehit.wav
deleted file mode 100644 (file)
index c765035..0000000
Binary files a/sound/misc/typehit.wav and /dev/null differ
index 5a16bdfcd19fe1d0a895dab1fa6ac313ae529251..4bac6b03e148723f765bea7ccbfb507fb443c3d1 100644 (file)
Binary files a/sound/nexball/bounce.ogg and b/sound/nexball/bounce.ogg differ
index f77b01b22fe7535f1d4c33edf0e84cf86ee546fb..92fea776344242d996e3018639136ecc856c9f8c 100644 (file)
Binary files a/sound/nexball/drop.ogg and b/sound/nexball/drop.ogg differ
index bb18f53f11617a23513ff6b86eacc7b2d9356010..eef18326a7f6d5de01bbeb0da3dd4ff9db9bab43 100644 (file)
Binary files a/sound/weapons/crylink_fire.ogg and b/sound/weapons/crylink_fire.ogg differ
index f10d6dd0c2aa07835aaa0e5a47736fdb3733bb2d..b2aa78eff1aa4e7fcd1ca5226978c4af76dc9084 100644 (file)
Binary files a/sound/weapons/crylink_fire2.ogg and b/sound/weapons/crylink_fire2.ogg differ
index d60c7bc397fa5d9bbc56a251d1692fdbf6bafa63..5813c4cb6deb9648223c46a841e546a26877d486 100644 (file)
Binary files a/sound/weapons/crylink_impact.ogg and b/sound/weapons/crylink_impact.ogg differ
index 26c7af5d86e90829de6115b71dc7d139aaf8a72c..be84bfe2f939da2d482fba8cf609ec3ee9c18abe 100644 (file)
Binary files a/sound/weapons/crylink_impact2.ogg and b/sound/weapons/crylink_impact2.ogg differ
index 18b3e156d1763f81612ea77a1d72e47d5a95ca1d..ea534b6d507e1ea35b4caf028e20e2d980020a6c 100644 (file)
Binary files a/sound/weapons/electro_fire.ogg and b/sound/weapons/electro_fire.ogg differ
index a7192fa8994a5dc5667d61fe647ece8a9609d422..d501a5bfbef4a12467b29b839d1564b8e082e7f8 100644 (file)
Binary files a/sound/weapons/electro_fire2.ogg and b/sound/weapons/electro_fire2.ogg differ
index 7301d3e0693ffbbf9ce09cb565ed46bbd110bddd..1822e0e6e505691a96f578d84c613bca4805ae42 100644 (file)
Binary files a/sound/weapons/electro_impact_combo.ogg and b/sound/weapons/electro_impact_combo.ogg differ
diff --git a/sound/weapons/fireball_fire.ogg b/sound/weapons/fireball_fire.ogg
new file mode 100644 (file)
index 0000000..01b57ae
Binary files /dev/null and b/sound/weapons/fireball_fire.ogg differ
diff --git a/sound/weapons/fireball_fire.wav b/sound/weapons/fireball_fire.wav
deleted file mode 100644 (file)
index 9f8ca1d..0000000
Binary files a/sound/weapons/fireball_fire.wav and /dev/null differ
diff --git a/sound/weapons/fireball_fire2.ogg b/sound/weapons/fireball_fire2.ogg
new file mode 100644 (file)
index 0000000..13797be
Binary files /dev/null and b/sound/weapons/fireball_fire2.ogg differ
diff --git a/sound/weapons/fireball_fire2.wav b/sound/weapons/fireball_fire2.wav
deleted file mode 100644 (file)
index 34526ae..0000000
Binary files a/sound/weapons/fireball_fire2.wav and /dev/null differ
index 05c6d375f2aacd92468959021d09ce633560b04a..c26c7103c9538bba53a10250ad95295dc02b434d 100644 (file)
Binary files a/sound/weapons/fireball_fly.ogg and b/sound/weapons/fireball_fly.ogg differ
index 4e7a929f35ba0221554e7ccac1e777bbbbe09d72..00da23c24fd1226080d2fe90487d4a5ec71aee31 100644 (file)
Binary files a/sound/weapons/fireball_fly2.ogg and b/sound/weapons/fireball_fly2.ogg differ
diff --git a/sound/weapons/fireball_impact2.ogg b/sound/weapons/fireball_impact2.ogg
new file mode 100644 (file)
index 0000000..9e6c947
Binary files /dev/null and b/sound/weapons/fireball_impact2.ogg differ
diff --git a/sound/weapons/fireball_impact2.wav b/sound/weapons/fireball_impact2.wav
deleted file mode 100644 (file)
index eec5a57..0000000
Binary files a/sound/weapons/fireball_impact2.wav and /dev/null differ
diff --git a/sound/weapons/fireball_prefire2.ogg b/sound/weapons/fireball_prefire2.ogg
new file mode 100644 (file)
index 0000000..a9224fc
Binary files /dev/null and b/sound/weapons/fireball_prefire2.ogg differ
diff --git a/sound/weapons/fireball_prefire2.wav b/sound/weapons/fireball_prefire2.wav
deleted file mode 100644 (file)
index bf76fae..0000000
Binary files a/sound/weapons/fireball_prefire2.wav and /dev/null differ
index 8175cd7aa3afbb1e780564489194593364fee3a1..82da52c1c2fe751725b0ab5877f5a38151fc3cab 100644 (file)
Binary files a/sound/weapons/grenade_impact.ogg and b/sound/weapons/grenade_impact.ogg differ
index fcb68c00ba3c5af7f5745884612ba99dfba8978e..da045a45c8524dbea21d069b402ad6b46ea20b37 100644 (file)
Binary files a/sound/weapons/hagar_fire.ogg and b/sound/weapons/hagar_fire.ogg differ
index eed76405c5a4de7da9bc77f761bf77a717876187..62973e1af68dc2df977b8032b5c7a8057cd67aa8 100644 (file)
Binary files a/sound/weapons/hook_impact.ogg and b/sound/weapons/hook_impact.ogg differ
index 2d2e8a96c27232b675ce2ce7a792f404ece3a975..6cac03be5305a1f38f057eab92123f2ae16cee2c 100644 (file)
Binary files a/sound/weapons/hookbomb_fire.ogg and b/sound/weapons/hookbomb_fire.ogg differ
index ea5122e04e5b3f558891a68d0cb8ee9d7c588107..f837baf6fa98aee87badd052ef4db80607048c1b 100644 (file)
Binary files a/sound/weapons/lasergun_fire.ogg and b/sound/weapons/lasergun_fire.ogg differ
index d08710985743ab7de72c67b14c8d58870001c3d1..1dec6ff826d136049dd895aabb10454c54f9e0bd 100644 (file)
Binary files a/sound/weapons/minstanexfire.ogg and b/sound/weapons/minstanexfire.ogg differ
diff --git a/sound/weapons/missile_fly.ogg b/sound/weapons/missile_fly.ogg
new file mode 100644 (file)
index 0000000..13e43e6
Binary files /dev/null and b/sound/weapons/missile_fly.ogg differ
index 5d28b731cee1f6e8d305958728617bb4c84c7f4b..c576c0a169fbb9d80b2b34bb1d7a80e475ae13f1 100644 (file)
Binary files a/sound/weapons/nexfire.ogg and b/sound/weapons/nexfire.ogg differ
index 948a996388227b59a26d834a5d8157f0dc05af2a..b6476d8bf29d6f66aa18b2e787a846f80956d3a4 100644 (file)
Binary files a/sound/weapons/neximpact.ogg and b/sound/weapons/neximpact.ogg differ
index 36f1183daa35e003b8a7d6f774e7cded07e3ae6b..f0f2b3a207b7994362dade5705b4f770d121844b 100644 (file)
Binary files a/sound/weapons/nexwhoosh1.ogg and b/sound/weapons/nexwhoosh1.ogg differ
index 38ffa22f33090b94b8bb2f3ef3259cd5daa47763..57ac5e60af7fbd383118a9b05f14485b92d84877 100644 (file)
Binary files a/sound/weapons/nexwhoosh2.ogg and b/sound/weapons/nexwhoosh2.ogg differ
index 3db8d4b44605818b3c42508a88bf153e672ca335..a5764f79e8a2b55fb97e49b12160be537f976710 100644 (file)
Binary files a/sound/weapons/nexwhoosh3.ogg and b/sound/weapons/nexwhoosh3.ogg differ
index 2edb3739cc6345759e6621317a23ffcaecfe08ae..ef67597f4439247b3febfd841a930f256ca2fbd6 100644 (file)
Binary files a/sound/weapons/reload.ogg and b/sound/weapons/reload.ogg differ
index 5f2cb3a8348a87c9e0fce9a1a0f2fd2db9b9895f..f0d6b5fbffdd4aea4cbe8986a802b42162f9f5f7 100644 (file)
Binary files a/sound/weapons/rocket_fire.ogg and b/sound/weapons/rocket_fire.ogg differ
index 56b114e65d37e1900f4380f1cb5b26ecc909c8ab..92704cb9c3bc3cf33188d8712c94e6a43f0f7d98 100644 (file)
Binary files a/sound/weapons/rocket_impact.ogg and b/sound/weapons/rocket_impact.ogg differ
index ca1d8cc1e75a4c48a26151aa2d3f062e8a74cfa0..fd02d133c540360eaa6e5bb34ef15e643fe6de43 100644 (file)
Binary files a/sound/weapons/rocket_mode.ogg and b/sound/weapons/rocket_mode.ogg differ
index 8d4f607c742a2b17970129c9d072125bf545f5f1..41e89c348aedffa5ef85a1951ee220a3f3a22f52 100644 (file)
Binary files a/sound/weapons/shotgun_fire.ogg and b/sound/weapons/shotgun_fire.ogg differ
index 0562b559ed6d4280589eecede1610b3a8011902f..cb72feb5955d80eda60971e5a4db3a82326aa73f 100644 (file)
Binary files a/sound/weapons/shotgun_melee.ogg and b/sound/weapons/shotgun_melee.ogg differ
index 8d27e4fde32969d3fce75917edffda68e852f38e..db284e92699d05cbd0d199d59ad8350e24deb30d 100644 (file)
Binary files a/sound/weapons/strength_fire.ogg and b/sound/weapons/strength_fire.ogg differ
diff --git a/sound/weapons/unavailable.ogg b/sound/weapons/unavailable.ogg
new file mode 100644 (file)
index 0000000..7d1bec5
Binary files /dev/null and b/sound/weapons/unavailable.ogg differ
diff --git a/sound/weapons/unavailable.wav b/sound/weapons/unavailable.wav
deleted file mode 100644 (file)
index b75c8c5..0000000
Binary files a/sound/weapons/unavailable.wav and /dev/null differ
index 24c73a4c05affd2ba71965e79720549b92adeef4..9dc389949394ccd2aa53efc2312c30b30aa4f8b9 100644 (file)
Binary files a/sound/weapons/uzi_fire.ogg and b/sound/weapons/uzi_fire.ogg differ
index 5a7756b06cfe328ea6add03a18e82a25031b0911..8c40e1f233173dc735ef49e3a14ddeeb7b0fe0b7 100644 (file)
Binary files a/sound/weapons/weapon_switch.ogg and b/sound/weapons/weapon_switch.ogg differ
index 4e1c1fbd19301115cfba65c882b129d03dacf093..55ee488946ad6f14bd8c5fbb48ade97fcdf1c99e 100644 (file)
Binary files a/sound/weapons/weaponpickup.ogg and b/sound/weapons/weaponpickup.ogg differ
index 5a470f6d642cf016defcbb357935bb47c18469cf..2ef83416e31566b2d352a13ac9d82a0ea54b71ae 100644 (file)
Binary files a/textures/erebusfullbright.tga and b/textures/erebusfullbright.tga differ
index 992af7530e551bbf24c0b64a6313a9c3b3edcfee..d2f981933f587b7417401d280cf62dfe1e1c9461 100644 (file)
Binary files a/textures/erebusfullbright_gloss.tga and b/textures/erebusfullbright_gloss.tga differ
index e825195ef5ba5ebaa508788dfda805b35ad59799..1c26b072cf1d2a514070ce40420523101c0bc1c0 100644 (file)
Binary files a/textures/erebusfullbright_reflect.tga and b/textures/erebusfullbright_reflect.tga differ
index 364bae2d9a72f533dcc95d6ed483f33786e3d880..9aee3c18ac244bb629958d4c4e6d988606c2533a 100644 (file)
Binary files a/textures/erebusfullbright_shirt.tga and b/textures/erebusfullbright_shirt.tga differ
index 8169f3779f477ba3e8b2adcc3daa9548d0a0d63e..1eba0fefc7a7e6a68e8326eb5269df21b34d6a91 100644 (file)
Binary files a/textures/nyxfullbright.tga and b/textures/nyxfullbright.tga differ
index 6b53f91cfe782dfdaf92c87feb84b8c3e65f83eb..f3f636dde2b0eff3fd8e49d3ca8c3d97e20feb81 100644 (file)
Binary files a/textures/nyxfullbright_gloss.tga and b/textures/nyxfullbright_gloss.tga differ
index a91959d3663f7d20ae2a3d6c6bdccc43ea360eff..ec01e22847e408a3db8cefe5abc7d45eca128010 100644 (file)
Binary files a/textures/nyxfullbright_glow.tga and b/textures/nyxfullbright_glow.tga differ
index e825195ef5ba5ebaa508788dfda805b35ad59799..0052c20d690dcf73d05c435f052068b8679fb885 100644 (file)
Binary files a/textures/nyxfullbright_reflect.tga and b/textures/nyxfullbright_reflect.tga differ
index 364bae2d9a72f533dcc95d6ed483f33786e3d880..9aee3c18ac244bb629958d4c4e6d988606c2533a 100644 (file)
Binary files a/textures/nyxfullbright_shirt.tga and b/textures/nyxfullbright_shirt.tga differ
index 489d82b15430a9a7945f36527f9510d7af8e6b47..d3a2c0bc5658e578f14f4236f97530ddfd5f18cb 100644 (file)
@@ -11,6 +11,7 @@ set g_vehicles_teams 1 "allow team specific vehicles"
 set g_vehicles_teleportable 0
 set g_vehicles_crush_dmg 70
 set g_vehicles_crush_force 50
+set g_vehicles_crush_minspeed 100
 set g_vehicles_allow_bots 0
 set g_vehicles_exit_attempts 25
 set g_vehicles_thinkrate 0.1
diff --git a/wpeditor.txt b/wpeditor.txt
new file mode 100644 (file)
index 0000000..19d23ff
--- /dev/null
@@ -0,0 +1,26 @@
+// open this quick menu with: quickmenu file "" wpeditor.txt
+"Spawn"                      "wpeditor spawn"
+"Remove"                     "wpeditor remove"
+"Save all"                   "wpeditor saveall"
+"Spawn at crosshair"         "wpeditor spawn crosshair"
+"Spawn jump"                 "wpeditor spawn jump"
+"Spawn crouch"               "wpeditor spawn crouch"
+"Spawn support"              "wpeditor spawn support"
+"Hardwire/Unhw at crosshair" "wpeditor hardwire crosshair"
+"Hardwire/Unhardwire"        "wpeditor hardwire"
+"Lock/Unlock"                "wpeditor lock"
+"Relink all"                 "wpeditor relinkall"
+"Find unreachable"           "wpeditor unreachable"
+"Show help in console"       "cmd help wpeditor"
+"Settings"
+       "Waypoint editor"             "toggle g_waypointeditor"
+       "On screen console messages"  "toggle con_notify 4 0"
+       "Bot in map"                  "toggle bot_number"
+       "Bots can't fire"             "toggle bot_nofire"
+       "Show bot's path to goal"     "toggle bot_debug_goalstack"
+       "Show tracewalk path"         "toggle bot_debug_tracewalk"
+       "No time limit"               "timelimit 0"
+       "Cheats"                      "toggle sv_cheats"
+       "God mode on/off"             "god"
+       "Fly mode on/off"             "fly"
+"Settings"
\ No newline at end of file
index 61651320af290c4d91acda0ec9afc7c3a7691b24..dfa3c0c57c26f8efe0862618918f653612dbe750 100644 (file)
@@ -2,8 +2,8 @@
 // if you want to reset your client to defaults, it's probably a better idea to delete (parts of) config.cfg and restart
 
 
-// changes a cvar and reports it to the server (for the menu to notify the
-// server about changes)
+// changes a cvar and reports it to the server (for the client to notify the server about changes)
+// DEPRECATED, cvars can be set in the client code to be sent automatically (using REPLICATE)
 alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\""
 
 seta cl_firststart "" "how many times the client has been run"
@@ -75,7 +75,6 @@ sensitivity 6
 v_gamma 1
 viewsize 100
 bgmvolume 1
-volume 0.5
 // fullscreen 1024x768x32bit
 vid_bitsperpixel 32
 vid_fullscreen 1
@@ -167,6 +166,7 @@ seta cl_leanmodel_highpass1 0.2 "gun leaning pre-highpass averaging time"
 seta cl_leanmodel_highpass 0.2 "gun leaning highpass averaging time"
 seta cl_leanmodel_lowpass 0.05 "gun leaning lowpass averaging time"
 
+cl_maxfps_alwayssleep 0 // gives up some processing time to other applications each frame, default is 1 (not necessary since Xonotic caps FPS by default)
 cl_rollangle 0 // amount of view tilt when strafing, default is 2.0
 v_kicktime 0 // how long damage kicks of the view last, default is 0 seconds
 gl_polyblend 0 // whether to use screen tints, this has now been replaced by a better system in CSQC
@@ -194,7 +194,7 @@ seta cl_autotaunt 0 "automatically taunt enemies when fragging them"
 seta cl_voice_directional 1    "0 = all voices are non-directional, 1 = all voices are directional, 2 = only taunts are directional"
 seta cl_voice_directional_taunt_attenuation 0.5 "this defines the distance from which taunts can be heard"
 
-seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy, 1: same pitch 2: increase pitch with more damage 3: decrease pitch with more damage"
+seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy, 1: same pitch 2: decrease pitch with more damage 3: increase pitch with more damage"
 set cl_hitsound_antispam_time 0.05 "don't play the hitsound more often than this"
 seta cl_hitsound_min_pitch 0.75 "minimum pitch of hit sound"
 seta cl_hitsound_max_pitch 1.5 "maximum pitch of hit sound"
@@ -234,6 +234,8 @@ cl_movement 1
 cl_movement_track_canjump 0
 cl_stairsmoothspeed 200
 
+alias wpeditor_menu "quickmenu file \"\" wpeditor.txt"
+
 alias g_waypointeditor_spawn         "wpeditor spawn"
 alias g_waypointeditor_remove        "wpeditor remove"
 alias g_waypointeditor_relinkall     "wpeditor relinkall"
@@ -305,8 +307,6 @@ r_glsl_offsetmapping_lod 1
 r_glsl_offsetmapping_reliefmapping 0
 r_glsl_offsetmapping_scale 0.02
 
-scr_conalpha 1
-scr_conbrightness 0.2
 scr_screenshot_jpeg 1
 scr_screenshot_jpeg_quality 0.9
 
@@ -396,6 +396,7 @@ set g_waypointsprite_timealphaexponent 1
 seta g_waypointsprite_turrets 1 "disable turret waypoints"
 seta g_waypointsprite_turrets_maxdist 5000 "max distance for turret waypoints"
 seta g_waypointsprite_turrets_text 0 "show the turret's name in the waypoint"
+seta g_waypointsprite_turrets_onlyhurt 0 "only show the turret waypoint for a short period after being hurt"
 seta g_waypointsprite_uppercase 1
 seta g_waypointsprite_text 0 "Always show text instead of icons, setting this to 0 will still use text if the icon is unavailable"
 seta g_waypointsprite_iconsize 32
@@ -448,7 +449,7 @@ seta cl_damagetext_2d_overlap_offset "0 -15 0" "Offset 2D damage text by this mu
 seta cl_damagetext_2d_close_range 125 "Always use 2D damagetext for hits closer that this"
 seta cl_damagetext_2d_out_of_view 1 "Always use 2D damagetext for hits that occurred off-screen"
 
-seta cl_vehicles_alarm 1 "Play an alarm sound when the vehicle you are driving is heavily damaged"
+seta cl_vehicles_alarm 0 "Play an alarm sound when the vehicle you are driving is heavily damaged"
 seta cl_vehicles_hud_tactical 1
 seta cl_vehicles_hudscale 0.5
 seta cl_vehicles_notify_time 15
@@ -610,6 +611,7 @@ makesaved music_playlist_list0
 makesaved music_playlist_random0
 
 cl_netfps 60 // should match or be a multiple of sys_ticrate
+_cl_rate 40000 // fast adsl
 
 gl_texture_anisotropy 8
 seta gl_texturecompression 0 // FIXME the description is wrong - when this is 0, e.g. gl_texturecompression_sky still takes effect
@@ -620,7 +622,7 @@ gl_texturecompression_lightcubemaps 0
 gl_texturecompression_q3bsplightmaps 0
 gl_texturecompression_sky 1
 
-cl_maxfps 200
+cl_maxfps 250
 
 seta menu_mouse_absolute 1 "use the OS mouse pointer motion for menu"
 seta menu_mouse_speed 1 "speed multiplier for the mouse in the menu (does not affect in-game aiming)"
@@ -647,9 +649,9 @@ alias _gl_flashblend_update_01 "gl_flashblend 0"
 alias _gl_flashblend_update_11 "gl_flashblend 0"
 alias gl_flashblend_update "_gl_flashblend_update_$r_shadow_realtime_dlight$r_showsurfaces"
 
-set cl_handicap 1      "multiplies damage received and divides damage dealt NOTE: reconnect or use 'sendcvar cl_handicap' to update the choice."
+set cl_handicap 1      "multiplies damage received and divides damage dealt"
 
-seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such. (client setting) NOTE: reconnect or use sendcvar command to update the choice."
+seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such"
 
 seta cl_autoscreenshot 1 "Take a screenshot upon the end of a match... 0 = Disable completely, 1 = Allow sv_autoscreenshot to take a screenshot when requested, 2 = Always take an autoscreenshot anyway."
 
@@ -764,7 +766,6 @@ scr_conalpha2factor 0.3
 scr_conalpha3factor 1
 scr_conalphafactor 0.8
 scr_conbrightness 0.35
-scr_conforcewhiledisconnected 1
 scr_conscroll2_x 0.11
 scr_conscroll2_y 0.2
 scr_conscroll3_x 0
@@ -810,7 +811,7 @@ set cl_db_saveasdump 0 "write client.db in dump format (loads slower, easier to
 // uid2name
 seta cl_allow_uid2name -1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid2name (allows showing your name in race rankings for instance)"
 seta cl_allow_uidtracking 1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid tracking (allows associating your data with your player ID)"
-// FIXME set to -1 before release, once we have a dialog for this!
+seta cl_allow_uidranking 1 "0 = disable, 1 = enable uid ranking (allows statistics like elo to rank you in leaderboards)"
 
 // polygonoffset for submodel SUCKS SUCKS SUCKS (only a hack for quake1, we don't need that)
 r_polygonoffset_submodel_offset 0
index 3a01784c7c5d4bf6c5451fbda664ad0d44f83799..f44d9c96f969fa5853216a289a2d8c7e0bdeffb9 100644 (file)
@@ -1,3 +1,10 @@
+// most common prefixes (currently not used consistently - especially g_ and sv_):
+// cl_ client
+// g_ gameplay
+// r_ renderer
+// sv_ server administration, should not affect gameplay
+// _ temporary, private or internal cvar - should not be changed manually, sometimes used in scripts
+
 // Xonotic version (formatted for machines)
 // used to determine if a client version is compatible
 // this doesn't have to be bumped with every release
index 463df7224e364a9c6aad3c3517c7a5321e2ee611..6d1f427725a18e9e691decb7e9631dc13478b44d 100644 (file)
@@ -2,7 +2,7 @@
 // note that it doesn't reset all server cvars,
 // some are shared with the client and so are left in xonotic-common.cfg
 
-set name_maxlength 64 "max player name length (not counting color codes) allowed by the server"
+set sv_name_maxlength 64 "max player name length (not counting color codes) allowed by the server"
 
 // taunts and voices
 set sv_taunt 1 "allow taunts on the server"
@@ -32,6 +32,8 @@ set g_warmup_allow_timeout 0  "allow calling timeouts in the warmup-stage (if sv_
 set g_warmup_allguns 1 "provide more weapons on start while in warmup: 0 = normal start weapons, 1 = all guns available on the map, 2 = all normal weapons"
 set g_warmup_majority_factor 0.8 "minimum percentage of players ready needed for warmup to end"
 
+alias sv_hook_warmupend
+
 set g_chat_nospectators 0      "if 0 spec/observer chat is always visible to the player, if 1 it is never visible to players, if 2 it is only visible to players during warmup stage"
 set sv_vote_nospectators 0     "only players can call a vote (thus spectators and observers can't call a vote): 0 = all people can vote, 1 = spectators can vote in warmup stage, 2 = only players can vote (no exceptions)."
 
@@ -112,6 +114,7 @@ set bot_usemodelnames 0     "Use player model names for bot names"
 set bot_nofire 0       "When set, bots never fire. Mainly for testing in g_waypointeditor mode"
 set bot_prefix [BOT]   "Prefix in front of the bot names"
 set bot_suffix ""      "Suffix behind the bot names"
+skill 8
 set skill_auto 0       "when 1, \"skill\" gets adjusted to match the best player on the map"
 set bot_debug_tracewalk 0 "Enable visual indicators for short-term navigation. Green: Goal Reached / Yellow: Obstacle found / Red: Unsolvable obstacle found"
 set bot_debug_goalstack 0 "Visualize the current path that each bot is following. Use with as few bots as possible."
@@ -190,12 +193,12 @@ set g_pinata 0 "if set to 1 you will not only drop your current weapon when you
 set g_weapon_stay 0 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
 set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
 set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default"
-set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammunition"
+set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammo"
 set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn"
 set g_pickup_respawntime_scaling_reciprocal 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*"
 set g_pickup_respawntime_scaling_offset 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening"
 set g_pickup_respawntime_scaling_linear 1 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly"
-set g_weaponarena "0"  "put in a list of weapons to enable a weapon arena mode, or try \"all\" or \"most\""
+set g_weaponarena "0"  "put in a list of weapons to enable a weapon arena mode, or try \"all\", \"most\", \"all_available\" or \"most_available\" (available only gives the weapon if the map normally has it as a pickup item)"
 set g_weaponarena_random "0"   "if set to a number, only that weapon count is given on every spawn (randomly)"
 set g_weaponarena_random_with_blaster "1"      "additionally, always provide the blaster in random weapon arena games"
 set g_spawnpoints_auto_move_out_of_solid 0 "if set to 1 you will see a warning if a spawn point was placed inside a solid"
@@ -212,6 +215,8 @@ set g_maplist_index 0       "this is used internally for saving position in maplist cy
 set g_maplist_selectrandom 0   "if 1, a random map will be chosen as next map - DEPRECATED in favor of g_maplist_shuffle"
 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_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"
 set g_items_maxdist 4500 "maximum distance at which an item can be viewed, after which it will be invisible"
@@ -221,6 +226,7 @@ set g_grab_range 200 "distance at which dragable objects can be grabbed"
 set g_cloaked 0 "display all players mostly invisible"
 set g_player_alpha 1 "default opacity of players"
 set g_player_brightness 0      "set to 2 for brighter players"
+set g_player_damageforcescale 2 "push multiplier of attacks against players"
 set g_balance_cloaked_alpha 0.25 "opacity of cloaked players"
 
 set g_playerclip_collisions 1 "0 = disable collision testing against playerclips, might be useful on some defrag maps"
@@ -418,15 +424,11 @@ set g_ban_sync_trusted_servers_verify 0   "when set to 1, additional bans sent by
 
 set g_showweaponspawns 1 "1: display waypoints for weapon spawns found on the map when a weapon key is pressed and the weapon is not owned; 2: for dropped weapons too; 3: for all the weapons sharing the same impulse"
 
-// ballistics use physical units, but qu based
-//   Quake-Newton: 1 qN  = 1 qu * 1 g / 1 s^2
-//   Quake-Joule:  1 qJ  = 1 qN * 1 qu
-//   Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
-
-set g_ballistics_mindistance 2 "enable ballistics starting from 2 qu"
-set g_ballistics_density_player 0.50 "players are 2x as easy to pass through as walls"
-set g_ballistics_density_corpse 0.10 "corpses are 10x as easy to pass through as walls"
-set g_ballistics_penetrate_clips 0 "allow ballistics to pass through weapon clips"
+set g_ballistics_mindistance 2 "when shooting through walls thinner than this, treat them as this thick (useful because patches (curved surfaces) have no thickness)"
+set g_ballistics_density_player 0.50 "how hard players are to shoot through compared to walls"
+set g_ballistics_density_corpse 0.10 "how hard corpses are to shoot through compared to walls"
+set g_ballistics_penetrate_clips 1 "allow ballistics to pass through weapon clips"
+set g_ballistics_solidpenetration_exponent 0.25 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)"
 
 sv_status_show_qcstatus 1      "Xonotic uses this field instead of frags"
 set g_full_getstatus_responses 0       "this currently breaks qstat"
@@ -491,6 +493,8 @@ set g_maxspeed 0 "player speed limit, faster players are killed (0 for unlimited
 
 // sv_cullentities_trace is 1, so the client doesn't have to
 sv_cullentities_trace 1
+// due to a bug in the engine, the default setting of this (16) spams the network with item updates
+sv_cullentities_trace_eyejitter 0
 
 // less "lagging" of other players, but also less PL tolerant... let's try this
 sv_clmovement_inputtimeout 0.066 // slightly less than 2 frames, so only one frame can be compensated
@@ -562,3 +566,4 @@ set sv_showspectators 1 "Show who's spectating who in the player info panel when
 set sv_damagetext 2 "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage"
 
 set sv_showfps 5 "Show player's FPS counters in the scoreboard. This setting acts as a delay in seconds between updates"
+set autocvar_sv_doors_always_open 0 "If set to 1 don't close doors which after they were open"