]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/mapinfo_title_fix
authorMario <mario@smbclan.net>
Sun, 21 Oct 2018 16:52:27 +0000 (02:52 +1000)
committerMario <mario@smbclan.net>
Sun, 21 Oct 2018 16:52:27 +0000 (02:52 +1000)
320 files changed:
.gitlab-ci.yml
.tx/merge-base
_hud_common.cfg
bal-wep-mario.cfg
bal-wep-xdf.cfg
binds-xonotic.cfg
common.ru.po
effectinfo.txt
effects-normal.cfg
gamemodes-client.cfg
gamemodes-server.cfg
gfx/menu/luma/bigbutton_c.tga
gfx/menu/luma/bigbutton_d.tga
gfx/menu/luma/bigbutton_f.tga
gfx/menu/luma/bigbutton_n.tga
gfx/menu/luma/bigbuttongray_c.tga
gfx/menu/luma/bigbuttongray_d.tga
gfx/menu/luma/bigbuttongray_f.tga
gfx/menu/luma/bigbuttongray_n.tga
gfx/menu/luma/border.tga
gfx/menu/luma/button_c.tga
gfx/menu/luma/button_d.tga
gfx/menu/luma/button_f.tga
gfx/menu/luma/button_n.tga
gfx/menu/luma/buttongray_c.tga
gfx/menu/luma/buttongray_d.tga
gfx/menu/luma/buttongray_f.tga
gfx/menu/luma/buttongray_n.tga
gfx/menu/luma/checkbox_c0.tga
gfx/menu/luma/checkbox_c1.tga
gfx/menu/luma/checkbox_d0.tga
gfx/menu/luma/checkbox_d1.tga
gfx/menu/luma/checkbox_f0.tga
gfx/menu/luma/checkbox_f1.tga
gfx/menu/luma/checkbox_n0.tga
gfx/menu/luma/checkbox_n1.tga
gfx/menu/luma/checkmark.tga
gfx/menu/luma/clearbutton_c.tga
gfx/menu/luma/clearbutton_f.tga
gfx/menu/luma/clearbutton_n.tga
gfx/menu/luma/closebutton_c.tga
gfx/menu/luma/closebutton_f.tga
gfx/menu/luma/closebutton_n.tga
gfx/menu/luma/colorbutton_c.tga
gfx/menu/luma/colorbutton_f.tga
gfx/menu/luma/colorbutton_n.tga
gfx/menu/luma/colorpicker_m.tga
gfx/menu/luma/cursor.tga
gfx/menu/luma/cursor_move.tga
gfx/menu/luma/cursor_resize.tga
gfx/menu/luma/cursor_resize2.tga
gfx/menu/luma/gametype_as.tga
gfx/menu/luma/gametype_ca.tga
gfx/menu/luma/gametype_ctf.tga
gfx/menu/luma/gametype_cts.tga
gfx/menu/luma/gametype_dm.tga
gfx/menu/luma/gametype_dom.tga
gfx/menu/luma/gametype_duel.tga
gfx/menu/luma/gametype_ft.tga
gfx/menu/luma/gametype_inf.tga
gfx/menu/luma/gametype_inv.tga
gfx/menu/luma/gametype_jb.tga
gfx/menu/luma/gametype_ka.tga
gfx/menu/luma/gametype_kh.tga
gfx/menu/luma/gametype_lms.tga
gfx/menu/luma/gametype_nb.tga
gfx/menu/luma/gametype_ons.tga
gfx/menu/luma/gametype_rc.tga
gfx/menu/luma/gametype_tdm.tga
gfx/menu/luma/gametype_vip.tga
gfx/menu/luma/icon_aeslevel1.tga
gfx/menu/luma/icon_aeslevel2.tga
gfx/menu/luma/icon_aeslevel3.tga
gfx/menu/luma/icon_aeslevel4.tga
gfx/menu/luma/icon_aeslevel5.tga
gfx/menu/luma/icon_ipv4.tga
gfx/menu/luma/icon_ipv6.tga
gfx/menu/luma/icon_mod_.tga
gfx/menu/luma/icon_mod_XDF.tga [deleted file]
gfx/menu/luma/icon_mod_instagib.tga
gfx/menu/luma/icon_mod_jeff.tga
gfx/menu/luma/icon_mod_minstagib.tga
gfx/menu/luma/icon_mod_newtoys.tga
gfx/menu/luma/icon_mod_overkill.tga
gfx/menu/luma/icon_mod_quake.tga
gfx/menu/luma/icon_mod_xdf.tga [new file with mode: 0644]
gfx/menu/luma/icon_mod_xpm.tga [new file with mode: 0644]
gfx/menu/luma/icon_pure1.tga
gfx/menu/luma/icon_stats1.tga
gfx/menu/luma/inputbox_f.tga
gfx/menu/luma/inputbox_n.tga
gfx/menu/luma/nopreview_map.tga
gfx/menu/luma/nopreview_menuskin.tga
gfx/menu/luma/nopreview_player.tga
gfx/menu/luma/radiobutton_c0.tga
gfx/menu/luma/radiobutton_c1.tga
gfx/menu/luma/radiobutton_d0.tga
gfx/menu/luma/radiobutton_d1.tga
gfx/menu/luma/radiobutton_f0.tga
gfx/menu/luma/radiobutton_f1.tga
gfx/menu/luma/radiobutton_n0.tga
gfx/menu/luma/radiobutton_n1.tga
gfx/menu/luma/scrollbar_c.tga
gfx/menu/luma/scrollbar_f.tga
gfx/menu/luma/scrollbar_n.tga
gfx/menu/luma/scrollbar_s.tga
gfx/menu/luma/skinpreview.tga
gfx/menu/luma/skinvalues.txt
gfx/menu/luma/slider_c.tga
gfx/menu/luma/slider_d.tga
gfx/menu/luma/slider_f.tga
gfx/menu/luma/slider_n.tga
gfx/menu/luma/slider_s.tga
gfx/menu/luma/tooltip.tga
gfx/menu/luminos/icon_mod_xpm.tga [new file with mode: 0644]
gfx/menu/wickedx/icon_mod_xpm.tga [new file with mode: 0644]
gfx/menu/xaw/icon_mod_xpm.tga [new file with mode: 0644]
gfx/scoreboard/player_ready.tga
gfx/scoreboard/playercolor_base.tga
gfx/scoreboard/playercolor_pants.tga
gfx/scoreboard/playercolor_shirt.tga
gfx/scoreboard/scoreboard_bg.tga
gfx/scoreboard/scoreboard_tableheader.tga
help-overkill.cfg [new file with mode: 0644]
help-xonotic.cfg [new file with mode: 0644]
help.cfg [new file with mode: 0644]
notifications.cfg
qcsrc/client/autocvars.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/defs.qh
qcsrc/client/hud/hud.qc
qcsrc/client/hud/hud.qh
qcsrc/client/hud/hud_config.qc
qcsrc/client/hud/panel/infomessages.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/physics.qc
qcsrc/client/hud/panel/quickmenu.qc
qcsrc/client/hud/panel/racetimer.qc
qcsrc/client/hud/panel/radar.qc
qcsrc/client/hud/panel/score.qc
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/hud/panel/scoreboard.qh
qcsrc/client/hud/panel/timer.qc
qcsrc/client/hud/panel/vote.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/shownames.qc
qcsrc/client/view.qc
qcsrc/client/view.qh
qcsrc/client/weapons/projectile.qc
qcsrc/common/animdecide.qc
qcsrc/common/effects/all.inc
qcsrc/common/effects/effectinfo.inc
qcsrc/common/gamemodes/gamemode/_mod.inc
qcsrc/common/gamemodes/gamemode/_mod.qh
qcsrc/common/gamemodes/gamemode/assault/sv_assault.qh
qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/cts/sv_cts.qc
qcsrc/common/gamemodes/gamemode/duel/_mod.inc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/duel/_mod.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/duel/sv_duel.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/duel/sv_duel.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/lms/sv_lms.qc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/nexball/sv_weapon.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/gamemodes/sv_rules.qh
qcsrc/common/items/inventory.qh
qcsrc/common/items/item/pickup.qc
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/mapobjects/func/bobbing.qc
qcsrc/common/mapobjects/func/button.qc
qcsrc/common/mapobjects/func/conveyor.qc
qcsrc/common/mapobjects/func/door.qc
qcsrc/common/mapobjects/func/plat.qc
qcsrc/common/mapobjects/misc/_mod.inc
qcsrc/common/mapobjects/misc/_mod.qh
qcsrc/common/mapobjects/misc/keys.qc [new file with mode: 0644]
qcsrc/common/mapobjects/misc/keys.qh [new file with mode: 0644]
qcsrc/common/mapobjects/models.qc
qcsrc/common/mapobjects/subs.qh
qcsrc/common/mapobjects/trigger/counter.qc
qcsrc/common/mapobjects/trigger/counter.qh
qcsrc/common/mapobjects/trigger/hurt.qc
qcsrc/common/mapobjects/trigger/hurt.qh
qcsrc/common/mapobjects/trigger/jumppads.qc
qcsrc/common/mapobjects/trigger/keylock.qc
qcsrc/common/mapobjects/trigger/keylock.qh
qcsrc/common/mapobjects/triggers.qc
qcsrc/common/mapobjects/triggers.qh
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/minigames/minigame/bd.qc
qcsrc/common/minigames/minigame/ps.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc
qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/okhmg.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qh
qcsrc/common/mutators/mutator/overkill/oknex.qc
qcsrc/common/mutators/mutator/overkill/oknex.qh
qcsrc/common/mutators/mutator/overkill/okrpc.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qh
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc
qcsrc/common/notifications/all.inc
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/movetypes/movetypes.qh
qcsrc/common/physics/movetypes/toss.qc
qcsrc/common/physics/movetypes/walk.qc
qcsrc/common/physics/player.qc
qcsrc/common/physics/player.qh
qcsrc/common/playerstats.qc
qcsrc/common/sounds/all.qc
qcsrc/common/state.qc
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/turrets/turret/machinegun_weapon.qc
qcsrc/common/turrets/turret/walker_weapon.qc
qcsrc/common/util.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qh
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
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/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/common/wepent.qc
qcsrc/common/wepent.qh
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/warpzone/client.qc
qcsrc/menu/item.qc
qcsrc/menu/item.qh
qcsrc/menu/item/container.qh
qcsrc/menu/item/image.qh
qcsrc/menu/item/inputbox.qc
qcsrc/menu/item/label.qh
qcsrc/menu/item/listbox.qh
qcsrc/menu/xonotic/crosshairpreview.qh
qcsrc/menu/xonotic/dialog_multiplayer_create.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_settings_misc.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/picker.qh
qcsrc/menu/xonotic/util.qc
qcsrc/server/_mod.inc
qcsrc/server/_mod.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/scripting.qc
qcsrc/server/cheats.qc
qcsrc/server/cheats.qh
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/clientkill.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/compat/quake3.qc
qcsrc/server/compat/quake3.qh
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_world.qc
qcsrc/server/impulse.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc [deleted file]
qcsrc/server/item_key.qh [deleted file]
qcsrc/server/matrix.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
qcsrc/server/player.qc
qcsrc/server/player.qh
qcsrc/server/spawnpoints.qc
qcsrc/server/teamplay.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/accuracy.qh
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/selection.qh
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/tracing.qh
qcsrc/server/weapons/weaponsystem.qc
ruleset-XPM.cfg
ruleset-overkill.cfg
scripts/weapons.shader
vehicles.cfg [new file with mode: 0644]
xonotic-client.cfg
xonotic-common.cfg
xonotic-server.cfg

index 9423d5d5dc081806a1dd2887200972f5ae5de2cd..09f32ba196dbe54ea108e54c9665b92cb0030dda 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=dc1bc3ac45188576a9651c6b7a1535a8
+    - EXPECT=bb534e81ce09934ceadfd952a8ecd016
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 12e22e55744578d3ad8135aac71ec33813f92f0e..3512ca5dc542939aff93cadaafcc1544cf16655e 100644 (file)
@@ -1 +1 @@
-Sun Sep  2 07:24:05 CEST 2018
+Sun Sep 30 07:24:04 CEST 2018
index 3631df7eb4882cc7d2dc9d85063c845bff47c887..75e8eb8d6f51a5d4ee6b94b804aea9eaac9a0d45 100644 (file)
@@ -115,6 +115,9 @@ seta hud_panel_scoreboard_spectators_showping 1 "show ping of spectators"
 seta hud_panel_scoreboard_spectators_aligned 0 "align spectators in columns"
 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"
+
 // hud panel aliases
 alias quickmenu "cl_cmd hud quickmenu ${* ?}"
 
@@ -156,11 +159,11 @@ seta hud_damage_pain_threshold_lower_health 50 "at which health we start lowerin
 seta hud_damage_pain_threshold_pulsating_min 0.6 "minimum value when calculating the pulse: max(pulsating_min, fabs(sin(PI * time / period))"
 seta hud_damage_pain_threshold_pulsating_period 0.8 "one pulse every X seconds"
 
-seta hud_powerup 0 "power of the sharpen effect when owning the shield or strength powerups, default is 0.5"
+seta hud_powerup 0 "power of the sharpen effect when owning the shield or strength powerups"
 
 seta hud_postprocessing 1 "enables the ability for effects such as hud_damage_blur and hud_contents to apply a postprocessing method upon the screen - enabling this disables manual editing of the postprocess cvars"
-seta hud_postprocessing_maxbluralpha 0 "maximum alpha which the blur postprocess can be, default is 0.5"
-seta hud_postprocessing_maxblurradius 8 "maximum radius which the blur postprocess can be, default is 8"
+seta hud_postprocessing_maxbluralpha 0 "maximum alpha which the blur postprocess can be"
+seta hud_postprocessing_maxblurradius 8 "maximum radius which the blur postprocess can be"
 
 seta hud_contents 1 "an improved version of gl_polyblend for liquids such as water/lava/slime, draw a filler when inside the liquid"
 seta hud_contents_blur 10 "Use postprocessing to blur the screen when you are inside a liquid. Higher values = more blur"
index d2ff12f6bc81cf2e13051600315fd4fb78f9c2ca..45a75349be2cfba6658cd4199f6a25aba847350c 100644 (file)
@@ -60,8 +60,8 @@ 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 "shockwave"
-set g_balance_shotgun_weaponstart 0
+set g_balance_shotgun_weaponreplace ""
+set g_balance_shotgun_weaponstart 1
 set g_balance_shotgun_weaponstartoverride -1
 set g_balance_shotgun_weaponthrowable 1
 // }}}
@@ -260,9 +260,9 @@ 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 50
-set g_balance_crylink_secondary_edgedamage 15
-set g_balance_crylink_secondary_force -400
+set g_balance_crylink_secondary_damage 10
+set g_balance_crylink_secondary_edgedamage 5
+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
@@ -270,17 +270,17 @@ 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 1
+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 5
-set g_balance_crylink_secondary_other_lifetime 5
-set g_balance_crylink_secondary_radius 70
-set g_balance_crylink_secondary_refire 0.8
-set g_balance_crylink_secondary_shots 1
-set g_balance_crylink_secondary_speed 3000
-set g_balance_crylink_secondary_spread 0
-set g_balance_crylink_secondary_spreadtype 1
+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.65
+set g_balance_crylink_secondary_shots 5
+set g_balance_crylink_secondary_speed 7000
+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 ""
@@ -725,7 +725,7 @@ 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_weaponstart 0
 set g_balance_shockwave_weaponstartoverride -1
 set g_balance_shockwave_weaponthrowable 0
 // }}}
@@ -753,10 +753,10 @@ 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 1250
+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.5
+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
@@ -883,7 +883,7 @@ 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 13.1
+set g_balance_okmachinegun_primary_solidpenetration 63
 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
index 2e0e74aa3d7a993b7a97f1ac1b43f9ead3bbc797..13bdc529a9f7364e36ce66ec85b596732e2b0f7b 100644 (file)
@@ -762,11 +762,11 @@ 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_force 200
 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_refire 0.033333
 set g_balance_arc_bolt_speed 2300
 set g_balance_arc_bolt_spread 0
 set g_balance_arc_burst_ammo 15
index 18ee7ea28f1a100f21e29c8e0aed1d0c9fece23e..611f5da95a867d7be500d8caf38b8a84038f12e0 100644 (file)
@@ -40,6 +40,7 @@ bind MWHEELUP weapnext
 bind MWHEELDOWN weapprev
 bind r reload
 bind BACKSPACE dropweapon
+bind k kill
 bind g dropweapon
 bind f +use
 bind v +button8 // drag object
index 06e1922ae77fc612fb754d24eb30aba42d40dd4f..7b2b73abe3433ff3980f6f67f8866ab75a310a71 100644 (file)
@@ -6,7 +6,7 @@
 # adem4ik, 2014
 # Alex Talker <alextalker7@gmail.com>, 2014-2015
 # Andrei Stepanov, 2014
-# Andrei Stepanov, 2014-2018
+# Andrei Stepanov <adem4ik@gmail.com>, 2014-2018
 # Andrey P <andrey.pyntikov@gmail.com>, 2016
 # Artem Vorotnikov <artem@vorotnikov.me>, 2015
 # Lord Canistra <lordcanistra@gmail.com>, 2011
@@ -19,7 +19,7 @@ msgstr ""
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2017-07-09 00:35+0200\n"
 "PO-Revision-Date: 2018-03-16 06:43+0000\n"
-"Last-Translator: Andrei Stepanov\n"
+"Last-Translator: Andrei Stepanov <adem4ik@gmail.com>\n"
 "Language-Team: Russian (http://www.transifex.com/team-xonotic/xonotic/"
 "language/ru/)\n"
 "Language: ru\n"
index 128169c502911d760c7de4707850887c805f6284..c07774a05b99473c12eb20e5f9de754fc87f895c 100644 (file)
@@ -2751,14 +2751,36 @@ effect flac_explode
        velocityjitter 256 256 256
        velocityoffset 0 0 80
 effect tr_bullet
-       type spark
-       alpha 256 256 2560
-       color 0xff8960 0xff8533
-       size 4 4
-       stretchfactor 0.200000
-       tex 70 70
-       trailspacing 750
-       velocitymultiplier 3
+       type beam
+       alpha 500 600 10000
+       color 0xf03000 0xff6010
+       countabsolute 1
+       sizeincrease -3
+       size 0.6 0.8
+       tex 200 200
+effect tr_bullet
+       type smoke
+       airfriction -4
+       alpha 256 256 350
+       color 0x202020 0x404040
+       notunderwater
+       sizeincrease 0.400000
+       size 1 2
+       tex 0 8
+       trailspacing 16
+       velocityjitter 4 4 4
+effect tr_bullet
+       type bubble
+       alpha 256 256 128
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 0.5 0.6
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect smoking_smallemitter
        type alphastatic
        airfriction -1
@@ -8262,3 +8284,34 @@ effect arc_bolt_explode
        tex 40 40
        velocityjitter 224 224 224
        velocityoffset 0 0 80
+effect tr_bullet_weak
+       type beam
+       alpha 75 100 3000
+       color 0xf03000 0xff6010
+       countabsolute 1
+       sizeincrease -3
+       size 0.6 0.8
+       tex 200 200
+effect tr_bullet_weak
+       type smoke
+       airfriction -4
+       alpha 256 256 350
+       color 0x202020 0x404040
+       notunderwater
+       sizeincrease 0.400000
+       size 1 2
+       tex 0 8
+       trailspacing 16
+       velocityjitter 4 4 4
+effect tr_bullet_weak
+       type bubble
+       alpha 256 256 128
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 0.5 0.6
+       tex 62 62
+       trailspacing 32
+       underwater
+       velocityjitter 16 16 16
index c421e5b325b6925c89b17e2a926fe018e5a170b2..ba708cb9f803e9c4446f0f1861c019a3e3510892 100644 (file)
@@ -9,7 +9,7 @@ cl_playerdetailreduction 4
 gl_flashblend 0
 gl_picmip 0
 gl_texturecompression_2d 0
-gl_texturecompression_sky 1
+gl_texturecompression_sky 0
 mod_q3bsp_nolightmaps 0
 r_bloom 0
 r_coronas 1
index e7a1607f15c8274f10603d441f65f9be21a3133d..c43b9d1d3f2e6fe73fddbb33e8489670350edc4d 100644 (file)
@@ -31,6 +31,7 @@ alias cl_hook_gamestart_cts
 alias cl_hook_gamestart_ka
 alias cl_hook_gamestart_ft
 alias cl_hook_gamestart_inv
+alias cl_hook_gamestart_duel
 alias cl_hook_gameend "rpn /cl_matchcount dup load 1 + =" // increase match count every time a game ends
 alias cl_hook_shutdown
 alias cl_hook_activeweapon
index f13dd854ac08ad2f2eea309ae36ba214388ce124..57c9f7b7086f2c8ce25ff9f25cf475c2664c334c 100644 (file)
@@ -28,6 +28,7 @@ alias sv_hook_gamestart_cts
 alias sv_hook_gamestart_ka
 alias sv_hook_gamestart_ft
 alias sv_hook_gamestart_inv
+alias sv_hook_gamestart_duel
 alias sv_hook_gamerestart
 alias sv_hook_gameend
 
@@ -54,16 +55,17 @@ alias sv_vote_gametype_hook_nb
 alias sv_vote_gametype_hook_ons
 alias sv_vote_gametype_hook_rc
 alias sv_vote_gametype_hook_tdm
+alias sv_vote_gametype_hook_duel
 
-// Example preset to allow duel to be used for the gametype voting screen
+// Example preset to allow 1v1ctf to be used for the gametype voting screen
 // sv_vote_gametype_*_type Must be set to the name of the gametype the option is based on
 // sv_vote_gametype_*_name Contains a human-readable name of the gametype
 // sv_vote_gametype_*_description Contains a longer description
-//set sv_vote_gametype_duel_type dm
-//set sv_vote_gametype_duel_name Duel
-//set sv_vote_gametype_duel_description "One vs One match"
+//set sv_vote_gametype_1v1ctf_type ctf
+//set sv_vote_gametype_1v1ctf_name "Capture the Flag Duel"
+//set sv_vote_gametype_1v1ctf_description "One vs One match in CTF"
 //alias sv_vote_gametype_hook_all "set g_maxplayers 0"
-//alias sv_vote_gametype_hook_duel "set g_maxplayers 2"
+//alias sv_vote_gametype_hook_1v1ctf "set g_maxplayers 2"
 
 
 // ===========
@@ -196,6 +198,13 @@ set g_inv_respawn_delay_large_count 0
 set g_inv_respawn_delay_max 0
 set g_inv_respawn_waves 0
 set g_inv_weapon_stay 0
+set g_duel_respawn_delay_small 0
+set g_duel_respawn_delay_small_count 0
+set g_duel_respawn_delay_large 0
+set g_duel_respawn_delay_large_count 0
+set g_duel_respawn_delay_max 0
+set g_duel_respawn_waves 0
+set g_duel_weapon_stay 0
 
 
 // =========
@@ -309,12 +318,15 @@ set g_cts 0 "CTS: complete the stage"
 set g_cts_selfdamage 1 "0 = disable all selfdamage and falldamage in cts"
 set g_cts_finish_kill_delay 10 "prevent cheating by running back to the start line, and starting out with more speed than otherwise possible"
 set g_cts_send_rankings_cnt 15 "send this number of map records to clients"
+set g_cts_removeprojectiles 0 "remove projectiles when the player dies, to prevent using weapons earlier in the stage than intended"
 
 
 // ==========================
 //  deathmatch (ffa or team)
 // ==========================
 set g_dm 1 "Deathmatch: killing any other player is one frag, player with most frags wins"
+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"
@@ -523,3 +535,10 @@ set g_invasion_spawnpoint_spawn_delay 0.5
 set g_invasion_teams 0 "number of teams in invasion (note: use mapinfo to set this)"
 set g_invasion_team_spawns 1 "use team spawns in teamplay invasion mode"
 set g_invasion_type 0 "type of invasion mode - 0: round-based, 1: hunting, 2: complete the stage (note: use mapinfo to set this)"
+
+// ======
+//  duel
+// ======
+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"
index 3565f3c36e66741016aa6ac98e7534ffcd19baf3..49f3b7db3c3fa9958ce33eaae423c9f491e8e065 100644 (file)
Binary files a/gfx/menu/luma/bigbutton_c.tga and b/gfx/menu/luma/bigbutton_c.tga differ
index 0efae80e723d585a483a9892d43dd791915bc8a9..5fb89048098be4f3119826457c6e97f4fc843f28 100644 (file)
Binary files a/gfx/menu/luma/bigbutton_d.tga and b/gfx/menu/luma/bigbutton_d.tga differ
index 3edc7dab2f51ebae12b4a5f4936e42e95047ae8b..638dcd48752dfff421894772ccccb6eb901e0b90 100644 (file)
Binary files a/gfx/menu/luma/bigbutton_f.tga and b/gfx/menu/luma/bigbutton_f.tga differ
index 4f07b0c4be33cc64edc5863755e8d890b5c162a5..0c773b252bcd460293d2a79e8d05a71f5b184cbb 100644 (file)
Binary files a/gfx/menu/luma/bigbutton_n.tga and b/gfx/menu/luma/bigbutton_n.tga differ
index e18e0f6e7951c0ef450e46efbbb561b2e10433d5..eed1781f99d9536b4951a998d58c0c9d1d23da65 100644 (file)
Binary files a/gfx/menu/luma/bigbuttongray_c.tga and b/gfx/menu/luma/bigbuttongray_c.tga differ
index 87b5dd5286f464688a00bfea795986f8a708cc5a..8b6ef4be35ef5d1bac578cff139026cd3cfd0d07 100644 (file)
Binary files a/gfx/menu/luma/bigbuttongray_d.tga and b/gfx/menu/luma/bigbuttongray_d.tga differ
index 3624987845163f992ffbcca977fe669030da027f..b87d09474efd93891205ae344e2ded7544ba087a 100644 (file)
Binary files a/gfx/menu/luma/bigbuttongray_f.tga and b/gfx/menu/luma/bigbuttongray_f.tga differ
index e18e0f6e7951c0ef450e46efbbb561b2e10433d5..eed1781f99d9536b4951a998d58c0c9d1d23da65 100644 (file)
Binary files a/gfx/menu/luma/bigbuttongray_n.tga and b/gfx/menu/luma/bigbuttongray_n.tga differ
index 95bdc3c488526c385fd06c02c36070d9a22a536c..40705b6931fcdd4eb7e05cf9966f589bac305798 100644 (file)
Binary files a/gfx/menu/luma/border.tga and b/gfx/menu/luma/border.tga differ
index b86b63a25fc18c9e0aafc9bb5a74f8f07e9a7849..33c7cb74bbbae06f16b6a9e1cbcf8aefe4aea9eb 100644 (file)
Binary files a/gfx/menu/luma/button_c.tga and b/gfx/menu/luma/button_c.tga differ
index f80433038e859c215b6ec1cdd7a96ae1c42cf9ab..e5b65d7563773328ce48e30a6aa8e98ece7fcbbd 100644 (file)
Binary files a/gfx/menu/luma/button_d.tga and b/gfx/menu/luma/button_d.tga differ
index 0b54fee3403c6556c166cd8e8387181f7c0f9ffc..30d32521a50e75e20b115248849db2f5c9a740dc 100644 (file)
Binary files a/gfx/menu/luma/button_f.tga and b/gfx/menu/luma/button_f.tga differ
index 0dc4fd6af454d300bd713ce577774c96f4484e35..6d098576a3e6c4dbf8405c56b3619bf5b516fee6 100644 (file)
Binary files a/gfx/menu/luma/button_n.tga and b/gfx/menu/luma/button_n.tga differ
index 4c1ae7c0fef5412c24d9caed78455d95a465f072..d05266b40f82636516e219d203237097a75d997b 100644 (file)
Binary files a/gfx/menu/luma/buttongray_c.tga and b/gfx/menu/luma/buttongray_c.tga differ
index e0e8318e00b3d34c347f96e5e72a6c19ad05ba69..4bfab65e9954c469c6393151a873854c8971456f 100644 (file)
Binary files a/gfx/menu/luma/buttongray_d.tga and b/gfx/menu/luma/buttongray_d.tga differ
index cc604bc824b5aca5c947a7c34162862d7d2ef7c7..d5ac917fda07b8c2ada1b214e584c317383d8ff8 100644 (file)
Binary files a/gfx/menu/luma/buttongray_f.tga and b/gfx/menu/luma/buttongray_f.tga differ
index 4c1ae7c0fef5412c24d9caed78455d95a465f072..d05266b40f82636516e219d203237097a75d997b 100644 (file)
Binary files a/gfx/menu/luma/buttongray_n.tga and b/gfx/menu/luma/buttongray_n.tga differ
index f8e6960cc260e7d0a339625bd51c7d2c57d24e78..30669ca6af017b781c55a6bb737008ed465ea02a 100644 (file)
Binary files a/gfx/menu/luma/checkbox_c0.tga and b/gfx/menu/luma/checkbox_c0.tga differ
index 32d2f6d7b59f65039a9aebfd60c8f0768144b0ad..acb9bc609753ce82761cea0cbe8b0078bd825556 100644 (file)
Binary files a/gfx/menu/luma/checkbox_c1.tga and b/gfx/menu/luma/checkbox_c1.tga differ
index b059ab64c4a2112538367009cf88971d339bb18d..f42971a26acc918d01f1340d4485f404b1f62512 100644 (file)
Binary files a/gfx/menu/luma/checkbox_d0.tga and b/gfx/menu/luma/checkbox_d0.tga differ
index e38b9629ceb145fbb77cb06e1c17df96b3556ee5..2346dc73875973c96c18329ec30749ec5d449b59 100644 (file)
Binary files a/gfx/menu/luma/checkbox_d1.tga and b/gfx/menu/luma/checkbox_d1.tga differ
index 5201675e6778e8c2c6f7b473b620df3a53e351dc..ddc0842f7664729e4de86bd9daf40121957c4c5f 100644 (file)
Binary files a/gfx/menu/luma/checkbox_f0.tga and b/gfx/menu/luma/checkbox_f0.tga differ
index 116b29c80d90deb1cc820b3bcf720642334ffc44..fb16d9055b29dbddd3e15f79cf80c9ecb6d0ad61 100644 (file)
Binary files a/gfx/menu/luma/checkbox_f1.tga and b/gfx/menu/luma/checkbox_f1.tga differ
index 9786dc84ed431a56db68ed4fc4343c7e1630ea33..4f4d7120b914e494f1743210b7c24e9ee96c2926 100644 (file)
Binary files a/gfx/menu/luma/checkbox_n0.tga and b/gfx/menu/luma/checkbox_n0.tga differ
index 427d3ce421dffb55ae2c2af3f69d5dcdb0df88cc..1102900dacb5cb4abe360629ddfeebbab958ee5c 100644 (file)
Binary files a/gfx/menu/luma/checkbox_n1.tga and b/gfx/menu/luma/checkbox_n1.tga differ
index eb4b259fcd8dde88d69b43d143be91cd2531bfab..c6698a2c20108291d725ed090680845403ee1941 100644 (file)
Binary files a/gfx/menu/luma/checkmark.tga and b/gfx/menu/luma/checkmark.tga differ
index 36fc40b80438e02f0c4bf7ecbec8445b628c6a62..efcf9b5a563c6d9d42312be3ddbe1c2c071ab8b6 100644 (file)
Binary files a/gfx/menu/luma/clearbutton_c.tga and b/gfx/menu/luma/clearbutton_c.tga differ
index c2418a40d38968035d37c271f81af407edc5deb0..2306d91456144ce1466478c798f1526825ae2447 100644 (file)
Binary files a/gfx/menu/luma/clearbutton_f.tga and b/gfx/menu/luma/clearbutton_f.tga differ
index 3ac282b6e94853fc28259dbea4c58ddc01e61a85..343ae6a173759e31c745a79d3c03af39df340288 100644 (file)
Binary files a/gfx/menu/luma/clearbutton_n.tga and b/gfx/menu/luma/clearbutton_n.tga differ
index 3a8f46fd45749cdc51be15eeadf42cb5194fc650..1e03c392db11049b16089e205d2c2b333a3478d1 100644 (file)
Binary files a/gfx/menu/luma/closebutton_c.tga and b/gfx/menu/luma/closebutton_c.tga differ
index 0b3933b6d30faa8da4517f38bde51f5b2870625c..7f1f5b58f4bca691ede99e0fbbec79d42c868a0f 100644 (file)
Binary files a/gfx/menu/luma/closebutton_f.tga and b/gfx/menu/luma/closebutton_f.tga differ
index 4ea4b1cc12d76e3ed0cb0618a9da1dd635f65706..0313efab7cf060faa50d87f6edf9b194b0749fc9 100644 (file)
Binary files a/gfx/menu/luma/closebutton_n.tga and b/gfx/menu/luma/closebutton_n.tga differ
index 91f343e70339192491eab3787fa99dd32f3a2662..086f9a7a3df6f5f2348214372c809fab0e9fe1e0 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_c.tga and b/gfx/menu/luma/colorbutton_c.tga differ
index 0aa806b0418c56ed3bd97c0296d4f7cd6f73d89d..32dd33e47958c742f26ed175e007ed87032d7b4a 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_f.tga and b/gfx/menu/luma/colorbutton_f.tga differ
index bcba096780ef13ad713664c38997e05e2023dcd5..ca128b7922b3e15b95f46c3b06ac55b27db0ade0 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_n.tga and b/gfx/menu/luma/colorbutton_n.tga differ
index 6775942eeca3197348cf8eb13f29523321223271..30ec7f78a764ab7697a0d19014fa95510e12adb0 100644 (file)
Binary files a/gfx/menu/luma/colorpicker_m.tga and b/gfx/menu/luma/colorpicker_m.tga differ
index b12436a98378463de96600cc261219b18b738875..87a12b6f2c74789a7fa395b5a6bc67c5ddf0b408 100644 (file)
Binary files a/gfx/menu/luma/cursor.tga and b/gfx/menu/luma/cursor.tga differ
index 81e265d9936c94486d5c5145f7305b665113af08..19268ea7d0f2e8d734c66db7c37f789ccb23598f 100644 (file)
Binary files a/gfx/menu/luma/cursor_move.tga and b/gfx/menu/luma/cursor_move.tga differ
index 617323edeece7198d17ece98c8bc5bd738dade12..84f53f99e8543928781fc6941c997152c4cfcc5e 100644 (file)
Binary files a/gfx/menu/luma/cursor_resize.tga and b/gfx/menu/luma/cursor_resize.tga differ
index 606015b012856f35d24d30c4f718e82771c83c40..10a550d512f86d9654a01a28a53c89e825569ef9 100644 (file)
Binary files a/gfx/menu/luma/cursor_resize2.tga and b/gfx/menu/luma/cursor_resize2.tga differ
index 9724f4049782003d45d38640f2db83d01447c717..41e1c2894466410434782d13a60af9e0e0dd4930 100644 (file)
Binary files a/gfx/menu/luma/gametype_as.tga and b/gfx/menu/luma/gametype_as.tga differ
index 196196e5ecd984d8c09e5f87a6036f0a157fc01b..e4e827c7a5a7ebf2b230bee8672796fda38e3428 100644 (file)
Binary files a/gfx/menu/luma/gametype_ca.tga and b/gfx/menu/luma/gametype_ca.tga differ
index eefb2fe0b547d40627a159400a52ec55fbb69b86..13a1175301ea09ec38e4a9687fc7a909a1f63099 100644 (file)
Binary files a/gfx/menu/luma/gametype_ctf.tga and b/gfx/menu/luma/gametype_ctf.tga differ
index da86fa4faf0e27bd33a85a84fc80098bfc534d0f..86c4a1309dc227667d3d7173873c027e398de4ca 100644 (file)
Binary files a/gfx/menu/luma/gametype_cts.tga and b/gfx/menu/luma/gametype_cts.tga differ
index 3d0874ead11edefab9c321165bfa0c802d4a2c12..37a3657b8061eb5191ba8519af9f54f45c8fdfea 100644 (file)
Binary files a/gfx/menu/luma/gametype_dm.tga and b/gfx/menu/luma/gametype_dm.tga differ
index eb6605b5b3db89f84af354e07c7d88538a3986e4..3e7b0dedbd56cc815dc79df3674dba22e292ec2f 100644 (file)
Binary files a/gfx/menu/luma/gametype_dom.tga and b/gfx/menu/luma/gametype_dom.tga differ
index 3558725a542264919c9bf01d0b82b2bcab56b942..ac9a4e2e9658086db86cb1a816cc1f089586db20 100644 (file)
Binary files a/gfx/menu/luma/gametype_duel.tga and b/gfx/menu/luma/gametype_duel.tga differ
index f6228a5106a1fdfa9fe4013e63e63e7c2e629b0f..b0636ba87ab18dd401736369fac19b7837148258 100644 (file)
Binary files a/gfx/menu/luma/gametype_ft.tga and b/gfx/menu/luma/gametype_ft.tga differ
index 90938379725a60b477a751d3ea770965673d2879..237ed6e6f536a0cbdbfebd39d4a7598395e377fa 100644 (file)
Binary files a/gfx/menu/luma/gametype_inf.tga and b/gfx/menu/luma/gametype_inf.tga differ
index d954af1ebc99a0e6c6b94a665f79362f6ac08d02..5003f6ce5a611688c3946da459db945b905ea38a 100644 (file)
Binary files a/gfx/menu/luma/gametype_inv.tga and b/gfx/menu/luma/gametype_inv.tga differ
index e6b35a4e1c40f2ef36b49876ac088901086388db..105ffcfbbc9826bf3993f0ea64c18f6593908ac2 100644 (file)
Binary files a/gfx/menu/luma/gametype_jb.tga and b/gfx/menu/luma/gametype_jb.tga differ
index 38acfc705e989236e7bbe6e259b985cd0017b289..3731ab3c1a59fd23104f268ce4c2c8f0a1f6816c 100644 (file)
Binary files a/gfx/menu/luma/gametype_ka.tga and b/gfx/menu/luma/gametype_ka.tga differ
index df30ff0ea18f5630c3e1f1a3247bc11dcbc39555..a3a678f0f322197b9dda79031a8aec2049f08416 100644 (file)
Binary files a/gfx/menu/luma/gametype_kh.tga and b/gfx/menu/luma/gametype_kh.tga differ
index e14d2a2f9bb58407b2d328c12322cf8ae6e032f5..4cccac846b1389ee18031a4e3518be0cb8e844f0 100644 (file)
Binary files a/gfx/menu/luma/gametype_lms.tga and b/gfx/menu/luma/gametype_lms.tga differ
index 93b021e4555aacef4889d76b5384addc99715edc..37be7c751d113a4053adbd72b4456d82c5f1f098 100644 (file)
Binary files a/gfx/menu/luma/gametype_nb.tga and b/gfx/menu/luma/gametype_nb.tga differ
index 48a0c5a13a37e5ce40de8579fb2f3c0b8d302ecd..d73d19a966f539c2c8e79dbc89cab0fb9c05c523 100644 (file)
Binary files a/gfx/menu/luma/gametype_ons.tga and b/gfx/menu/luma/gametype_ons.tga differ
index a03204238f00dfe439f0b62fc8bbf991a9a4d879..a88c9eef52fb20ebac1903e9af0db58ffb2d8817 100644 (file)
Binary files a/gfx/menu/luma/gametype_rc.tga and b/gfx/menu/luma/gametype_rc.tga differ
index 3a6c0922f4b047a54f7137e430f499745032aedd..2b4a343024924f2dcb514fc0ef2a46c0acade7cd 100644 (file)
Binary files a/gfx/menu/luma/gametype_tdm.tga and b/gfx/menu/luma/gametype_tdm.tga differ
index 8a8f7d984d9ca4e25cae4a32082aa0455557727c..d9af96b9364a9eedba54b94bedd398c506437aad 100644 (file)
Binary files a/gfx/menu/luma/gametype_vip.tga and b/gfx/menu/luma/gametype_vip.tga differ
index c32dd97a85d90dcdc42bf8935af07006b4ee74ca..f7c190e8bc0a563668e52068daa2903e3b5ffb68 100644 (file)
Binary files a/gfx/menu/luma/icon_aeslevel1.tga and b/gfx/menu/luma/icon_aeslevel1.tga differ
index c32dd97a85d90dcdc42bf8935af07006b4ee74ca..f7c190e8bc0a563668e52068daa2903e3b5ffb68 100644 (file)
Binary files a/gfx/menu/luma/icon_aeslevel2.tga and b/gfx/menu/luma/icon_aeslevel2.tga differ
index c90efa8c0d208c899f8cfcb1a6ceb9a332e3c460..f84432ddd328d026ea3c9a476ddbf01f3b1846f0 100644 (file)
Binary files a/gfx/menu/luma/icon_aeslevel3.tga and b/gfx/menu/luma/icon_aeslevel3.tga differ
index c90efa8c0d208c899f8cfcb1a6ceb9a332e3c460..f84432ddd328d026ea3c9a476ddbf01f3b1846f0 100644 (file)
Binary files a/gfx/menu/luma/icon_aeslevel4.tga and b/gfx/menu/luma/icon_aeslevel4.tga differ
index c90efa8c0d208c899f8cfcb1a6ceb9a332e3c460..f84432ddd328d026ea3c9a476ddbf01f3b1846f0 100644 (file)
Binary files a/gfx/menu/luma/icon_aeslevel5.tga and b/gfx/menu/luma/icon_aeslevel5.tga differ
index 83659d08efa00a6c88c137154697f5335ebe2fc5..e7baf78b9cb66cd564e8c16094f169b4bbd7802f 100644 (file)
Binary files a/gfx/menu/luma/icon_ipv4.tga and b/gfx/menu/luma/icon_ipv4.tga differ
index 43d9d41785f364bdb3b61c31641eb93f745adfe0..db474afe755ee253aface8f727fba29488cf7d1b 100644 (file)
Binary files a/gfx/menu/luma/icon_ipv6.tga and b/gfx/menu/luma/icon_ipv6.tga differ
index 79a1f24504e0384a3d224de0113c76b2ae464de1..8ba3747e0ffed110f425687323090bca02742f9a 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_.tga and b/gfx/menu/luma/icon_mod_.tga differ
diff --git a/gfx/menu/luma/icon_mod_XDF.tga b/gfx/menu/luma/icon_mod_XDF.tga
deleted file mode 100644 (file)
index c0b4e6d..0000000
Binary files a/gfx/menu/luma/icon_mod_XDF.tga and /dev/null differ
index ce8c2d50d7704a99a6ce9e36528dc70d9f998479..750bb19b3a672e105e73ec33ed1eb2ea87603c7e 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_instagib.tga and b/gfx/menu/luma/icon_mod_instagib.tga differ
index ba3080a7df31bf0e9e89e9baba6b32807241dcc0..9fc2a9a83aa96b8f7183c54ed19f5af5a27e1d32 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_jeff.tga and b/gfx/menu/luma/icon_mod_jeff.tga differ
index ce8c2d50d7704a99a6ce9e36528dc70d9f998479..750bb19b3a672e105e73ec33ed1eb2ea87603c7e 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_minstagib.tga and b/gfx/menu/luma/icon_mod_minstagib.tga differ
index c5f212c0787e03d5ae2a3d31dfffb0b1827d0bbe..7862e58f389631783449bc6c449897fdd7e22f8d 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_newtoys.tga and b/gfx/menu/luma/icon_mod_newtoys.tga differ
index aeeaeb883a0d02bc86c70416d00e2ec381a38e9b..d72e7f622e46dcfa3935b92e761b49112dd63863 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_overkill.tga and b/gfx/menu/luma/icon_mod_overkill.tga differ
index e9eb0dfd0f14a6aefdc596cddada0f0f95786cee..58901465d5eb0fc89cf3dc5be100cb32d9b3562c 100644 (file)
Binary files a/gfx/menu/luma/icon_mod_quake.tga and b/gfx/menu/luma/icon_mod_quake.tga differ
diff --git a/gfx/menu/luma/icon_mod_xdf.tga b/gfx/menu/luma/icon_mod_xdf.tga
new file mode 100644 (file)
index 0000000..6749a48
Binary files /dev/null and b/gfx/menu/luma/icon_mod_xdf.tga differ
diff --git a/gfx/menu/luma/icon_mod_xpm.tga b/gfx/menu/luma/icon_mod_xpm.tga
new file mode 100644 (file)
index 0000000..47c3fb6
Binary files /dev/null and b/gfx/menu/luma/icon_mod_xpm.tga differ
index fbe4dc9ffacef6a30231ce81766dc638a5aa79e9..041921822fd7ab28e86984c1f735061a6cb4a495 100644 (file)
Binary files a/gfx/menu/luma/icon_pure1.tga and b/gfx/menu/luma/icon_pure1.tga differ
index 841dde650f8ccd05e7ad8303a237635510ec6699..564edf5b3cd366944075edbe57abd72c2ed085c5 100644 (file)
Binary files a/gfx/menu/luma/icon_stats1.tga and b/gfx/menu/luma/icon_stats1.tga differ
index c31aa438efe89a0f3f9653ed4958321c82c95772..658e9c41e531bdaecc4ad896df5481a2a3bb7daa 100644 (file)
Binary files a/gfx/menu/luma/inputbox_f.tga and b/gfx/menu/luma/inputbox_f.tga differ
index 621f50d9cd6ef0536d66f74725681f7bb76afb4f..0bbd45023dbc9b1f478520db1bd870398dc72a76 100644 (file)
Binary files a/gfx/menu/luma/inputbox_n.tga and b/gfx/menu/luma/inputbox_n.tga differ
index 5cd70916d5d2519328d9c0673857aa61148c6803..aa8ee77bd3d22559a3c2d737361eab87b9bd1e99 100644 (file)
Binary files a/gfx/menu/luma/nopreview_map.tga and b/gfx/menu/luma/nopreview_map.tga differ
index c332b6345ac0df9bc63e4cf27fcf7dd1f559ddf7..1806719d0db09944259837da5d13c916659027a6 100644 (file)
Binary files a/gfx/menu/luma/nopreview_menuskin.tga and b/gfx/menu/luma/nopreview_menuskin.tga differ
index e1fa52c67ee88f8c050e2ffe082c31a1e55ce4ec..583a91b47505e0fd3577ff92cba9cef4347e8d24 100644 (file)
Binary files a/gfx/menu/luma/nopreview_player.tga and b/gfx/menu/luma/nopreview_player.tga differ
index 8b60a1b274441481b3254ff9895e166be6d110dc..2cb80f979f2a5e6e438e981479a924e836c9b707 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_c0.tga and b/gfx/menu/luma/radiobutton_c0.tga differ
index d23f9df0207126fee3a5b32274c7c663ad9aed71..d1561539e9ddf8a827b3648c46131476e974d466 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_c1.tga and b/gfx/menu/luma/radiobutton_c1.tga differ
index 16a4ff8a323e0b15d88079964082eb944a67c568..8bc37140dda3bd0bbbaf9f83fa08d198770661ca 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_d0.tga and b/gfx/menu/luma/radiobutton_d0.tga differ
index b4eacffbc29f574eb91b957d4df3ed10c96c090d..93bf16dbd0c9df05ade93d7b5f5e5e9a4bfbc9b1 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_d1.tga and b/gfx/menu/luma/radiobutton_d1.tga differ
index 59ecc0805b5826de64e4a00c7164d9c73c4a2b07..7875e388139b6fdea8d19096a5767f5b1a601785 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_f0.tga and b/gfx/menu/luma/radiobutton_f0.tga differ
index 396e2771a82d3fe4e94714fcada4791209d5ed2f..63ddaf5b47b986f88a3d94e5098a72bbb797ab89 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_f1.tga and b/gfx/menu/luma/radiobutton_f1.tga differ
index 13a96e96900895a580da08f76dae9f5fc351c7fc..150a39286f43fef9f87611f791eecc73e9a13677 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_n0.tga and b/gfx/menu/luma/radiobutton_n0.tga differ
index a64b50cc31b38d79805d86d8c485335de67b61a1..34b6618a93f6b0b8b95c21c1066d5d555e148efe 100644 (file)
Binary files a/gfx/menu/luma/radiobutton_n1.tga and b/gfx/menu/luma/radiobutton_n1.tga differ
index 09333d1412b1d3349d470bced09c77c8bfeeb784..6bedb66c96242d8daa0adce40eb5b559dfbd3759 100644 (file)
Binary files a/gfx/menu/luma/scrollbar_c.tga and b/gfx/menu/luma/scrollbar_c.tga differ
index 109278c9f0997b8a1e1273ca79228f0928646fe2..539328d00af2f1d34cd550511f2ae49f66b5a835 100644 (file)
Binary files a/gfx/menu/luma/scrollbar_f.tga and b/gfx/menu/luma/scrollbar_f.tga differ
index b8a01d1779b3fc878348909232f53d631c8af8d7..e081a306b3d0f98c51c9ead60a5ccc322182816f 100644 (file)
Binary files a/gfx/menu/luma/scrollbar_n.tga and b/gfx/menu/luma/scrollbar_n.tga differ
index 699e11c328f108353d1eb2c79010c68a9633f1f9..c1e21e4f97178ea765b90da1e39cd91f99757a1e 100644 (file)
Binary files a/gfx/menu/luma/scrollbar_s.tga and b/gfx/menu/luma/scrollbar_s.tga differ
index f89a2e605f57526c7d3ec866ca2c08360686c0bd..50e4ffd3dc10ce43c511a0a3e35b53704f8bed45 100644 (file)
Binary files a/gfx/menu/luma/skinpreview.tga and b/gfx/menu/luma/skinpreview.tga differ
index cfaa1e5804da071f55675621780791861d5b3fc2..eef45e9a0a44f8d0439139e9c651b1956c0553cd 100644 (file)
@@ -12,7 +12,7 @@ author sev
 ALIGN_BACKGROUND              c5h5
 ALIGN_BACKGROUND_INGAME       c5h5
 ALPHA_BACKGROUND_INGAME       1
-ALPHA_DISABLED                0.2
+ALPHA_DISABLED                0.25
 ALPHA_BEHIND                  0.5
 
 // button
@@ -115,7 +115,7 @@ POSITION_DIALOG_CREDITS       '-0.05 1.2 0'
 POSITION_DIALOG_QUIT          '1.05 1.2 0'
 
 // font
-ALPHA_TEXT                    0.8
+ALPHA_TEXT                    0.875
 COLOR_TEXT                    '0.96 0.99 1'
 ALPHA_HEADER                  0.5
 COLOR_HEADER                  '0.96 0.99 1'
@@ -144,7 +144,7 @@ COLOR_KEYGRABBER_TITLES       '0.03 0.25 0.49'
 ALPHA_LISTBOX_BACKGROUND      0.5
 COLOR_LISTBOX_BACKGROUND      '0 0 0'
 ALPHA_LISTBOX_SELECTED        1
-COLOR_LISTBOX_SELECTED        '0.97 0.56 0.27'
+COLOR_LISTBOX_SELECTED        '0.9 0.53 0.28'
 ALPHA_LISTBOX_WAITING         0.8
 COLOR_LISTBOX_WAITING         '0.73 0.82 0.9'
 ALPHA_LISTBOX_FOCUSED         0.55
@@ -209,7 +209,7 @@ WIDTH_SLIDERTEXT              0.333333333333
 
 // tooltip
 ALPHA_TOOLTIP                 0.8
-COLOR_TOOLTIP                 '1 0.97 0.94'
+COLOR_TOOLTIP                 '1 0.97 0.95'
 AVOID_TOOLTIP                 '8 8 0'
 BORDER_TOOLTIP                '16 16 0'
 MARGIN_TOOLTIP                '10 8 0'
index 8471b32d97116be45571b4cae98e72c3867b8f2f..b460e27408a59537974f89c84c4e6c4595f8fd57 100644 (file)
Binary files a/gfx/menu/luma/slider_c.tga and b/gfx/menu/luma/slider_c.tga differ
index c264fee985d36a9cdb5ba83df90e8b46b8fc1be5..fbd76c22a51feafb9b9b7a75c7d71057959c29d8 100644 (file)
Binary files a/gfx/menu/luma/slider_d.tga and b/gfx/menu/luma/slider_d.tga differ
index 6ff26873fd55e53d8fa899d659b23569235a4688..96e5318df2650c17651f394aaab6c61419f0452e 100644 (file)
Binary files a/gfx/menu/luma/slider_f.tga and b/gfx/menu/luma/slider_f.tga differ
index 2ee36af322ef7227cfe5f48025a747d73378da03..4d68120e6ef127ef16530f2299a0b5a9b8b92f8d 100644 (file)
Binary files a/gfx/menu/luma/slider_n.tga and b/gfx/menu/luma/slider_n.tga differ
index e5b7141dd3203c1451432a5f14f1228904025499..e78e8a413439a5c2ea61592a0ca9d51c2ef75293 100644 (file)
Binary files a/gfx/menu/luma/slider_s.tga and b/gfx/menu/luma/slider_s.tga differ
index 32ea27c8ed72174d0764a25a6f81d698b2e244e2..fbb29936a640fdf07ed9a50b8c6ac73904931b51 100644 (file)
Binary files a/gfx/menu/luma/tooltip.tga and b/gfx/menu/luma/tooltip.tga differ
diff --git a/gfx/menu/luminos/icon_mod_xpm.tga b/gfx/menu/luminos/icon_mod_xpm.tga
new file mode 100644 (file)
index 0000000..3d51ff3
Binary files /dev/null and b/gfx/menu/luminos/icon_mod_xpm.tga differ
diff --git a/gfx/menu/wickedx/icon_mod_xpm.tga b/gfx/menu/wickedx/icon_mod_xpm.tga
new file mode 100644 (file)
index 0000000..3d51ff3
Binary files /dev/null and b/gfx/menu/wickedx/icon_mod_xpm.tga differ
diff --git a/gfx/menu/xaw/icon_mod_xpm.tga b/gfx/menu/xaw/icon_mod_xpm.tga
new file mode 100644 (file)
index 0000000..3d51ff3
Binary files /dev/null and b/gfx/menu/xaw/icon_mod_xpm.tga differ
index 71cbd68a71540d7a6800a6fb18bad869d273c58a..66bfa6e308efa09a4a5d7d7bc0fea047e6f1dceb 100644 (file)
Binary files a/gfx/scoreboard/player_ready.tga and b/gfx/scoreboard/player_ready.tga differ
index 443abc4f6de2870396896400af6a19d4062eb1fd..c67a4ace5f91e65d9bace365648c3c17af452552 100644 (file)
Binary files a/gfx/scoreboard/playercolor_base.tga and b/gfx/scoreboard/playercolor_base.tga differ
index f9c7307973ec1adfacc097a5608c24311d114c92..d48ea9a98c042983a579e830fe2d0cd30383016b 100644 (file)
Binary files a/gfx/scoreboard/playercolor_pants.tga and b/gfx/scoreboard/playercolor_pants.tga differ
index eeeaf4c370a8442f7e296117437375303a84e4ba..54a3826006049db3400693946e763b250599094a 100644 (file)
Binary files a/gfx/scoreboard/playercolor_shirt.tga and b/gfx/scoreboard/playercolor_shirt.tga differ
index e8a5d348b3a7a443b0094f50c2aef305e8973637..13bc9f3fb63a538a8fecd24ecd0bebee34869311 100644 (file)
Binary files a/gfx/scoreboard/scoreboard_bg.tga and b/gfx/scoreboard/scoreboard_bg.tga differ
index 122d4f482d56e3fd506617579c5e06e739cdb1f0..9a050d5ca646b469ea1d893a674d0d6649dfc55b 100644 (file)
Binary files a/gfx/scoreboard/scoreboard_tableheader.tga and b/gfx/scoreboard/scoreboard_tableheader.tga differ
diff --git a/help-overkill.cfg b/help-overkill.cfg
new file mode 100644 (file)
index 0000000..e48147c
--- /dev/null
@@ -0,0 +1,18 @@
+set help_msg_0 "Wondering why you die so often? Because you're ignoring armor and health pickups"
+set help_msg_1 "Use secondary fire (blaster) on the floor to jump higher"
+set help_msg_2 "Double press W after spawning to accelerate by jumping forward (=dodging)"
+set help_msg_3 "Keep the jump key pressed to stay fast (=bunny-hopping)"
+set help_msg_4 "Run along a flat wall and quickly press W twice to gain speed (=wall dodging)"
+set help_msg_5 "Pick up armor shards from dead enemies to survive the next hit"
+set help_msg_6 "Stand *completely* still, then quickly double press W, A, S or D to dodge"
+set help_msg_7 "Use the blaster to make large jumps or climb walls"
+set help_msg_8 "Use the Shotgun (or Machine Gun) to slow down fast players"
+set help_msg_9 "When running, blaster the floor or walls to gain more speed"
+set help_msg_10 "Use G (default key) to throw Nades (you want the 'dropweapon' bind, not 'hook', for better timing)"
+set help_msg_11 "Don't reload, switch to Shotgun"
+set help_msg_12 "You can blaster the flag or dropped Nades to push them away"
+set help_msg_13 "This is how most pros throw Nades: press G (dropweapon bind), wait *several* seconds, press G again"
+set help_msg_14 "Dodge forward to climb walls faster"
+set help_msg_15 "Double press W, then hold space to start moving"
+set help_msg_16 "Spectate stronger players to learn their tricks"
+set help_msg_count 17 // update this when adding messages - it should be the number of messages (which means last message index + 1)
diff --git a/help-xonotic.cfg b/help-xonotic.cfg
new file mode 100644 (file)
index 0000000..1bd9e27
--- /dev/null
@@ -0,0 +1,60 @@
+set help_msg_0 "Big Admin is watching you, so please be friendly or feel their almighty ban-hammer!"
+set help_msg_1 "If you want to learn more about Xonotic, read ^1'Halogene's Newbie Corner' (https://xonotic.org/guide) ${help_cfg_prefix}as it contains lots of useful tips and tricks, explains all the weapons and helps to improve your gameplay."
+set help_msg_2 "Please watch out for balanced teams and change by pressing F5 (teammenu) or F6 (auto join 'best' team)."
+set help_msg_3 "When trying to bunny-hop you can ^1hold the jump button ${help_cfg_prefix}while you are still in the air, this will make those jumps VERY easy to time and work more reliable."
+set help_msg_4 "When a vote is called you can accept it via F1 or reject it via F2 (default keys)."
+set help_msg_5 "Spectating other (good) players helps to learn new tricks. To spectate press F3 and then Mouse1 to switch between the players you want to spectate. F5, F6 or jump will get you back into the game (default keys)."
+set help_msg_6 "Being a beginner is great! You can learn so many new tricks and improve quickly. Watch others, ask for advice and use your common sense effectively."
+set help_msg_7 "If others are better than you, it does not mean they cheat. Save such complaints for when you have more experience and know what kind of funky stuff is possible."
+set help_msg_8 "In CTF, it's good to move around and get involved in the action. You get fragged quite a bit but you are also most helpful to your team."
+set help_msg_9 "Use the radar to see where your teammates are. Pressing zoom will expand the radar image to give you a better overview."
+set help_msg_10 "Most teammessages display waypoints by default. Use those to guide your teammates. You can also see them and the flagcarrier in the radar."
+set help_msg_11 "Protect your flagcarrier at all cost! Also save health and armor for him, he might need them more than you!"
+set help_msg_12 "You can use the Blaster and most explosive weapons to jump around. Just look 'at your feet' and press fire. If you also jump at the same time, you get even higher."
+set help_msg_13 "Be friendly and helpful to other players! Being angry at others' mistakes is understandable, but nobody is perfect. Try to use calm words when telling them how to correct their mistake."
+set help_msg_14 "You can use the zoom key with all guns, only the Vortex has it as a extra function on Mouse2 (default key)."
+set help_msg_15 "Notice what is happening around you! If your base is empty in CTF, then STAY and defend the flag! Make sure someone defends the flagcarrier or assist him yourself."
+set help_msg_16 "You can drop the weapon you currently have with Backspace (default key). You can help your unarmed teammates this way."
+set help_msg_17 "Learn to use the team messages! You find them in the Setting/Input menu. Try changing them to keys you can press easier than the defaults."
+set help_msg_18 "Gaming should be fun! Try to have a nice time, be helpful, mindful and treat others like you want to be treated."
+set help_msg_19 "Visit the official forum on ^1https://forums.xonotic.org/ ${help_cfg_prefix}and feel free to open a thread if you have questions."
+set help_msg_20 "If you already have a good weapon, it's a great idea to let your teammates get something better than the Shotgun too!"
+set help_msg_21 "Press T to chat with others, press Y for messages to your team only, press TAB to see the scores and U for the chat history (default keys)."
+set help_msg_22 "You can use ^1'suggestmap PART_OF_NAME' ${help_cfg_prefix}to make a map come up at the vote screen after a map was played."
+set help_msg_23 "The console is accessible through the ~ key or by pressing Shift+ESC. It has many more advanced features, use 'cmdlist' and 'cvarlist' to get a full list of available commands/settings."
+set help_msg_24 "The Blaster is a useful tool for gaining speed and jumping around, but it does little damage."
+set help_msg_25 "The Shotgun's primary firemode has spread and is more useful at a closer distance, use secondary for the melee attack and slap into other players faces!"
+set help_msg_26 "The Machine Gun secondary has a burst fire mode and less spread than the primary mode."
+set help_msg_27 "The Mortar is a good all around gun but takes some practice to aim it, because of the projectile's curve."
+set help_msg_28 "The Electro has a combo attack. Fire the primary mode at the balls from the secondary mode for a huge and powerful explosion."
+set help_msg_29 "The Crylink's primary fire bounces. Both firemodes pull your enemies, making it a great tool to stop a flag carrier."
+set help_msg_30 "The Vortex is a powerful sniper gun. Aim carefully!"
+set help_msg_31 "The Hagar is underestimated, but very powerful if you aim right. The secondary mode charges up to four rockets and causes devasting damage if you release them."
+set help_msg_32 "The Devastator is powerful but slow. Keep Mouse1 pressed to guide the rockets. Secondary firemode makes the rocket(s) explode."
+set help_msg_33 "The Arc is a strong lighting beam, which bends slighty if you move your mouse. The secondary firemode is very strong but short. Both firemodes also heal teammates if you shoot at them."
+set help_msg_34 "By default, explosions go through walls. Be careful when hiding behind walls!"
+set help_msg_35 "Get on IRC to chat with fellow players. Take a look at ^1https://xonotic.org/chat/${help_cfg_prefix}."
+set help_msg_36 "Don't drink and frag."
+set help_msg_37 "Don't shoot at players who are typing/chatting. You recognize those players by the keyboard symbols above their head."
+set help_msg_38 "'gg' is shorthand for 'Good Game', 'gl' means 'Good luck' and 'hf' 'Have fun'."
+set help_msg_39 "Players with the prefix '$bot_prefix${help_cfg_prefix}' in their nick are bots on this server. There is also a clan named [BOT]."
+set help_msg_40 "You spawn with ^1two ${help_cfg_prefix}weapons. Use the Blaster for much faster movement."
+set help_msg_41 "Visit the stats page at ^1https://stats.xonotic.org/ ${help_cfg_prefix}and check out how you are doing in the rankings!"
+set help_msg_42 "Start playing 1on1 if you want to learn fast"
+set help_msg_43 "Visit ^1https://xonotic.org/pickup/ ${help_cfg_prefix}to get in touch with the experienced players, ask them stuff and play with them!"
+set help_msg_44 "Look for servers that have a good ping for you. You can't play this game well with a ping > 100. If there are no servers close enough to you, cooperate with your friends to setup one."
+set help_msg_45 "If you want to play the next map you can cast a vote via 'vcall endmatch' in the console. Other players can vote using F1 and F2 (default keys)."
+set help_msg_46 "Always watch your back. Do not just run away, fight back as you retreat. Otherwise, you could be shot in the back."
+set help_msg_47 "Try to get as much armor and health as you can, but remember your teammates need armor and health too."
+set help_msg_48 "Do not attack if you have neither a good weapon, nor health, nor armor."
+set help_msg_49 "Standing still makes you an easy target. You can move around the map faster by bunny hopping."
+set help_msg_50 "You can use the Blaster to climb up walls. Before trying this, become familiar with the basics of Blaster movement."
+set help_msg_51 "You can control your movement in air. Use it to prevent yourself from falling off the map when somebody starts pushing you around."
+set help_msg_52 "Use the Blaster, Mortar or Devastator in space maps to push other players off the map. They will enjoy it."
+set help_msg_53 "You can turn off automatic weapon changing in the Player menu. If you configure your key bindings, manually switching weapons can be faster and easier."
+set help_msg_54 "Choose the right weapon for the job, not just the one that the game automatically puts in your hand."
+set help_msg_55 "Enter ^1'lsmaps' ${help_cfg_prefix}in the console to get a list of maps configured on the server."
+set help_msg_56 "While you are in the air, release the forward key, press one of the left/right keys and move your mouse in the same direction. This will bend your fly/jump path."
+set help_msg_57 "Hold the jump key to keep on jumping (called ^1'bunny-hopping'${help_cfg_prefix}) which will accelerate your speed."
+set help_msg_58 "'xonotic.org/guide changed my life' -- ^x777S^x090Є^x088Є^x000Қ^x900⁻ʸ${help_cfg_prefix}, 2018"
+set help_msg_count 59 // update this when adding messages - it should be the number of messages (which means last message index + 1)
diff --git a/help.cfg b/help.cfg
new file mode 100644 (file)
index 0000000..52cfb09
--- /dev/null
+++ b/help.cfg
@@ -0,0 +1,24 @@
+// Simple help message system
+// It prints messages with the configured name
+
+// You can start the help system with the command help_loop but this has been found to annoy players.
+// A better way is to put `alias sv_hook_gamestart_all "defer 20 help_next"` into your server.cfg,
+// that way you get one message per match.
+
+// the messages need to be starting from 0 and be consecutive
+// for manual use: help_inc switches to the next message, help_doit will print the current message, help_next will do both together
+
+// settings
+set help_cfg_nick "^2Help System^3" "the messages will appear in chat coming from the sever using this name"
+set help_cfg_time 5 "the time between two messages in seconds when started using help_loop"
+set help_cfg_prefix "^2" "prepended to each message, useful to color the nick and message differently"
+
+// aliases making up the actual helpsystem
+set help_tmp_index -1 // -1 since we first increment, then show it
+alias help_say "set help_tmp_oldnick \"$sv_adminnick\"; set sv_adminnick \"$help_cfg_nick\"; say \"$*\"; help_say2"
+alias help_say2 "set sv_adminnick \"$help_tmp_oldnick\""
+alias help_doit "sv_cmd rpn /help_tmp_msg help_msg_$help_tmp_index def; help_doit2"
+alias help_doit2 "help_say $help_cfg_prefix$help_tmp_msg"
+alias help_inc "sv_cmd rpn /help_tmp_index help_tmp_index 1 add $help_msg_count mod def"
+alias help_next "help_inc; help_doit" // increment first - if the ruleset changed, the number of tips could have too, this avoids overflow
+alias help_loop "help_next; defer $help_cfg_time help_loop"
index dc50883e0df2b5b0bfcc10211b55cddc32b705df..07423e3aac74c1034b1587c1b69febcd78eae0d3 100644 (file)
@@ -693,11 +693,11 @@ seta notification_WEAPON_VAPORIZER_MURDER "1" "Enable this multiple notification
 seta notification_WEAPON_VORTEX_MURDER "1" "Enable this multiple notification"
 
 // MSG_CHOICE notifications (count = 28):
-seta notification_CHOICE_CTF_CAPTURE_BROKEN "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_BROKEN "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
 seta notification_CHOICE_CTF_CAPTURE_BROKEN_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
-seta notification_CHOICE_CTF_CAPTURE_TIME "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_TIME "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
 seta notification_CHOICE_CTF_CAPTURE_TIME_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
-seta notification_CHOICE_CTF_CAPTURE_UNBROKEN "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_UNBROKEN "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
 seta notification_CHOICE_CTF_CAPTURE_UNBROKEN_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
 seta notification_CHOICE_CTF_PICKUP_ENEMY "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
 seta notification_CHOICE_CTF_PICKUP_ENEMY_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
index 9c63f431267b47977c5303182ca9600f22008c95..db756608defe4a18404579bd22bca0c42b97625c 100644 (file)
@@ -411,6 +411,8 @@ float autocvar_cl_hitsound_min_pitch = 0.75;
 float autocvar_cl_hitsound_max_pitch = 1.5;
 float autocvar_cl_hitsound_nom_damage = 25;
 float autocvar_cl_hitsound_antispam_time;
+int autocvar_cl_eventchase_spectated_change = 1;
+float autocvar_cl_eventchase_spectated_change_time = 1;
 int autocvar_cl_eventchase_death = 1;
 float autocvar_cl_eventchase_distance = 140;
 bool autocvar_cl_eventchase_frozen = false;
index 035ba2a1647c29a2445ca54d73022670536cfed3..522859c8b193ea1d4c4729b72ba50d6322aafc5c 100644 (file)
@@ -600,7 +600,7 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer)
                return;
        this.csqcmodel_predraw_run = framecount;
 
-       if(!this.modelindex || this.model == "null")
+       if(!this.modelindex || this.model == "null" || this.alpha < 0)
        {
                this.drawmask = 0;
                return;
@@ -608,7 +608,7 @@ void CSQCModel_Hook_PreDraw(entity this, bool isplayer)
        else
                this.drawmask = MASK_NORMAL;
 
-       if(this.isplayermodel) // this checks if it's a player MODEL!
+       if(this.isplayermodel && this.drawmask) // this checks if it's a player MODEL!
        {
                CSQCPlayer_ModelAppearance_Apply(this, this.entnum == player_localnum + 1);
                CSQCPlayer_LOD_Apply(this);
index 22cbc1a2df32b072905fa8ce9caee5de4f256dc4..5204e8f36dbcd09f54912bab92b453094914e01c 100644 (file)
@@ -77,6 +77,7 @@ float nb_pb_period;
 // 0 - playing
 // >0 - id of spectated player
 float spectatee_status;
+float spectatee_status_changed_time;
 
 // short mapname
 string shortmapname;
index 2becced8e0cbcda94ad910946fc4480939b21856..bee8d0568ec2ac1afe7b7ba2704cb3dc77b08f9f 100644 (file)
@@ -561,6 +561,26 @@ void Hud_Dynamic_Frame()
        HUD_Scale_Disable();
 }
 
+bool HUD_WouldShowCursor()
+{
+       if(autocvar__hud_configure)
+               return true;
+       if(hud_panel_radar_mouse)
+               return true;
+       if(mv_active)
+               return true;
+       //entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1)); // TODO: doesn't use regular cursor handling
+       //if(local_player.viewloc && (local_player.viewloc.spawnflags & VIEWLOC_FREEAIM))
+               //return true;
+       if(HUD_Radar_Clickable())
+               return true;
+       if(HUD_MinigameMenu_IsOpened())
+               return true;
+       if(QuickMenu_IsOpened())
+               return true;
+       return false;
+}
+
 void HUD_Main()
 {
        int i;
@@ -676,10 +696,15 @@ void HUD_Main()
                HUD_Panel_Draw(HUD_PANEL(RADAR));
        if(autocvar__con_chat_maximized)
                HUD_Panel_Draw(HUD_PANEL(CHAT));
-       if(hud_panel_quickmenu)
+       if (QuickMenu_IsOpened())
                HUD_Panel_Draw(HUD_PANEL(QUICKMENU));
        HUD_Panel_Draw(HUD_PANEL(SCOREBOARD));
 
+       bool cursor_active_prev = cursor_active;
+       cursor_active = HUD_WouldShowCursor();
+       if (cursor_active_prev != cursor_active && autocvar_hud_cursormode)
+               setcursormode(cursor_active);
+
        if (intermission == 2)
                HUD_Reset();
 
index 68d1e6bffabb1c327a75d5068b91a7cfd072683e..d2349a6a5c60bef7f384b1c31d41cb89114c88e6 100644 (file)
@@ -7,6 +7,8 @@ void Hud_Dynamic_Frame();
 
 bool HUD_Radar_Clickable();
 void HUD_Radar_Mouse();
+bool HUD_WouldShowCursor();
+bool QuickMenu_IsOpened();
 
 REGISTRY(hud_panels, BITS(6))
 #define hud_panels_from(i) _hud_panels_from(i, NULL)
@@ -73,8 +75,6 @@ int vote_prev; // previous state of vote_active to check for a change
 float vote_alpha;
 float vote_change; // "time" when vote_active changed
 
-float hud_panel_quickmenu;
-
 vector mousepos;
 vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
 vector panel_click_resizeorigin; // coordinates for opposite point when resizing
@@ -228,7 +228,7 @@ REGISTER_HUD_PANEL(MINIGAMEHELP,    HUD_MinigameHelp,   PANEL_CONFIG_NO
 REGISTER_HUD_PANEL(MINIGAMEMENU,    HUD_MinigameMenu,   PANEL_CONFIG_NO                          , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME | PANEL_SHOW_MAPVOTE | PANEL_SHOW_WITH_SB) // MINIGAMEMENU
 REGISTER_HUD_PANEL(MAPVOTE,         MapVote_Draw,       PANEL_CONFIG_NO                          ,                                             PANEL_SHOW_MAPVOTE                     ) // MAPVOTE
 REGISTER_HUD_PANEL(ITEMSTIME,       HUD_ItemsTime,      PANEL_CONFIG_MAIN | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME                                                                ) // ITEMSTIME
-REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      PANEL_CONFIG_MAIN                        , PANEL_SHOW_MAINGAME                                                                ) // QUICKMENU
+REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      PANEL_CONFIG_MAIN                        , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME                                          ) // QUICKMENU
 REGISTER_HUD_PANEL(SCOREBOARD,      Scoreboard_Draw,    PANEL_CONFIG_NO                          , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME | PANEL_SHOW_MAPVOTE | PANEL_SHOW_WITH_SB) // SCOREBOARD
 // always add new panels to the end of list
 
index e8ec807be5bc4f9c4e0f59e9410b748da1520757..3043e6e6860d90a0673829688f681eff6fb44e0d 100644 (file)
@@ -5,6 +5,7 @@
 #include <client/autocvars.qh>
 #include <client/defs.qh>
 #include <client/miscfunctions.qh>
+#include <client/view.qh>
 
 #define HUD_Write(s) fputs(fh, s)
 #define HUD_Write_Cvar(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n"))
@@ -253,6 +254,7 @@ void HUD_Configure_Exit_Force()
                hud_configure_menu_open = 0;
                localcmd("togglemenu\n");
        }
+       cursor_type = CURSOR_NORMAL;
        cvar_set("_hud_configure", "0");
 }
 
@@ -760,7 +762,7 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                if (bInputType == 1)
                        return true;
                if (!hud_configure_menu_open)
-                       cvar_set("_hud_configure", "0");
+                       HUD_Configure_Exit_Force();
        }
        else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // switch panel
        {
@@ -951,7 +953,7 @@ LABEL(find_tab_panel)
        return true;
 }
 
-float HUD_Panel_Check_Mouse_Pos(float allow_move)
+int HUD_Panel_Check_Mouse_Pos(bool allow_move)
 {
        int i, j = 0;
        while(j < hud_panels_COUNT)
@@ -968,30 +970,30 @@ float HUD_Panel_Check_Mouse_Pos(float allow_move)
                // move
                if(allow_move && mousepos.x > panel_pos.x && mousepos.y > panel_pos.y && mousepos.x < panel_pos.x + panel_size.x && mousepos.y < panel_pos.y + panel_size.y)
                {
-                       return 1;
+                       return CURSOR_MOVE;
                }
                // resize from topleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       return 2;
+                       return CURSOR_RESIZE;
                }
                // resize from topright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       return 3;
+                       return CURSOR_RESIZE2;
                }
                // resize from bottomleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       return 3;
+                       return CURSOR_RESIZE2;
                }
                // resize from bottomright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       return 2;
+                       return CURSOR_RESIZE;
                }
        }
-       return 0;
+       return CURSOR_NORMAL;
 }
 
 // move a panel to the beginning of the panel order array (which means it gets drawn last, on top of everything else)
@@ -1111,15 +1113,11 @@ void HUD_Panel_EnableMenu()
        hud_configure_menu_open = 2;
        localcmd("menu_showhudoptions ", highlightedPanel.panel_name, "\n");
 }
-float mouse_over_panel;
 void HUD_Panel_Mouse()
 {
        if(autocvar__menu_alpha == 1)
                return;
 
-       if (!autocvar_hud_cursormode)
-               update_mousepos();
-
        if(mouseClicked)
        {
                if(prevMouseClicked == 0)
@@ -1150,7 +1148,7 @@ void HUD_Panel_Mouse()
                                        prevMouseClickedTime = time;
                                        prevMouseClickedPos = mousepos;
                                }
-                               mouse_over_panel = HUD_Panel_Check_Mouse_Pos(mouseClicked & S_MOUSE1);
+                               cursor_type = HUD_Panel_Check_Mouse_Pos(mouseClicked & S_MOUSE1);
                        }
                }
                else
@@ -1203,25 +1201,12 @@ void HUD_Panel_Mouse()
                if(prevMouseClicked)
                        highlightedAction = 0;
                if(hud_configure_menu_open == 2)
-                       mouse_over_panel = 0;
+                       cursor_type = CURSOR_NORMAL;
                else
-                       mouse_over_panel = HUD_Panel_Check_Mouse_Pos(true);
-               if (mouse_over_panel && !tab_panel)
+                       cursor_type = HUD_Panel_Check_Mouse_Pos(true);
+               if (cursor_type != CURSOR_NORMAL && !tab_panel) // mouse over a panel?
                        drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .1, DRAWFLAG_NORMAL);
        }
-       // draw cursor after performing move/resize to have the panel pos/size updated before mouse_over_panel
-       float cursor_alpha = 1 - autocvar__menu_alpha;
-
-       if(!mouse_over_panel)
-               draw_cursor_normal(mousepos, '1 1 1', cursor_alpha);
-       else if(mouse_over_panel == 1)
-               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
-       else if(mouse_over_panel == 2)
-               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize", '1 1 1', cursor_alpha);
-       else
-               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize2", '1 1 1', cursor_alpha);
-
-       prevMouseClicked = mouseClicked;
 }
 void HUD_Configure_DrawGrid()
 {
@@ -1258,8 +1243,6 @@ void HUD_Configure_Frame()
 
                if(!hud_configure_prev)
                {
-                       if(autocvar_hud_cursormode)
-                               setcursormode(1);
                        hudShiftState = 0;
                        for(i = hud_panels_COUNT - 1; i >= 0; --i)
                                hud_panels_from(panel_order[i]).update_time = time;
@@ -1279,8 +1262,6 @@ void HUD_Configure_Frame()
        {
                if(hud_configure_menu_open)
                        hud_configure_menu_open = 0;
-               if(autocvar_hud_cursormode)
-                       setcursormode(0);
                hud_dynamic_shake_factor = -1;
        }
 }
index 7b7d82b4445c376ea46a019daf14ee2488b0c5dc..f63ffb1deab223f0c31425248acfbee784399a48 100644 (file)
@@ -118,7 +118,7 @@ void HUD_InfoMessages()
 
                        MUTATOR_CALLHOOK(DrawInfoMessages, pos, mySize);
 
-                       if(!warmup_stage && gametype == MAPINFO_TYPE_LMS)
+                       if(!warmup_stage && ISGAMETYPE(LMS))
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
index 87e4a7fb251af875266a9ea72c82cdd6449e1f91..4d1691a7fd57798ac639b7023f6a04f81e476a36 100644 (file)
@@ -54,9 +54,9 @@ void HUD_Mod_CA(vector myPos, vector mySize)
        mod_active = 1; // required in each mod function that always shows something
 
        int layout;
-       if(gametype == MAPINFO_TYPE_CA)
+       if(ISGAMETYPE(CA))
                layout = autocvar_hud_panel_modicons_ca_layout;
-       else //if(gametype == MAPINFO_TYPE_FREEZETAG)
+       else //if(ISGAMETYPE(FREEZETAG))
                layout = autocvar_hud_panel_modicons_freezetag_layout;
        int rows, columns;
        float aspect_ratio;
@@ -528,7 +528,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
 
        // clientside personal record
        string rr;
-       if(gametype == MAPINFO_TYPE_CTS)
+       if(ISGAMETYPE(CTS))
                rr = CTS_RECORD;
        else
                rr = RACE_RECORD;
index a6c65183d4541cc0cb23c1cdf133e594fc3c1e0c..aa77690a6a4a23ee36aa39548511289239ab8ad1 100644 (file)
@@ -18,7 +18,7 @@ void HUD_Physics()
        {
                if(!autocvar_hud_panel_physics) return;
                if(spectatee_status == -1 && (autocvar_hud_panel_physics == 1 || autocvar_hud_panel_physics == 3)) return;
-               if(autocvar_hud_panel_physics == 3 && !(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return;
+               if(autocvar_hud_panel_physics == 3 && !(ISGAMETYPE(RACE) || ISGAMETYPE(CTS))) return;
        }
 
        HUD_Panel_LoadCvars();
index e7e3c6d65241b9b7a207faa2aedcaa9603ac4009..29907505bceffef9edf1fb472f8554b1567fd5ea 100644 (file)
@@ -4,6 +4,7 @@
 #include <client/defs.qh>
 #include <client/miscfunctions.qh>
 #include <common/ent_cs.qh>
+#include <common/minigames/cl_minigames.qh>
 #include <client/hud/_mod.qh>
 #include <client/mapvoting.qh>
 
@@ -57,8 +58,21 @@ void QuickMenu_Page_ClearEntry(int i)
        QuickMenu_Page_Command_Type[i] = 0;
 }
 
+bool HUD_QuickMenu_Forbidden()
+{
+       return (mv_active
+               || (hud_configure_prev && hud_configure_prev != -1)
+               || HUD_MinigameMenu_IsOpened()
+               || (QuickMenu_TimeOut && time > QuickMenu_TimeOut));
+}
+
+// returns true if succeded, false otherwise
 bool QuickMenu_Open(string mode, string submenu, string file)
 {
+       QuickMenu_TimeOut = 0;
+       if (HUD_QuickMenu_Forbidden())
+               return false;
+
        int fh = -1;
        string s;
 
@@ -166,9 +180,6 @@ bool QuickMenu_Open(string mode, string submenu, string file)
        else
                QuickMenu_Page_Load("", 0);
 
-       hud_panel_quickmenu = 1;
-       if(autocvar_hud_cursormode)
-               setcursormode(1);
        hudShiftState = 0;
 
        QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
@@ -192,14 +203,9 @@ void QuickMenu_Close()
        for (i = 0; i < QUICKMENU_MAXLINES; ++i)
                QuickMenu_Page_ClearEntry(i);
        QuickMenu_Page_Entries = 0;
-       hud_panel_quickmenu = 0;
        mouseClicked = 0;
        prevMouseClicked = 0;
        QuickMenu_Buffer_Close();
-
-       if(autocvar_hud_cursormode)
-       if(!mv_active)
-               setcursormode(0);
 }
 
 // It assumes submenu open tag is already detected
@@ -487,9 +493,6 @@ void QuickMenu_Mouse()
                return;
        }
 
-       if (!autocvar_hud_cursormode)
-               update_mousepos();
-
        panel = HUD_PANEL(QUICKMENU);
        HUD_Panel_LoadCvars();
 
@@ -525,10 +528,6 @@ void QuickMenu_Mouse()
                                QuickMenu_Page_ActiveEntry((entry_num < QUICKMENU_MAXLINES - 1) ? entry_num + 1 : 0);
                }
        }
-
-       draw_cursor_normal(mousepos, '1 1 1', 0.8);
-
-       prevMouseClicked = mouseClicked;
 }
 
 void HUD_Quickmenu_DrawEntry(vector pos, string desc, string option, vector fontsize)
@@ -571,16 +570,10 @@ void HUD_QuickMenu()
 {
        if(!autocvar__hud_configure)
        {
-               if (hud_configure_prev && hud_configure_prev != -1)
-                       QuickMenu_Close();
-
-               if(!hud_draw_maximized) return;
-               if(mv_active) return;
-               //if(!autocvar_hud_panel_quickmenu) return;
-               if(!hud_panel_quickmenu) return;
+               if (!hud_draw_maximized || !QuickMenu_IsOpened())
+                       return;
 
-               if(QuickMenu_TimeOut)
-               if(time > QuickMenu_TimeOut)
+               if (HUD_QuickMenu_Forbidden())
                {
                        QuickMenu_Close();
                        return;
index 6a190f2ca5f7c9b14c90590ed81f5227acc56bf0..7d09cf1ff5430276df551fe95c2025ab33258371 100644 (file)
@@ -98,7 +98,7 @@ void HUD_RaceTimer ()
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_racetimer) return;
-               if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return;
+               if(!(ISGAMETYPE(RACE) || ISGAMETYPE(CTS))) return;
                if(spectatee_status == -1) return;
        }
 
index 65073d9fed09700f5c8aebc6dfd6c322f6a05294..cd4551725b3f90ba23440ef1db843a2fadd05f34 100644 (file)
@@ -27,8 +27,6 @@ void HUD_Radar_Show_Maximized(bool doshow, bool clickable)
        {
                if (clickable)
                {
-                       if(autocvar_hud_cursormode)
-                               setcursormode(1);
                        hud_panel_radar_mouse = 1;
 
                        // we must unset the player's buttons, as they aren't released elsewhere
@@ -43,9 +41,6 @@ void HUD_Radar_Show_Maximized(bool doshow, bool clickable)
        {
                hud_panel_radar_mouse = 0;
                mouseClicked = 0;
-               if(autocvar_hud_cursormode)
-               if(!mv_active)
-                       setcursormode(0);
        }
 }
 void HUD_Radar_Hide_Maximized()
@@ -141,9 +136,6 @@ void HUD_Radar_Mouse()
                return;
        }
 
-       if (!autocvar_hud_cursormode)
-               update_mousepos();
-
        panel = HUD_PANEL(RADAR);
        HUD_Panel_LoadCvars();
 
@@ -169,9 +161,6 @@ void HUD_Radar_Mouse()
                HUD_Radar_Hide_Maximized();
                return;
        }
-
-
-       draw_cursor_normal(mousepos, '1 1 1', 0.8);
 }
 
 void HUD_Radar()
@@ -354,7 +343,7 @@ void HUD_Radar()
        IL_EACH(g_radaricons, it.teamradar_icon, {
                if ( hud_panel_radar_mouse )
                if ( GetResourceAmount(it, RESOURCE_HEALTH) >= 0 )
-               if ( it.team == myteam + 1 || gametype == MAPINFO_TYPE_RACE || !teamplay )
+               if ( it.team == myteam + 1 || ISGAMETYPE(RACE) || !teamplay )
                {
                        vector coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(it.origin));
                        if(vdist((mousepos - coord), <, 8))
index 56fa5867c240f33484f9495d4818bde4b5197e51..525bf614b8be11e0cd01c075ec857b61c2937090 100644 (file)
@@ -140,7 +140,7 @@ void HUD_Score()
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_score) return;
-               if(spectatee_status == -1 && (gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return;
+               if(spectatee_status == -1 && (ISGAMETYPE(RACE) || ISGAMETYPE(CTS))) return;
        }
 
        HUD_Panel_LoadCvars();
index 32ccccfca3355dedfa235c20e96f316ee61ed2b4..4989aac508cdb221238a6593ad28fbfd677e7ccc 100644 (file)
@@ -61,6 +61,9 @@ float autocvar_hud_panel_scoreboard_namesize = 15;
 bool autocvar_hud_panel_scoreboard_accuracy = true;
 bool autocvar_hud_panel_scoreboard_accuracy_doublerows = false;
 bool autocvar_hud_panel_scoreboard_accuracy_nocolors = false;
+float autocvar_hud_panel_scoreboard_accuracy_showdelay = 2;
+float autocvar_hud_panel_scoreboard_accuracy_showdelay_minpos = 0.75;
+
 bool autocvar_hud_panel_scoreboard_ctf_leaderboard = true;
 
 bool autocvar_hud_panel_scoreboard_dynamichud = false;
@@ -1025,6 +1028,12 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
                        field_pos.x += fieldpadding + (max(fieldsize, min_fieldsize) - fieldsize) * 0.5;
                        drawstring(field_pos, field, hud_fontsize, sbt_field_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
                }
+               if(pl.eliminated)
+               {
+                       h_size.x = column_width + hud_fontsize.x * 0.25;
+                       h_size.y = hud_fontsize.y;
+                       drawfill(pos - hud_fontsize.x * 0.25 * eX, h_size, '0 0 0', 0.5 * panel_fg_alpha, DRAWFLAG_NORMAL);
+               }
                pos.x += column_width;
                pos.x += hud_fontsize.x;
        }
@@ -1136,7 +1145,7 @@ bool Scoreboard_WouldDraw()
                return true;
        else if (intermission == 2)
                return false;
-       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS && !active_minigame)
+       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && !ISGAMETYPE(CTS) && !active_minigame)
                return true;
        else if (scoreboard_showscores_force)
                return true;
@@ -1146,6 +1155,15 @@ bool Scoreboard_WouldDraw()
 float average_accuracy;
 vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
 {
+       if (frametime)
+       {
+               if (scoreboard_fade_alpha == 1)
+                       scoreboard_acc_fade_alpha = min(1, scoreboard_acc_fade_alpha + frametime * 10);
+               else
+                       scoreboard_acc_fade_alpha = 1; // sync fading with the scoreboard
+       }
+       vector initial_pos = pos;
+
        WepSet weapons_stat = WepSet_GetFromStat();
        WepSet weapons_inmap = WepSet_GetFromStat_InMap();
        int disownedcnt = 0;
@@ -1179,7 +1197,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
        float weapon_height = 29;
        float height = hud_fontsize.y + weapon_height;
 
-       drawstring(pos + eX * panel_bg_padding, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(pos + eX * panel_bg_padding, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', panel_fg_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
        pos.y += 1.25 * hud_fontsize.y;
        if(panel.current_panel_bg != "0")
                pos.y += panel_bg_border;
@@ -1187,7 +1205,11 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
        panel_pos = pos;
        panel_size.y = height * rows;
        panel_size.y += panel_bg_padding * 2;
+
+       float panel_bg_alpha_save = panel_bg_alpha;
+       panel_bg_alpha *= scoreboard_acc_fade_alpha;
        HUD_Panel_DrawBg();
+       panel_bg_alpha = panel_bg_alpha_save;
 
        vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
        if(panel.current_panel_bg != "0")
@@ -1205,18 +1227,18 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
        float weapon_width = tmp.x / columnns / rows;
 
        if (sbt_bg_alpha)
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
 
        if(sbt_highlight)
        {
                // column highlighting
                for (int i = 0; i < columnns; ++i)
                        if ((i % 2) == 0)
-                               drawfill(pos + eX * weapon_width * rows * i, vec2(weapon_width * rows, height * rows), '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+                               drawfill(pos + eX * weapon_width * rows * i, vec2(weapon_width * rows, height * rows), '0 0 0', sbt_highlight_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
 
                // row highlighting
                for (int i = 0; i < rows; ++i)
-                       drawfill(pos + eY * (weapon_height + height * i), vec2(tmp.x, hud_fontsize.y), rgb, sbt_highlight_alpha, DRAWFLAG_NORMAL);
+                       drawfill(pos + eY * (weapon_height + height * i), vec2(tmp.x, hud_fontsize.y), rgb, sbt_highlight_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
        }
 
        average_accuracy = 0;
@@ -1249,7 +1271,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                        weapon_alpha = 0.2 * sbt_fg_alpha;
 
                // weapon icon
-               drawpic_aspect_skin(tmpos, it.model2, vec2(weapon_width, weapon_height), '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(tmpos, it.model2, vec2(weapon_width, weapon_height), '1 1 1', weapon_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
                // the accuracy
                if (weapon_stats >= 0) {
                        weapons_with_stats += 1;
@@ -1264,7 +1286,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                        if(!autocvar_hud_panel_scoreboard_accuracy_nocolors)
                                rgb = Accuracy_GetColor(weapon_stats);
 
-                       drawstring(tmpos + vec2(padding, weapon_height), s, hud_fontsize, rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       drawstring(tmpos + vec2(padding, weapon_height), s, hud_fontsize, rgb, sbt_fg_alpha * scoreboard_acc_fade_alpha, DRAWFLAG_NORMAL);
                }
                tmpos.x += weapon_width * rows;
                pos.x += weapon_width * rows;
@@ -1280,7 +1302,10 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
 
        panel_size.x += panel_bg_padding * 2; // restore initial width
-       return end_pos;
+
+       if (scoreboard_acc_fade_alpha == 1)
+               return end_pos;
+       return initial_pos + (end_pos - initial_pos) * scoreboard_acc_fade_alpha;
 }
 
 vector MapStats_DrawKeyValue(vector pos, string key, string value) {
@@ -1379,7 +1404,7 @@ vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_siz
        vector hl_rgb = rgb + '0.5 0.5 0.5';
 
        pos.y += hud_fontsize.y;
-       drawstring(pos + eX * panel_bg_padding, ((gametype == MAPINFO_TYPE_CTF) ? _("Capture time rankings") : _("Rankings")), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(pos + eX * panel_bg_padding, ((ISGAMETYPE(CTF)) ? _("Capture time rankings") : _("Rankings")), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
        pos.y += 1.25 * hud_fontsize.y;
        if(panel.current_panel_bg != "0")
                pos.y += panel_bg_border;
@@ -1469,6 +1494,39 @@ vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_siz
        return end_pos;
 }
 
+float scoreboard_time;
+bool have_weapon_stats;
+bool Scoreboard_AccuracyStats_WouldDraw(float ypos)
+{
+       if (ISGAMETYPE(CTS) || ISGAMETYPE(RACE) || ISGAMETYPE(NEXBALL))
+               return false;
+       if (!autocvar_hud_panel_scoreboard_accuracy || warmup_stage || ypos > 0.91 * vid_conheight)
+               return false;
+
+       if (time < scoreboard_time + autocvar_hud_panel_scoreboard_accuracy_showdelay
+               && ypos > autocvar_hud_panel_scoreboard_accuracy_showdelay_minpos * vid_conheight
+               && !intermission)
+       {
+               return false;
+       }
+
+       if (!have_weapon_stats)
+       {
+               FOREACH(Weapons, it != WEP_Null, {
+                       int weapon_stats = weapon_accuracy[i - WEP_FIRST];
+                       if (weapon_stats >= 0)
+                       {
+                               have_weapon_stats = true;
+                               break;
+                       }
+               });
+               if (!have_weapon_stats)
+                       return false;
+       }
+
+       return true;
+}
+
 void Scoreboard_Draw()
 {
        if(!autocvar__hud_configure)
@@ -1477,6 +1535,8 @@ void Scoreboard_Draw()
 
                // frametime checks allow to toggle the scoreboard even when the game is paused
                if(scoreboard_active) {
+                       if (scoreboard_fade_alpha < 1)
+                               scoreboard_time = time;
                        if(hud_configure_menu_open == 1)
                                scoreboard_fade_alpha = 1;
                        float scoreboard_fadeinspeed = autocvar_hud_panel_scoreboard_fadeinspeed;
@@ -1500,7 +1560,10 @@ void Scoreboard_Draw()
                }
 
                if (!scoreboard_fade_alpha)
+               {
+                       scoreboard_acc_fade_alpha = 0;
                        return;
+               }
        }
        else
                scoreboard_fade_alpha = 0;
@@ -1600,12 +1663,10 @@ void Scoreboard_Draw()
                pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size);
        }
 
-       bool show_accuracy = (gametype != MAPINFO_TYPE_CTS && gametype != MAPINFO_TYPE_RACE && gametype != MAPINFO_TYPE_NEXBALL);
-
-       if (show_accuracy && autocvar_hud_panel_scoreboard_accuracy && !warmup_stage)
+       if (Scoreboard_AccuracyStats_WouldDraw(pos.y))
                pos = Scoreboard_AccuracyStats_Draw(pos, panel_bg_color, bg_size);
 
-       if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE || (autocvar_hud_panel_scoreboard_ctf_leaderboard && gametype == MAPINFO_TYPE_CTF && STAT(CTF_SHOWLEADERBOARD))) {
+       if(ISGAMETYPE(CTS) || ISGAMETYPE(RACE) || (autocvar_hud_panel_scoreboard_ctf_leaderboard && ISGAMETYPE(CTF) && STAT(CTF_SHOWLEADERBOARD))) {
                if(race_speedaward) {
                        drawcolorcodedstring(pos, sprintf(_("Speed award: %d%s ^7(%s^7)"), race_speedaward, race_speedaward_unit, ColorTranslateRGB(race_speedaward_holder)), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                        pos.y += 1.25 * hud_fontsize.y;
@@ -1646,7 +1707,7 @@ void Scoreboard_Draw()
        tl = STAT(TIMELIMIT);
        fl = STAT(FRAGLIMIT);
        ll = STAT(LEADLIMIT);
-       if(gametype == MAPINFO_TYPE_LMS)
+       if(ISGAMETYPE(LMS))
        {
                if(tl > 0)
                        str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
index b2bda4829e1084b71652488f78b1444ca10b203e..f585b480fe70b119f2491c3df712d5475aa2f3b3 100644 (file)
@@ -3,6 +3,7 @@
 
 bool scoreboard_active;
 float scoreboard_fade_alpha;
+float scoreboard_acc_fade_alpha;
 
 void Cmd_Scoreboard_SetFields(int argc);
 void Scoreboard_Draw();
index 0dcbb70dba3cfe067d51160d74b2c26d8be70196..e01aa751757e3087b25038cdac422e6b162c4049 100644 (file)
@@ -63,6 +63,8 @@ void HUD_Timer()
 
        if (intermission_time) {
                timer = seconds_tostring(max(0, floor(intermission_time - STAT(GAMESTARTTIME))));
+       } else if (warmup_stage && warmup_timeleft >= 60) {
+               timer = _("WARMUP");
        } else if (autocvar_hud_panel_timer_increment || (!warmup_stage && timelimit == 0) || (warmup_stage && warmup_timeleft <= 0)) {
                if (time < STAT(GAMESTARTTIME))
                        timer = seconds_tostring(0); //while restart is still active, show 00:00
index 57b32039dc50fdf401d4da978413c0e4192a800f..0337eccfc215cac966713dd4602018548129b935 100644 (file)
@@ -9,7 +9,7 @@
 
 void HUD_Vote()
 {
-       if(autocvar_cl_allow_uid2name == -1 && (gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE || (serverflags & SERVERFLAG_PLAYERSTATS)))
+       if(autocvar_cl_allow_uid2name == -1 && (ISGAMETYPE(CTS) || ISGAMETYPE(RACE) || (serverflags & SERVERFLAG_PLAYERSTATS)))
        {
                // this dialog gets overriden by the uid2name menu dialog, if it exists
                // TODO remove this client side uid2name dialog in the next release
index 6844b1e078d7ad30380aae9913c1301832a5bc1d..51324e1c5e09aa320895b35d1725ba572d21382d 100644 (file)
@@ -223,6 +223,8 @@ void Shutdown()
 
        localcmd("\ncl_hook_shutdown\n");
 
+       localcmd("\n-button14\n");
+
        deactivate_minigame();
        HUD_MinigameMenu_Close(NULL, NULL, NULL);
 }
@@ -363,20 +365,21 @@ void PostInit()
 // In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos.
 float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
 {
-    TC(int, bInputType);
-       if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
+       TC(int, bInputType);
+       bool override = false;
+       override |= HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary);
+       if (override)
                return true;
 
-       if (QuickMenu_InputEvent(bInputType, nPrimary, nSecondary))
-               return true;
+       override |= QuickMenu_InputEvent(bInputType, nPrimary, nSecondary);
 
-       if (HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary))
-               return true;
+       override |= HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary);
 
-       if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
-               return true;
+       override |= MapVote_InputEvent(bInputType, nPrimary, nSecondary);
+
+       override |= HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary);
 
-       if (HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary))
+       if(override)
                return true;
 
        return false;
@@ -528,6 +531,7 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
                race_laptime = 0;
                race_checkpointtime = 0;
                hud_dynamic_shake_factor = -1;
+               spectatee_status_changed_time = time;
        }
        if (autocvar_hud_panel_healtharmor_progressbar_gfx)
        {
index 8a0e78a0d8126fa7fa78fcca829a5c2af1b1f411..f0f8f1d4bea5ad62563c20df43bc0ce6ad2c9f29 100644 (file)
@@ -11,6 +11,8 @@ string minimapname;
 
 bool postinit;
 entity gametype;
+// temporary hack
+#define ISGAMETYPE(NAME) (gametype == MAPINFO_TYPE_##NAME)
 
 float FONT_USER = 8;
 
index 03e94dc7f304238bc916443bc4a6fbef512d7bc7..37cb59e082101f645ac197f6c224c12715f62bfd 100644 (file)
@@ -321,6 +321,7 @@ float MapVote_Selection(vector topleft, vector cellsize, float rows, float colum
        return mv_mouse_selection;
 }
 
+vector prev_mousepos;
 void MapVote_Draw()
 {
        string map;
@@ -339,10 +340,11 @@ void MapVote_Draw()
 
        if (!autocvar_hud_cursormode)
        {
-               vector mpos = mousepos;
-               update_mousepos();
-               if (mpos.x != mousepos.x || mpos.y != mousepos.y)
+               if (mousepos.x != prev_mousepos.x || mousepos.y != prev_mousepos.y)
+               {
                        mv_selection_keyboard = 0;
+                       prev_mousepos = mousepos;
+               }
        }
 
        center = (vid_conwidth - 1)/2;
@@ -485,8 +487,6 @@ void MapVote_Draw()
                pos.x = (xmax+xmin)*0.5;
                MapVote_DrawAbstain(pos, dist.x, xmax - xmin, tmp, i);
        }
-
-       draw_cursor_normal(mousepos, '1 1 1', panel_fg_alpha);
 }
 
 void Cmd_MapVote_MapDownload(int argc)
@@ -649,8 +649,7 @@ void GameTypeVote_ReadOption(int i)
 void MapVote_Init()
 {
        mv_active = 1;
-       if(autocvar_hud_cursormode) setcursormode(1);
-       else mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+       if(!autocvar_hud_cursormode) mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
        mv_selection = -1;
        mv_selection_keyboard = 0;
 
index 7c1ece5a3dc395c0afea7f4f2bfdfd8ab8519d4f..2fc1559494728343e27fed7b3282f2c37d668a0e 100644 (file)
@@ -38,8 +38,18 @@ const float SHOWNAMES_FADESPEED = 4;
 const float SHOWNAMES_FADEDELAY = 0.4;
 void Draw_ShowNames(entity this)
 {
-       if (this.sv_entnum == (current_player + 1))  // self or spectatee
-               if (!(autocvar_hud_shownames_self && autocvar_chase_active)) return;
+       if (this.sv_entnum == current_player + 1) // self or spectatee
+       {
+               if (!autocvar_chase_active)
+                       return;
+
+               if (!autocvar_hud_shownames_self
+                       && !(spectatee_status > 0 && time <= spectatee_status_changed_time + 1))
+               {
+                       return;
+               }
+       }
+
        if (!this.sameteam && !autocvar_hud_shownames_enemies) return;
        bool hit;
        if (!autocvar_hud_shownames_crosshairdistance && this.sameteam)
@@ -118,7 +128,7 @@ void Draw_ShowNames(entity this)
                // FIXME: alpha is negative when dead, breaking death fade
                if (!this.csqcmodel_isdead) a *= f;
        }
-       if (a < ALPHA_MIN_VISIBLE && gametype != MAPINFO_TYPE_CTS) return;
+       if (a < ALPHA_MIN_VISIBLE && ISGAMETYPE(CTS)) return;
        if (vdist(this.origin - view_origin, >=, max_shot_distance)) return;
        float dist = vlen(this.origin - view_origin);
        if (autocvar_hud_shownames_maxdistance)
index e873f64535bd40ca74bb8126e882c92f7085fe64..8fba190c64bfb32db161be60402cbbda6e8db29b 100644 (file)
@@ -48,6 +48,7 @@
 #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
 
 float autocvar_cl_viewmodel_scale;
+float autocvar_cl_viewmodel_alpha;
 
 bool autocvar_cl_bobmodel;
 float autocvar_cl_bobmodel_speed;
@@ -297,12 +298,9 @@ void viewmodel_draw(entity this)
        if(!this.activeweapon || !autocvar_r_drawviewmodel)
                return;
        int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
-       float a = this.alpha;
-       static bool wasinvehicle;
+       float a = ((autocvar_cl_viewmodel_alpha) ? bound(-1, autocvar_cl_viewmodel_alpha, this.m_alpha) : this.m_alpha);
        bool invehicle = player_localentnum > maxclients;
        if (invehicle) a = -1;
-       else if (wasinvehicle) a = 1;
-       wasinvehicle = invehicle;
        Weapon wep = this.activeweapon;
        int c = entcs_GetClientColors(current_player);
        vector g = weaponentity_glowmod(wep, NULL, c, this);
@@ -635,6 +633,8 @@ vector GetOrthoviewFOV(vector ov_worldmin, vector ov_worldmax, vector ov_mid, ve
 // this function must match W_SetupShot!
 float zoomscript_caught;
 
+bool minigame_wasactive;
+
 vector wcross_origin;
 float wcross_scale_prev, wcross_alpha_prev;
 vector wcross_color_prev;
@@ -803,34 +803,41 @@ vector liquidcolor_prev;
 
 float eventchase_current_distance;
 float eventchase_running;
-bool WantEventchase(entity this)
+int WantEventchase(entity this)
 {
        if(autocvar_cl_orthoview)
-               return false;
+               return 0;
        if(STAT(GAME_STOPPED) || intermission)
-               return true;
+               return 1;
        if(this.viewloc)
-               return true;
+               return 1;
        if(spectatee_status >= 0)
        {
                if(hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0))
-                       return true;
+                       return 1;
                if(MUTATOR_CALLHOOK(WantEventchase, this))
-                       return true;
+                       return 1;
                if(autocvar_cl_eventchase_frozen && STAT(FROZEN))
-                       return true;
+                       return 1;
                if(autocvar_cl_eventchase_death && (STAT(HEALTH) <= 0))
                {
                        if(autocvar_cl_eventchase_death == 2)
                        {
                                // don't stop eventchase once it's started (even if velocity changes afterwards)
                                if(this.velocity == '0 0 0' || eventchase_running)
-                                       return true;
+                                       return 1;
                        }
-                       else return true;
+                       else return 1;
+               }
+               if (spectatee_status > 0 && autocvar_cl_eventchase_spectated_change)
+               {
+                       if (time <= spectatee_status_changed_time + min(3, autocvar_cl_eventchase_spectated_change_time))
+                               return 1;
+                       else if (eventchase_running)
+                               return -1; // disable chase_active while eventchase is still enabled so to avoid a glicth
                }
        }
-       return false;
+       return 0;
 }
 
 void HUD_Crosshair_Vehicle(entity this)
@@ -1532,7 +1539,7 @@ void HUD_Draw(entity this)
        if(autocvar_r_letterbox == 0)
                if(autocvar_viewsize < 120)
                {
-                       if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS))
+                       if(!(ISGAMETYPE(RACE) || ISGAMETYPE(CTS)))
                                Accuracy_LoadLevels();
 
                        HUD_Main();
@@ -1559,6 +1566,51 @@ void ViewLocation_Mouse()
        //draw_cursor(viewloc_mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
 }
 
+void HUD_Cursor_Show()
+{
+       float cursor_alpha = 1 - autocvar__menu_alpha;
+       if(cursor_type == CURSOR_NORMAL)
+               draw_cursor_normal(mousepos, '1 1 1', cursor_alpha);
+       else if(cursor_type == CURSOR_MOVE)
+               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
+       else if(cursor_type == CURSOR_RESIZE)
+               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize", '1 1 1', cursor_alpha);
+       else if(cursor_type == CURSOR_RESIZE2)
+               draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize2", '1 1 1', cursor_alpha);
+}
+
+void HUD_Mouse(entity player)
+{
+       if(autocvar__menu_alpha == 1)
+               return;
+
+       if(!cursor_active)
+       {
+               if(player.viewloc && (player.viewloc.spawnflags & VIEWLOC_FREEAIM))
+                       ViewLocation_Mouse(); // NOTE: doesn't use cursormode
+               return;
+       }
+
+       if(!autocvar_hud_cursormode)
+               update_mousepos();
+
+       if(autocvar__hud_configure)
+               HUD_Panel_Mouse();
+       else
+       {
+               if (HUD_MinigameMenu_IsOpened())
+                       HUD_Minigame_Mouse();
+               if (QuickMenu_IsOpened())
+                       QuickMenu_Mouse();
+               if (HUD_Radar_Clickable())
+                       HUD_Radar_Mouse();
+       }
+
+       prevMouseClicked = mouseClicked;
+
+       HUD_Cursor_Show();
+}
+
 bool ov_enabled;
 float oldr_nearclip;
 float oldr_farclip_base;
@@ -1695,7 +1747,8 @@ void CSQC_UpdateView(entity this, float w, float h)
                        }
                }
 
-               if(WantEventchase(this))
+               int eventchase = WantEventchase(this);
+               if (eventchase)
                {
                        vector current_view_origin_override = '0 0 0';
                        vector view_offset_override = '0 0 0';
@@ -1773,7 +1826,8 @@ void CSQC_UpdateView(entity this, float w, float h)
                        if(!local_player.viewloc)
                                setproperty(VF_ANGLES, WarpZone_TransformVAngles(WarpZone_trace_transform, view_angles));
                }
-               else if(autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
+
+               if (eventchase <= 0 && autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
                {
                        eventchase_running = false;
                        cvar_set("chase_active", "0");
@@ -1964,6 +2018,20 @@ void CSQC_UpdateView(entity this, float w, float h)
                }
        }
 
+       if(active_minigame && HUD_MinigameMenu_IsOpened())
+       {
+               if(!minigame_wasactive)
+               {
+                       localcmd("+button14\n");
+                       minigame_wasactive = true;
+               }
+       }
+       else if(minigame_wasactive)
+       {
+               localcmd("-button14\n");
+               minigame_wasactive = false;
+       }
+
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
@@ -2399,7 +2467,7 @@ void CSQC_UpdateView(entity this, float w, float h)
        else if(cvar("r_glsl_postprocess") == 2)
                cvar_set("r_glsl_postprocess", "0");
 
-       /*if(gametype == MAPINFO_TYPE_CTF)
+       /*if(ISGAMETYPE(CTF))
          {
          ctf_view();
          } else */
@@ -2448,16 +2516,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                cvar_set("vid_conheight", h0);
        }
 
-       if(autocvar__hud_configure)
-               HUD_Panel_Mouse();
-       else if (HUD_MinigameMenu_IsOpened() || active_minigame)
-               HUD_Minigame_Mouse();
-       else if(QuickMenu_IsOpened())
-               QuickMenu_Mouse();
-       else if(local_player.viewloc && (local_player.viewloc.spawnflags & VIEWLOC_FREEAIM))
-               ViewLocation_Mouse(); // NOTE: doesn't use cursormode
-       else
-               HUD_Radar_Mouse();
+       HUD_Mouse(local_player);
 
        cl_notice_run();
        unpause_update();
index 93af4255e2b95570cd5ab278b22af71110b8368e..5bce2fe3246818293474b6383dd05a2a1d68ce39 100644 (file)
@@ -15,3 +15,10 @@ void TrueAim_Init();
 entity viewmodels[MAX_WEAPONSLOTS];
 
 vector viewloc_mousepos;
+
+bool cursor_active;
+int cursor_type;
+const int CURSOR_NORMAL = 0;
+const int CURSOR_MOVE = 1;
+const int CURSOR_RESIZE = 2;
+const int CURSOR_RESIZE2 = 3;
index f4871e7fc6194803adf7fa2a8b9ec1276abc06c3..067c0badb7da09a184c192daf1841d47c782da81 100644 (file)
@@ -265,19 +265,19 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                        this.fade_rate = 0;
                }
 
-               int myteam = ReadByte();
-               this.team = myteam - 1;
+               int proj_team = ReadByte();
+               this.team = proj_team - 1;
 
                if(teamplay)
                {
-                       if(myteam)
+                       if(proj_team)
                                this.colormap = (this.team) * 0x11; // note: team - 1 on server (client uses different numbers)
                        else
                                this.colormap = 0x00;
                        this.colormap |= BIT(10); // RENDER_COLORMAPPED
                }
                else
-                       this.colormap = myteam;
+                       this.colormap = proj_team;
                // TODO: projectiles use glowmaps for their color, not teams
                #if 0
                if(this.colormap > 0)
index b53a9ba0e9cbf6123d7438736785e8206200358a..69fe458269845c7e0acf7b3eaa17c3008cd5581d 100644 (file)
@@ -210,9 +210,8 @@ vector animdecide_getloweranim(entity e)
                                return vec3(e.anim_duckwalkbackright.x, t, ANIMPRIO_CROUCH);
                        case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
                                return vec3(e.anim_duckwalkbackleft.x, t, ANIMPRIO_CROUCH);
-                       default:
-                               return vec3(e.anim_duckidle.x, t, ANIMPRIO_CROUCH);
                }
+               return vec3(e.anim_duckidle.x, t, ANIMPRIO_CROUCH);
        }
        else
        {
@@ -236,12 +235,11 @@ vector animdecide_getloweranim(entity e)
                                return vec3(e.anim_backright.x, t, ANIMPRIO_ACTIVE);
                        case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
                                return vec3(e.anim_backleft.x, t, ANIMPRIO_ACTIVE);
-                       default:
-                               return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
                }
+               return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
        }
        // can't get here
-       return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
+       //return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
 }
 
 void animdecide_setimplicitstate(entity e, float onground)
index 3b534ab781d0f7d8a4614a4534fe4f208a28899d..882e715cde3bf3673045499e643547a01a2d44bf 100644 (file)
@@ -229,6 +229,7 @@ EFFECT(0, SMOKING,                  "smoking")
 EFFECT(0, SMOKE_RING,               "smoke_ring")
 EFFECT(0, JUMPPAD,                  "jumppad_activate")
 EFFECT(1, BULLET,                   "tr_bullet")
+EFFECT(1, BULLET_WEAK,              "tr_bullet_weak")
 EFFECT(0, EF_FLAME,                 "EF_FLAME")
 EFFECT(0, EF_STARDUST,              "EF_STARDUST")
 EFFECT(0, TE_EXPLOSION,             "TE_EXPLOSION")
index b659e8a8517a83755718d93ea06c03c9a9989db8..d3c184fab743f78878f3c4d01fc5a42c34ea17a5 100644 (file)
@@ -1,3 +1,12 @@
+// docs: https://www.quakewiki.net/darkplaces-wiki/effectinfo-scripting-reference/
+// use `cl_particles_reloadeffects` to reload effects without restarting engine
+// use `chase_active 1` and `cl_lockview 1` to see effects from different perspectives
+// `dumpeffectinfo` currently doesn't work so edit effectinfo.txt manually, just try to keep the files in sync
+
+// `tex` are indices into particles/particlefont.tga (see particles/particlefont-template.tga for numbers)
+// the first index is inclusive, second exclusive (so `tex 0 8` will use images 0 though 7)
+// unless they're equal (`tex 69 69` is the same as `tex 69 70`)
+
 // item respawn effect
 DEF(TE_WIZSPIKE);
 // flare particle and light
@@ -4410,20 +4419,50 @@ SUB(flac_explode) {
 
 // bullet trail (somewhat like a tracer)
 DEF(tr_bullet);
+SUB(tr_bullet) {
+       MY(alpha) = '500 600 10000';
+       MY(color_min) = "0xf03000";
+       MY(color_max) = "0xff6010";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = -3;
+       MY(size_min) = 0.6;
+       MY(size_max) = 0.8;
+       my(tex_min) = 200;
+       my(tex_max) = 200;
+       MY(type) = "beam";
+}
+SUB(tr_bullet) {
+       MY(airfriction) = -4;
+       MY(alpha) = '256 256 350';
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 0.4;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 0;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 16;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '4 4 4';
+}
 SUB(tr_bullet) {
        MY(alpha_min) = 256;
        MY(alpha_max) = 256;
-       MY(alpha_fade) = 2560;
-       MY(color_min) = "0xff8960";
-       MY(color_max) = "0xff8533";
-       MY(size_min) = 4;
-       MY(size_max) = 4;
-       MY(stretchfactor) = 0.200000;
-       MY(tex_min) = 70;
-       MY(tex_max) = 70;
-       MY(trailspacing) = 750;
-       MY(type) = "spark";
-       MY(velocitymultiplier) = 3;
+       MY(alpha_fade) = 128;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 0.5;
+       MY(size_max) = 0.6;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 16;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
 }
 
 // smoke emitter for small pipes
@@ -8889,3 +8928,51 @@ SUB(arc_bolt_explode) {
        MY(velocityjitter) = '224.0 224.0 224.0';
        MY(velocityoffset) = '0.0 0.0 80.0';
 }
+
+// weak bullet trail (somewhat like a tracer)
+DEF(tr_bullet_weak);
+SUB(tr_bullet_weak) {
+       MY(alpha) = '75 100 3000';
+       MY(color_min) = "0xf03000";
+       MY(color_max) = "0xff6010";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = -3;
+       MY(size_min) = 0.6;
+       MY(size_max) = 0.8;
+       my(tex_min) = 200;
+       my(tex_max) = 200;
+       MY(type) = "beam";
+}
+SUB(tr_bullet_weak) {
+       MY(airfriction) = -4;
+       MY(alpha) = '256 256 350';
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 0.4;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 0;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 16;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '4 4 4';
+}
+SUB(tr_bullet_weak) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 128;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 0.5;
+       MY(size_max) = 0.6;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 32;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
index c4cd002c782221fe420d38415c25fed570909a4d..a33ec87a01a34a5a8406f57aa3c3d52829cf3994 100644 (file)
@@ -6,6 +6,7 @@
 #include <common/gamemodes/gamemode/cts/_mod.inc>
 #include <common/gamemodes/gamemode/deathmatch/_mod.inc>
 #include <common/gamemodes/gamemode/domination/_mod.inc>
+#include <common/gamemodes/gamemode/duel/_mod.inc>
 #include <common/gamemodes/gamemode/freezetag/_mod.inc>
 #include <common/gamemodes/gamemode/invasion/_mod.inc>
 #include <common/gamemodes/gamemode/keepaway/_mod.inc>
index d7c1aa66cc35f6f3f8143031123542abf134a33c..ffd71d59d3f1092453b6d83f8048003693dfa531 100644 (file)
@@ -6,6 +6,7 @@
 #include <common/gamemodes/gamemode/cts/_mod.qh>
 #include <common/gamemodes/gamemode/deathmatch/_mod.qh>
 #include <common/gamemodes/gamemode/domination/_mod.qh>
+#include <common/gamemodes/gamemode/duel/_mod.qh>
 #include <common/gamemodes/gamemode/freezetag/_mod.qh>
 #include <common/gamemodes/gamemode/invasion/_mod.qh>
 #include <common/gamemodes/gamemode/keepaway/_mod.qh>
index 95b5b8ccf2ffc2ee5d2ed395c98f1c1376d57be9..fcfc78917f8239f64f2d72c3eee62ee5ed8511a3 100644 (file)
@@ -41,5 +41,8 @@ void(entity bot) havocbot_ast_reset_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;
 
+// assault game mode: Which team is attacking in this round?
+float assault_attacker_team;
+
 // predefined spawnfuncs
 void target_objective_decrease_activate(entity this);
index 4c889cb24be655fe22afa1af098046b1a0219082..2bbed4a9abb78f5cb8fd73ecbdf5d9a9a68474f7 100644 (file)
@@ -298,7 +298,7 @@ MUTATOR_HOOKFUNCTION(ca, ClientDisconnect)
 {
        entity player = M_ARGV(0, entity);
 
-       if (player.caplayer == 1)
+       if (IS_PLAYER(player) && !IS_DEAD(player))
                ca_LastPlayerForTeam_Notify(player);
        return true;
 }
@@ -307,7 +307,7 @@ MUTATOR_HOOKFUNCTION(ca, MakePlayerObserver)
 {
        entity player = M_ARGV(0, entity);
 
-       if (!IS_DEAD(player))
+       if (IS_PLAYER(player) && !IS_DEAD(player))
                ca_LastPlayerForTeam_Notify(player);
        if (player.killindicator_teamchange == -2) // player wants to spectate
                player.caplayer = 0;
@@ -380,12 +380,12 @@ MUTATOR_HOOKFUNCTION(ca, PlayerDamage_SplitHealthArmor)
        entity frag_attacker = M_ARGV(1, entity);
        entity frag_target = M_ARGV(2, entity);
        float frag_damage = M_ARGV(7, float);
-       float damage_take = M_ARGV(4, float);
-       float damage_save = M_ARGV(5, float);
+       float damage_take = bound(0, M_ARGV(4, float), GetResourceAmount(frag_target, RESOURCE_HEALTH));
+       float damage_save = bound(0, M_ARGV(5, float), GetResourceAmount(frag_target, RESOURCE_ARMOR));
 
        float excess = max(0, frag_damage - damage_take - damage_save);
 
-       if (frag_target != frag_attacker && IS_PLAYER(frag_attacker))
+       if (frag_target != frag_attacker && IS_PLAYER(frag_attacker) && DIFF_TEAM(frag_target, frag_attacker))
                GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * autocvar_g_ca_damage2score_multiplier);
 }
 
index efbbf94e72aceee1716ad7d50f9ad49edc6a66b7..2696a4e87892d4dca5dbc3b688d91f0b4bf85059 100644 (file)
@@ -1519,7 +1519,7 @@ void havocbot_goalrating_ctf_enemyflag(entity this, float ratingscale)
                {
                        // adjust rating of our flag carrier depending on his health
                        head = head.tag_entity;
-                       float f = bound(0, (head.health + head.armorvalue) / 100, 2) - 1;
+                       float f = bound(0, (GetResourceAmount(head, RESOURCE_HEALTH) + GetResourceAmount(head, RESOURCE_ARMOR)) / 100, 2) - 1;
                        ratingscale += ratingscale * f * 0.1;
                }
                navigation_routerating(this, head, ratingscale, 10000);
index 636aeb6de7550f64735679ad00327eea5d400857..31bdae0790d558e40695cb57083e0a55f19cff3f 100644 (file)
@@ -5,6 +5,7 @@
 
 float autocvar_g_cts_finish_kill_delay;
 bool autocvar_g_cts_selfdamage;
+bool autocvar_g_cts_removeprojectiles;
 
 // legacy bot roles
 .float race_checkpoint;
@@ -253,6 +254,14 @@ MUTATOR_HOOKFUNCTION(cts, PlayerDies)
 
        frag_target.respawn_flags |= RESPAWN_FORCE;
        race_AbandonRaceCheck(frag_target);
+
+       if(autocvar_g_cts_removeprojectiles)
+       {
+               IL_EACH(g_projectiles, it.owner == frag_target && (it.flags & FL_PROJECTILE),
+               {
+                       delete(it);
+               });
+       }
 }
 
 MUTATOR_HOOKFUNCTION(cts, HavocBot_ChooseRole)
diff --git a/qcsrc/common/gamemodes/gamemode/duel/_mod.inc b/qcsrc/common/gamemodes/gamemode/duel/_mod.inc
new file mode 100644 (file)
index 0000000..5925816
--- /dev/null
@@ -0,0 +1,4 @@
+// generated file; do not modify
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/duel/sv_duel.qc>
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/duel/_mod.qh b/qcsrc/common/gamemodes/gamemode/duel/_mod.qh
new file mode 100644 (file)
index 0000000..00e553c
--- /dev/null
@@ -0,0 +1,4 @@
+// generated file; do not modify
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/duel/sv_duel.qh>
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/duel/sv_duel.qc b/qcsrc/common/gamemodes/gamemode/duel/sv_duel.qc
new file mode 100644 (file)
index 0000000..fc662e2
--- /dev/null
@@ -0,0 +1,22 @@
+#include "sv_duel.qh"
+
+MUTATOR_HOOKFUNCTION(duel, GetPlayerLimit)
+{
+       M_ARGV(0, int) = 2; // duel is always 1v1!
+}
+
+MUTATOR_HOOKFUNCTION(duel, Scores_CountFragsRemaining)
+{
+       // announce remaining frags?
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(duel, FilterItemDefinition)
+{
+       entity definition = M_ARGV(0, entity);
+
+       if(definition.instanceOfPowerup)
+       {
+               return !autocvar_g_duel_with_powerups;
+       }
+}
diff --git a/qcsrc/common/gamemodes/gamemode/duel/sv_duel.qh b/qcsrc/common/gamemodes/gamemode/duel/sv_duel.qh
new file mode 100644 (file)
index 0000000..d255c9b
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <common/mutators/base.qh>
+REGISTER_MUTATOR(duel, false)
+{
+    MUTATOR_STATIC();
+       return 0;
+}
+
+bool autocvar_g_duel_with_powerups;
index ce5eb3032bb21b5602e12b9518edc3896b9bcf27..0b87c03bd1489cba14f3bca30d31604534c7b65a 100644 (file)
@@ -19,8 +19,7 @@ void freezetag_count_alive_players()
        FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it),
        {
                ++total_players;
-               if ((GetResourceAmount(it, RESOURCE_HEALTH) < 1) ||
-                       (STAT(FROZEN, it) == 1))
+               if (GetResourceAmount(it, RESOURCE_HEALTH) < 1 || STAT(FROZEN, it) == FROZEN_NORMAL)
                {
                        continue;
                }
@@ -155,7 +154,7 @@ entity freezetag_LastPlayerForTeam(entity this)
 {
        entity last_pl = NULL;
        FOREACH_CLIENT(IS_PLAYER(it) && it != this && SAME_TEAM(it, this), {
-               if (!STAT(FROZEN, it) && GetResourceAmount(it, RESOURCE_HEALTH) >= 1)
+               if (STAT(FROZEN, it) != FROZEN_NORMAL && GetResourceAmount(it, RESOURCE_HEALTH) >= 1)
                {
                        if (!last_pl)
                                last_pl = it;
@@ -204,7 +203,7 @@ void freezetag_Freeze(entity targ, entity attacker)
        if(autocvar_g_freezetag_frozen_maxtime > 0)
                targ.freezetag_frozen_timeout = time + autocvar_g_freezetag_frozen_maxtime;
 
-       Freeze(targ, 0, 1, true);
+       Freeze(targ, 0, FROZEN_NORMAL, true);
 
        freezetag_count_alive_players();
 
@@ -213,7 +212,7 @@ void freezetag_Freeze(entity targ, entity attacker)
 
 bool freezetag_isEliminated(entity e)
 {
-       if(IS_PLAYER(e) && (STAT(FROZEN, e) == 1 || IS_DEAD(e)))
+       if(IS_PLAYER(e) && (STAT(FROZEN, e) == FROZEN_NORMAL || IS_DEAD(e)))
                return true;
        return false;
 }
@@ -231,7 +230,7 @@ void havocbot_goalrating_ft_freeplayers(entity this, float ratingscale, vector o
        entity best_pl = NULL;
        float best_dist2 = FLOAT_MAX;
        FOREACH_CLIENT(IS_PLAYER(it) && it != this && SAME_TEAM(it, this), {
-               if (STAT(FROZEN, it) == 1)
+               if (STAT(FROZEN, it) == FROZEN_NORMAL)
                {
                        if(vdist(it.origin - org, >, sradius))
                                continue;
@@ -267,10 +266,12 @@ void havocbot_role_ft_offense(entity this)
 
        // Count how many players on team are unfrozen.
        int unfrozen = 0;
-       FOREACH_CLIENT(IS_PLAYER(it) && SAME_TEAM(it, this) && !STAT(FROZEN, it), { unfrozen++; });
+       FOREACH_CLIENT(IS_PLAYER(it) && SAME_TEAM(it, this) && STAT(FROZEN, it) != FROZEN_NORMAL, {
+               unfrozen++;
+       });
 
        // If only one left on team or if role has timed out then start trying to free players.
-       if ((unfrozen == 0 && !STAT(FROZEN, this)) || time > this.havocbot_role_timeout)
+       if ((!unfrozen && STAT(FROZEN, this) != FROZEN_NORMAL) || time > this.havocbot_role_timeout)
        {
                LOG_TRACE("changing role to freeing");
                this.havocbot_role = havocbot_role_ft_freeing;
@@ -327,10 +328,11 @@ void havocbot_role_ft_freeing(entity this)
 
 void ft_RemovePlayer(entity this)
 {
-       SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0); // neccessary to update correctly alive stats
-       if(!STAT(FROZEN, this))
+       if (STAT(FROZEN, this) != FROZEN_NORMAL)
                freezetag_LastPlayerForTeam_Notify(this);
-       Unfreeze(this);
+       Unfreeze(this, false);
+
+       SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0); // neccessary to correctly count alive players
        freezetag_count_alive_players();
 }
 
@@ -358,8 +360,8 @@ MUTATOR_HOOKFUNCTION(ft, PlayerDies)
        if(round_handler_IsActive())
        if(round_handler_CountdownRunning())
        {
-               if(STAT(FROZEN, frag_target))
-                       Unfreeze(frag_target);
+               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
        }
@@ -370,20 +372,19 @@ MUTATOR_HOOKFUNCTION(ft, PlayerDies)
                || frag_deathtype == DEATH_TEAMCHANGE.m_id || frag_deathtype == DEATH_AUTOTEAMCHANGE.m_id)
        {
                // let the player die, he will be automatically frozen when he respawns
-               if(STAT(FROZEN, frag_target) != 1)
+               if (STAT(FROZEN, frag_target) != FROZEN_NORMAL)
                {
                        freezetag_Add_Score(frag_target, frag_attacker);
                        freezetag_count_alive_players();
                        freezetag_LastPlayerForTeam_Notify(frag_target);
                }
                else
-                       Unfreeze(frag_target); // remove ice
-               SetResourceAmountExplicit(frag_target, RESOURCE_HEALTH, 0); // Unfreeze resets health
+                       Unfreeze(frag_target, false); // remove ice
                frag_target.freezetag_frozen_timeout = -2; // freeze on respawn
                return true;
        }
 
-       if(STAT(FROZEN, frag_target))
+       if (STAT(FROZEN, frag_target) == FROZEN_NORMAL)
                return true;
 
        freezetag_Freeze(frag_target, frag_attacker);
@@ -451,10 +452,17 @@ MUTATOR_HOOKFUNCTION(ft, Unfreeze)
        entity targ = M_ARGV(0, entity);
        targ.freezetag_frozen_time = 0;
        targ.freezetag_frozen_timeout = 0;
-
-       freezetag_count_alive_players();
 }
 
+#ifdef IS_REVIVING
+       #undef IS_REVIVING
+#endif
+
+// returns true if player is reviving it
+#define IS_REVIVING(player, it, revive_extra_size) \
+       (it != player && !STAT(FROZEN, it) && !IS_DEAD(it) && SAME_TEAM(it, player) \
+       && boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
+
 MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
 {
        if(game_stopped)
@@ -465,42 +473,45 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
                return true;
 
        int n;
-       entity o = NULL;
        entity player = M_ARGV(0, entity);
-       //if(STAT(FROZEN, player))
+       //if (STAT(FROZEN, player) == FROZEN_NORMAL)
        //if(player.freezetag_frozen_timeout > 0 && time < player.freezetag_frozen_timeout)
                //player.iceblock.alpha = ICE_MIN_ALPHA + (ICE_MAX_ALPHA - ICE_MIN_ALPHA) * (player.freezetag_frozen_timeout - time) / (player.freezetag_frozen_timeout - player.freezetag_frozen_time);
 
+       IntrusiveList reviving_players = NULL;
+
        if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
                n = -1;
        else
        {
-               vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
                n = 0;
-               FOREACH_CLIENT(IS_PLAYER(it) && it != player, {
-                       if(STAT(FROZEN, it) == 0)
-                       if(!IS_DEAD(it))
-                       if(SAME_TEAM(it, player))
-                       if(boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
-                       {
-                               if(!o)
-                                       o = it;
-                               if(STAT(FROZEN, player) == 1)
-                                       it.reviving = true;
-                               ++n;
-                       }
+               vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
+               FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
+                       if (!reviving_players)
+                               reviving_players = IL_NEW();
+                       IL_PUSH(reviving_players, it);
+                       ++n;
                });
-
        }
 
-       if(n && STAT(FROZEN, player) == 1) // OK, there is at least one teammate reviving us
+       if (!n) // no teammate nearby
+       {
+               if (STAT(FROZEN, player) == FROZEN_NORMAL)
+               {
+                       STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) - frametime * autocvar_g_freezetag_revive_clearspeed, 1);
+                       SetResourceAmountExplicit(player, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * ((warmup_stage) ? warmup_start_health : start_health)));
+               }
+               else if (!STAT(FROZEN, player))
+                       STAT(REVIVE_PROGRESS, player) = 0; // thawing nobody
+       }
+       else if (STAT(FROZEN, player) == FROZEN_NORMAL) // OK, there is at least one teammate reviving us
        {
                STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
                SetResourceAmountExplicit(player, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * ((warmup_stage) ? warmup_start_health : start_health)));
 
                if(STAT(REVIVE_PROGRESS, player) >= 1)
                {
-                       Unfreeze(player);
+                       Unfreeze(player, false);
                        freezetag_count_alive_players();
 
                        if(n == -1)
@@ -511,32 +522,25 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
                        }
 
                        // EVERY team mate nearby gets a point (even if multiple!)
-                       FOREACH_CLIENT(IS_PLAYER(it) && it.reviving, {
+                       IL_EACH(reviving_players, true, {
                                GameRules_scoring_add(it, FREEZETAG_REVIVALS, +1);
                                GameRules_scoring_add(it, SCORE, +1);
-                               nades_GiveBonus(it,autocvar_g_nades_bonus_score_low);
+                               nades_GiveBonus(it, autocvar_g_nades_bonus_score_low);
                        });
 
-                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, o.netname);
-                       Send_Notification(NOTIF_ONE, o, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED, player.netname, o.netname);
+                       entity first = IL_FIRST(reviving_players);
+                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
+                       Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED, player.netname, first.netname);
                }
 
-               FOREACH_CLIENT(IS_PLAYER(it) && it.reviving, {
+               IL_EACH(reviving_players, true, {
                        STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
-                       it.reviving = false;
                });
        }
-       else if(!n && STAT(FROZEN, player) == 1) // only if no teammate is nearby will we reset
-       {
-               STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) - frametime * autocvar_g_freezetag_revive_clearspeed, 1);
-               SetResourceAmountExplicit(player, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * ((warmup_stage) ? warmup_start_health : start_health)));
-       }
-       else if(!n && !STAT(FROZEN, player))
-       {
-               STAT(REVIVE_PROGRESS, player) = 0; // thawing nobody
-       }
 
+       if (reviving_players)
+               IL_DELETE(reviving_players);
        return true;
 }
 
@@ -593,7 +597,7 @@ MUTATOR_HOOKFUNCTION(ft, FragCenterMessage)
        int kill_count_to_attacker = M_ARGV(3, int);
        int kill_count_to_target = M_ARGV(4, int);
 
-       if(STAT(FROZEN, frag_target))
+       if(STAT(FROZEN, frag_target) == FROZEN_NORMAL)
                return; // target was already frozen, so this is just pushing them off the cliff
 
        Send_Notification(NOTIF_ONE, frag_attacker, MSG_CHOICE, CHOICE_FRAG_FREEZE, frag_target.netname, kill_count_to_attacker, (IS_BOT_CLIENT(frag_target) ? -1 : CS(frag_target).ping));
index 4a3d80fd1b33605de50576c2d9f1becbf86e3bf8..d637ae46f6a52f934f2d806adc5c1cdb49334098 100644 (file)
@@ -27,8 +27,6 @@ const float ICE_MAX_ALPHA = 1;
 const float ICE_MIN_ALPHA = 0.1;
 float freezetag_teams;
 
-.float reviving; // temp var
-
 float autocvar_g_freezetag_revive_extra_size;
 float autocvar_g_freezetag_revive_speed;
 bool autocvar_g_freezetag_revive_nade;
index ffbecf1b3df6abcb68c558b4e1c9336713225328..493320ccebc695ac5e9a3b9276f8166e6587e844 100644 (file)
@@ -36,16 +36,16 @@ void ClearWinners();
 int WinningCondition_LMS()
 {
        entity first_player = NULL;
-       int total_players = 0;
+       int totalplayers = 0;
        FOREACH_CLIENT(IS_PLAYER(it), {
-               if (!total_players)
+               if (!totalplayers)
                        first_player = it;
-               ++total_players;
+               ++totalplayers;
        });
 
-       if (total_players)
+       if (totalplayers)
        {
-               if (total_players > 1)
+               if (totalplayers > 1)
                {
                        // two or more active players - continue with the game
 
index 89c53a82abc22eb1b7b4b8fc1a8784e8f5b6ea23..65c5bcd8a0189530b2baf7eeba38a2ebcacdc272 100644 (file)
@@ -7,7 +7,7 @@ REGISTER_MUTATOR(cl_nb, true);
 
 MUTATOR_HOOKFUNCTION(cl_nb, WantEventchase)
 {
-       if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
+       if(autocvar_cl_eventchase_nexball && ISGAMETYPE(NEXBALL) && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
                return true;
        return false;
 }
index 838d0dd7e9cf07e0be6fc7e4ebf894613e452f55..02b57b2ca879bac2ddc4f54fb70327902b7e5de3 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_weapon.qh"
 
-void W_Nexball_Attack(entity actor, .entity weaponentity, float t);
-void W_Nexball_Attack2(entity actor, .entity weaponentity);
+void W_Nexball_Attack(Weapon thiswep, entity actor, .entity weaponentity, float t);
+void W_Nexball_Attack2(Weapon thiswep, entity actor, .entity weaponentity);
 vector trigger_push_calculatevelocity(vector org, entity tgt, float ht, entity pushed_entity);
 
 METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, .entity weaponentity, int fire))
@@ -18,19 +18,19 @@ METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, .entity we
             }
             else
             {
-                W_Nexball_Attack(actor, weaponentity, -1);
+                W_Nexball_Attack(thiswep, actor, weaponentity, -1);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
             }
     if(fire & 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, autocvar_g_balance_nexball_secondary_refire))
         {
-            W_Nexball_Attack2(actor, weaponentity);
+            W_Nexball_Attack2(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
         }
 
     if(!(fire & 1) && STAT(NB_METERSTART, actor) && actor.ballcarried)
     {
-        W_Nexball_Attack(actor, weaponentity, time - STAT(NB_METERSTART, actor));
+        W_Nexball_Attack(thiswep, actor, weaponentity, time - STAT(NB_METERSTART, actor));
         // DropBall or stealing will set metertime back to 0
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
     }
@@ -105,7 +105,7 @@ void W_Nexball_Touch(entity this, entity toucher)
        delete(this);
 }
 
-void W_Nexball_Attack(entity actor, .entity weaponentity, float t)
+void W_Nexball_Attack(Weapon thiswep, entity actor, .entity weaponentity, float t)
 {
        entity ball;
        float mul, mi, ma;
@@ -141,7 +141,7 @@ void W_Nexball_Attack(entity actor, .entity weaponentity, float t)
        //TODO: use the speed_up cvar too ??
 }
 
-void W_Nexball_Attack2(entity actor, .entity weaponentity)
+void W_Nexball_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        if(actor.ballcarried.enemy)
        {
index 6d719eb977c512997131382e30a0698e0fcd14c0..b4c4dc68fed96fa6a6c32b7e47ca2cb0b3a7957f 100644 (file)
@@ -27,7 +27,6 @@ float autocvar_g_onslaught_teleport_radius;
 float autocvar_g_onslaught_spawn_choose;
 float autocvar_g_onslaught_click_radius;
 
-void FixSize(entity e);
 entity cam;
 
 // =======================
@@ -114,12 +113,6 @@ void ons_CaptureShield_Spawn(entity generator, bool is_generator)
 // Junk Pile
 // ==========
 
-void setmodel_fixsize(entity e, Model m)
-{
-       setmodel(e, m);
-       FixSize(e);
-}
-
 void onslaught_updatelinks()
 {
        entity l;
@@ -438,7 +431,7 @@ void ons_ControlPoint_Icon_Damage(entity this, entity inflictor, entity attacker
 
                this.owner.waslinked = this.owner.islinked;
                if(this.owner.model != "models/onslaught/controlpoint_pad.md3")
-                       setmodel_fixsize(this.owner, MDL_ONS_CP_PAD1);
+                       setmodel(this.owner, MDL_ONS_CP_PAD1);
                //setsize(this, '-32 -32 0', '32 32 8');
 
                delete(this);
@@ -578,7 +571,7 @@ void ons_ControlPoint_Icon_BuildThink(entity this)
                this.SendFlags |= CPSF_SETUP;
        }
        if(this.owner.model != MDL_ONS_CP_PAD2.model_str())
-               setmodel_fixsize(this.owner, MDL_ONS_CP_PAD2);
+               setmodel(this.owner, MDL_ONS_CP_PAD2);
 
        if(random() < 0.9 - GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health)
                Send_Effect(EFFECT_RAGE, this.origin + 10 * randomvec(), '0 0 -1', 1);
@@ -737,7 +730,7 @@ void ons_ControlPoint_Reset(entity this)
        setthink(this, ons_ControlPoint_Think);
        this.ons_toucher = NULL;
        this.nextthink = time + ONS_CP_THINKRATE;
-       setmodel_fixsize(this, MDL_ONS_CP_PAD1);
+       setmodel(this, MDL_ONS_CP_PAD1);
 
        WaypointSprite_UpdateMaxHealth(this.sprite, 0);
        WaypointSprite_UpdateRule(this.sprite,this.team,SPRITERULE_TEAMPLAY);
@@ -781,7 +774,7 @@ void ons_ControlPoint_Setup(entity cp)
        if(cp.message == "") { cp.message = "a"; }
 
        // appearence
-       setmodel_fixsize(cp, MDL_ONS_CP_PAD1);
+       setmodel(cp, MDL_ONS_CP_PAD1);
 
        // control point placement
        if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
index ca1b6f8e74649e80c2b1ebe8c180871c00cef75e..f8950684b4967eabaa9990de93a7e53746d8f0cc 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 // TODO: find a better location for these?
-float total_players;
+int total_players;
 
 // todo: accept the number of teams as a parameter
 void GameRules_teams(bool value);
index 9075c0912ed2a5044ba8e7b80b299a05723f31ba..ba824f40b41c14c470a214c33eeb0bd6e9064c4d 100644 (file)
@@ -107,7 +107,7 @@ bool Inventory_Send(Inventory this, Client to, int sf)
     TC(Inventory, this);
     WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
     entity e = this.owner;
-    if (IS_SPEC(e)) e = e.enemy;
+    if (IS_SPEC(e)) e = PS(e.enemy); // TODO: how can this *ever* be the case?
     TC(Player, e);
     Inventory data = e.inventory;
     Inventory_Write(data);
@@ -118,7 +118,7 @@ void Inventory_new(entity e)
 {
     Inventory inv = NEW(Inventory), bak = NEW(Inventory);
     inv.inventory = bak;
-    inv.drawonlytoclient = e;
+    inv.drawonlytoclient = IS_CLIENT(e) ? e : e.m_client;
     Net_LinkEntity((inv.owner = e).inventory = inv, false, 0, Inventory_Send);
 }
 void Inventory_delete(entity e) { delete(e.inventory.inventory); delete(e.inventory); }
index b5944fc0a3def7d7235f09bfc66e6ad33f2fb11e..a3c2d779edcde089ac3d4f7e142693de8e47070b 100644 (file)
@@ -11,9 +11,10 @@ METHOD(Pickup, giveTo, bool(Pickup this, entity item, entity player))
     TC(Pickup, this);
     bool b = Item_GiveTo(item, player);
     if (b) {
-        LOG_DEBUGF("entity %i picked up %s", player, this.m_name);
-        player.inventory.inv_items[this.m_id]++;
-        Inventory_update(player);
+        //LOG_DEBUGF("entity %i picked up %s", player, this.m_name);
+        entity store = IS_PLAYER(player) ? PS(player) : player;
+        store.inventory.inv_items[this.m_id]++;
+        Inventory_update(store);
     }
     return b;
 }
index 71b5335d753c3ff77dceae382b5e3e0adf738086..62e03d21b6fe8ed4fe375ea60d845636bcc420d7 100644 (file)
@@ -424,27 +424,7 @@ void _MapInfo_Map_Reset()
 
 string _MapInfo_GetDefault(Gametype t)
 {
-       switch(t)
-       {
-               case MAPINFO_TYPE_DEATHMATCH:      return "30 20 0";
-               case MAPINFO_TYPE_TEAM_DEATHMATCH: return "50 20 2 0";
-               case MAPINFO_TYPE_DOMINATION:      return "200 20 0";
-               case MAPINFO_TYPE_CTF:             return "300 20 10 0";
-               case MAPINFO_TYPE_LMS:             return "9 20 0";
-               case MAPINFO_TYPE_CA:              return "10 20 0";
-               case MAPINFO_TYPE_KEYHUNT:         return "1000 20 3 0";
-               case MAPINFO_TYPE_ASSAULT:         return "20 0";
-               case MAPINFO_TYPE_RACE:            return "20 5 7 15 0";
-               case MAPINFO_TYPE_ONSLAUGHT:       return "20 0";
-               case MAPINFO_TYPE_NEXBALL:         return "5 20 0";
-               case MAPINFO_TYPE_CTS:             return "20 0 0";
-               case MAPINFO_TYPE_FREEZETAG:       return "10 20 0";
-               // NOTE: DO NOT ADD ANY MORE GAME TYPES HERE
-               // THIS IS JUST LEGACY SUPPORT FOR NEXUIZ MAPS
-               // ONLY ADD NEW STUFF TO _MapInfo_GetDefaultEx
-               // THIS FUNCTION WILL EVENTUALLY BE REMOVED
-               default:                           return "";
-       }
+       return t.m_legacydefaults;
 }
 
 void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisType, int load_default)
@@ -457,7 +437,7 @@ void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisTy
        if(load_default)
                _MapInfo_Map_ApplyGametype(_MapInfo_GetDefault(pThisType), pWantedType, pThisType, false);
 
-       if(pWantedType == MAPINFO_TYPE_ASSAULT || pWantedType == MAPINFO_TYPE_ONSLAUGHT || pWantedType == MAPINFO_TYPE_RACE || pWantedType == MAPINFO_TYPE_CTS) // these modes don't use fraglimit
+       if(!pWantedType.frags) // these modes don't use fraglimit
        {
                cvar_set("fraglimit", "0");
        }
@@ -485,6 +465,8 @@ void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisTy
        // rc = timelimit timelimit_qualification laps laps_teamplay
        if(pWantedType == MAPINFO_TYPE_RACE)
        {
+               cvar_set("fraglimit", "0"); // special case!
+
                sa = car(s); if(sa == "") sa = cvar_string("timelimit");
                cvar_set("g_race_qualifying_timelimit", sa);
                s = cdr(s);
@@ -502,7 +484,7 @@ void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisTy
                s = cdr(s);
        }
 
-       if(pWantedType == MAPINFO_TYPE_ASSAULT || pWantedType == MAPINFO_TYPE_ONSLAUGHT || pWantedType == MAPINFO_TYPE_CTS) // these modes don't use fraglimit
+       if(!pWantedType.frags) // these modes don't use fraglimit
        {
                cvar_set("leadlimit", "0");
        }
@@ -855,6 +837,9 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                        if(fexists(strcat("scripts/", pFilename, ".arena")))
                                fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n");
 
+                       if(fexists(strcat("scripts/", pFilename, ".defi")))
+                               fputs(fh, "settemp_for_type all sv_vq3compat 1\n");
+
                        fputs(fh, "// optional: fog density red green blue alpha mindist maxdist\n");
                        fputs(fh, "// optional: settemp_for_type (all|gametypename) cvarname value\n");
                        fputs(fh, "// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
@@ -1065,13 +1050,7 @@ int MapInfo_Get_ByName(string pFilename, float pAllowGenerate, Gametype pGametyp
 {
        int r = MapInfo_Get_ByName_NoFallbacks(pFilename, pAllowGenerate, pGametypeToSet);
 
-       if(cvar("g_tdm_on_dm_maps"))
-       {
-               // if this is set, all DM maps support TDM too
-               if (!(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH.m_flags))
-                       if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)
-                               _MapInfo_Map_ApplyGametypeEx ("", pGametypeToSet, MAPINFO_TYPE_TEAM_DEATHMATCH);
-       }
+       FOREACH(Gametypes, it.m_isForcedSupported(it), _MapInfo_Map_ApplyGametypeEx("", pGametypeToSet, it));
 
        if(pGametypeToSet)
        {
index 4addd24001f6d32a594424a2761855c222f3b300..6fbb7ce896235d53fe240be81fd83ea0aea25002 100644 (file)
@@ -31,6 +31,8 @@ CLASS(Gametype, Object)
     ATTRIB(Gametype, message, string);
     /** does this gametype support teamplay? */
     ATTRIB(Gametype, team, bool, false);
+    /** does this gametype use a point limit? */
+    ATTRIB(Gametype, frags, bool, true);
     /** game type defaults */
     ATTRIB(Gametype, model2, string);
     /** game type description */
@@ -40,6 +42,9 @@ CLASS(Gametype, Object)
     ATTRIB(Gametype, m_modicons_reset, void());
 #endif
 
+    /** DO NOT USE, this is compatibility for legacy maps! */
+    ATTRIB(Gametype, m_legacydefaults, string, "");
+
     ATTRIB(Gametype, m_mutators, string);
     METHOD(Gametype, m_parse_mapinfo, bool(string k, string v))
     {
@@ -57,6 +62,15 @@ CLASS(Gametype, Object)
     {
         return false;
     }
+    METHOD(Gametype, m_isForcedSupported, bool(Gametype this))
+    {
+        return false;
+    }
+    METHOD(Gametype, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        string_null,                    _("The amount of frags needed before the match will end"));
+    }
 
     METHOD(Gametype, describe, string(Gametype this))
     {
@@ -70,7 +84,7 @@ CLASS(Gametype, Object)
         returns(this.message, strcat("gametype_", this.mdl));
     }
 
-    METHOD(Gametype, gametype_init, void(Gametype this, string hname, string sname, string g_name, bool gteamplay, string mutators, string defaults, string gdescription))
+    METHOD(Gametype, gametype_init, void(Gametype this, string hname, string sname, string g_name, bool gteamplay, bool gusepoints, string mutators, string defaults, string gdescription))
     {
         this.netname = g_name;
         this.mdl = sname;
@@ -79,6 +93,7 @@ CLASS(Gametype, Object)
         this.m_mutators = cons(sname, mutators);
         this.model2 = defaults;
         this.gametype_description = gdescription;
+        this.frags = gusepoints;
 
         // same as `1 << m_id`
         MAPINFO_TYPE_ALL |= this.items = this.m_flags = (MAPINFO_TYPE_ALL + 1);
@@ -96,24 +111,31 @@ REGISTRY_CHECK(Gametypes)
 CLASS(Deathmatch, Gametype)
     INIT(Deathmatch)
     {
-        this.gametype_init(this, _("Deathmatch"),"dm","g_dm",false,"","timelimit=15 pointlimit=30 leadlimit=0",_("Score as many frags as you can"));
+        this.gametype_init(this, _("Deathmatch"),"dm","g_dm",false,true,"","timelimit=15 pointlimit=30 leadlimit=0",_("Score as many frags as you can"));
     }
     METHOD(Deathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
     {
         return true;
     }
+    ATTRIB(Deathmatch, m_legacydefaults, string, "30 20 0");
 ENDCLASS(Deathmatch)
 REGISTER_GAMETYPE(DEATHMATCH, NEW(Deathmatch));
 
 CLASS(LastManStanding, Gametype)
     INIT(LastManStanding)
     {
-        this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",false,"","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=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
     }
     METHOD(LastManStanding, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
     {
         return true;
     }
+    METHOD(LastManStanding, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Lives:"),           3,   50,  1, "g_lms_lives_override",      string_null,                    string_null);
+    }
+    ATTRIB(LastManStanding, m_legacydefaults, string, "9 20 0");
 ENDCLASS(LastManStanding)
 REGISTER_GAMETYPE(LMS, NEW(LastManStanding));
 
@@ -123,7 +145,7 @@ void HUD_Mod_Race(vector pos, vector mySize);
 CLASS(Race, Gametype)
     INIT(Race)
     {
-        this.gametype_init(this, _("Race"),"rc","g_race",false,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
+        this.gametype_init(this, _("Race"),"rc","g_race",false,true,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
     }
     METHOD(Race, m_parse_mapinfo, bool(string k, string v))
     {
@@ -147,9 +169,15 @@ CLASS(Race, Gametype)
     {
         return true;
     }
+    METHOD(Race, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Laps:"),            1,   25,  1, "g_race_laps_limit",         string_null,                    string_null);
+    }
 #ifdef CSQC
     ATTRIB(Race, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race);
 #endif
+    ATTRIB(Race, m_legacydefaults, string, "20 5 7 15 0");
 ENDCLASS(Race)
 REGISTER_GAMETYPE(RACE, NEW(Race));
 #define g_race IS_GAMETYPE(RACE)
@@ -157,7 +185,7 @@ REGISTER_GAMETYPE(RACE, NEW(Race));
 CLASS(RaceCTS, Gametype)
     INIT(RaceCTS)
     {
-        this.gametype_init(this, _("Race CTS"),"cts","g_cts",false,"cloaked","timelimit=20",_("Race for fastest time."));
+        this.gametype_init(this, _("Race CTS"),"cts","g_cts",false,false,"cloaked","timelimit=20",_("Race for fastest time."));
     }
     METHOD(RaceCTS, m_generate_mapinfo, void(Gametype this, string v))
     {
@@ -171,9 +199,15 @@ CLASS(RaceCTS, Gametype)
         // for map databases
         //  cvar_set("fraglimit", sa);
     }
+    METHOD(RaceCTS, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null);
+    }
 #ifdef CSQC
     ATTRIB(RaceCTS, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race);
 #endif
+    ATTRIB(RaceCTS, m_legacydefaults, string, "20 0 0");
 ENDCLASS(RaceCTS)
 REGISTER_GAMETYPE(CTS, NEW(RaceCTS));
 #define g_cts IS_GAMETYPE(CTS)
@@ -181,7 +215,7 @@ REGISTER_GAMETYPE(CTS, NEW(RaceCTS));
 CLASS(TeamDeathmatch, Gametype)
     INIT(TeamDeathmatch)
     {
-        this.gametype_init(this, _("Team Deathmatch"),"tdm","g_tdm",true,"","timelimit=15 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team"));
+        this.gametype_init(this, _("Team Deathmatch"),"tdm","g_tdm",true,true,"","timelimit=15 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team"));
     }
     METHOD(TeamDeathmatch, m_parse_mapinfo, bool(string k, string v))
     {
@@ -202,10 +236,26 @@ CLASS(TeamDeathmatch, Gametype)
             return true;
         return false;
     }
+    METHOD(TeamDeathmatch, m_isForcedSupported, bool(Gametype this))
+    {
+        if(cvar("g_tdm_on_dm_maps"))
+        {
+            // if this is set, all DM maps support TDM too
+            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;
+    }
     METHOD(TeamDeathmatch, m_setTeams, void(string sa))
     {
         cvar_set("g_tdm_teams", sa);
     }
+    METHOD(TeamDeathmatch, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),     5,  100,  5, "g_tdm_point_limit",         "g_tdm_teams_override",         _("The amount of points needed before the match will end"));
+    }
+    ATTRIB(TeamDeathmatch, m_legacydefaults, string, "50 20 2 0");
 ENDCLASS(TeamDeathmatch)
 REGISTER_GAMETYPE(TEAM_DEATHMATCH, NEW(TeamDeathmatch));
 #define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
@@ -217,7 +267,7 @@ void HUD_Mod_CTF_Reset();
 CLASS(CaptureTheFlag, Gametype)
     INIT(CaptureTheFlag)
     {
-        this.gametype_init(this, _("Capture the Flag"),"ctf","g_ctf",true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team"));
+        this.gametype_init(this, _("Capture the Flag"),"ctf","g_ctf",true,true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team"));
     }
     METHOD(CaptureTheFlag, m_generate_mapinfo, void(Gametype this, string v))
     {
@@ -232,10 +282,16 @@ CLASS(CaptureTheFlag, Gametype)
     {
         cvar_set("fraglimit", sa);
     }
+    METHOD(CaptureTheFlag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Capture limit:"),   1,   20,  1, "capturelimit_override",     string_null,                    _("The amount of captures needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(CaptureTheFlag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CTF);
     ATTRIB(CaptureTheFlag, m_modicons_reset, void(), HUD_Mod_CTF_Reset);
 #endif
+    ATTRIB(CaptureTheFlag, m_legacydefaults, string, "300 20 10 0");
 ENDCLASS(CaptureTheFlag)
 REGISTER_GAMETYPE(CTF, NEW(CaptureTheFlag));
 #define g_ctf IS_GAMETYPE(CTF)
@@ -246,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,"","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=0",_("Kill all enemy teammates to win the round"));
     }
     METHOD(ClanArena, m_parse_mapinfo, bool(string k, string v))
     {
@@ -271,9 +327,15 @@ CLASS(ClanArena, Gametype)
     {
         cvar_set("g_ca_teams", sa);
     }
+    METHOD(ClanArena, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_ca_teams_override",          _("The amount of frags needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
 #endif
+    ATTRIB(ClanArena, m_legacydefaults, string, "10 20 0");
 ENDCLASS(ClanArena)
 REGISTER_GAMETYPE(CA, NEW(ClanArena));
 #define g_ca IS_GAMETYPE(CA)
@@ -284,7 +346,7 @@ void HUD_Mod_Dom(vector pos, vector mySize);
 CLASS(Domination, Gametype)
     INIT(Domination)
     {
-        this.gametype_init(this, _("Domination"),"dom","g_domination",true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win"));
+        this.gametype_init(this, _("Domination"),"dom","g_domination",true,true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win"));
     }
     METHOD(Domination, m_parse_mapinfo, bool(string k, string v))
     {
@@ -304,9 +366,15 @@ CLASS(Domination, Gametype)
         if(v == "dom_controlpoint")
             MapInfo_Map_supportedGametypes |= this.m_flags;
     }
+    METHOD(Domination, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),    50,  500, 10, "g_domination_point_limit",  "g_domination_teams_override",  _("The amount of points needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(Domination, m_modicons, void(vector pos, vector mySize), HUD_Mod_Dom);
 #endif
+    ATTRIB(Domination, m_legacydefaults, string, "200 20 0");
 ENDCLASS(Domination)
 REGISTER_GAMETYPE(DOMINATION, NEW(Domination));
 
@@ -316,7 +384,7 @@ void HUD_Mod_KH(vector pos, vector mySize);
 CLASS(KeyHunt, Gametype)
     INIT(KeyHunt)
     {
-        this.gametype_init(this, _("Key Hunt"),"kh","g_keyhunt",true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
+        this.gametype_init(this, _("Key Hunt"),"kh","g_keyhunt",true,true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
     }
     METHOD(KeyHunt, m_parse_mapinfo, bool(string k, string v))
     {
@@ -341,16 +409,22 @@ CLASS(KeyHunt, Gametype)
     {
         cvar_set("g_keyhunt_teams", sa);
     }
+    METHOD(KeyHunt, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),   200, 1500, 50, "g_keyhunt_point_limit",     "g_keyhunt_teams_override",     _("The amount of points needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(KeyHunt, m_modicons, void(vector pos, vector mySize), HUD_Mod_KH);
 #endif
+    ATTRIB(KeyHunt, m_legacydefaults, string, "1000 20 3 0");
 ENDCLASS(KeyHunt)
 REGISTER_GAMETYPE(KEYHUNT, NEW(KeyHunt));
 
 CLASS(Assault, Gametype)
     INIT(Assault)
     {
-        this.gametype_init(this, _("Assault"),"as","g_assault",true,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
+        this.gametype_init(this, _("Assault"),"as","g_assault",true,false,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
     }
     METHOD(Assault, m_generate_mapinfo, void(Gametype this, string v))
     {
@@ -361,6 +435,12 @@ CLASS(Assault, Gametype)
     {
         return true;
     }
+    METHOD(Assault, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null);
+    }
+    ATTRIB(Assault, m_legacydefaults, string, "20 0");
 ENDCLASS(Assault)
 REGISTER_GAMETYPE(ASSAULT, NEW(Assault));
 #define g_assault IS_GAMETYPE(ASSAULT)
@@ -368,13 +448,19 @@ REGISTER_GAMETYPE(ASSAULT, NEW(Assault));
 CLASS(Onslaught, Gametype)
     INIT(Onslaught)
     {
-        this.gametype_init(this, _("Onslaught"),"ons","g_onslaught",true,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
+        this.gametype_init(this, _("Onslaught"),"ons","g_onslaught",true,false,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
     }
     METHOD(Onslaught, m_generate_mapinfo, void(Gametype this, string v))
     {
         if(v == "onslaught_generator")
             MapInfo_Map_supportedGametypes |= this.m_flags;
     }
+    METHOD(Onslaught, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null);
+    }
+    ATTRIB(Onslaught, m_legacydefaults, string, "20 0");
 ENDCLASS(Onslaught)
 REGISTER_GAMETYPE(ONSLAUGHT, NEW(Onslaught));
 
@@ -384,7 +470,7 @@ void HUD_Mod_NexBall(vector pos, vector mySize);
 CLASS(NexBall, Gametype)
     INIT(NexBall)
     {
-        this.gametype_init(this, _("Nexball"),"nb","g_nexball",true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean"));
+        this.gametype_init(this, _("Nexball"),"nb","g_nexball",true,true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean"));
     }
     METHOD(NexBall, m_generate_mapinfo, void(Gametype this, string v))
     {
@@ -395,9 +481,15 @@ CLASS(NexBall, Gametype)
     {
         return true;
     }
+    METHOD(NexBall, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Goals:"),           1,   50,  1, "g_nexball_goallimit",       string_null,                    _("The amount of goals needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(NexBall, m_modicons, void(vector pos, vector mySize), HUD_Mod_NexBall);
 #endif
+    ATTRIB(NexBall, m_legacydefaults, string, "5 20 0");
 ENDCLASS(NexBall)
 REGISTER_GAMETYPE(NEXBALL, NEW(NexBall));
 #define g_nexball IS_GAMETYPE(NEXBALL)
@@ -405,7 +497,7 @@ REGISTER_GAMETYPE(NEXBALL, NEW(NexBall));
 CLASS(FreezeTag, Gametype)
     INIT(FreezeTag)
     {
-        this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",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=0",_("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))
     {
@@ -430,9 +522,15 @@ CLASS(FreezeTag, Gametype)
     {
         cvar_set("g_freezetag_teams", sa);
     }
+    METHOD(FreezeTag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_freezetag_teams_override",   _("The amount of frags needed before the match will end"));
+    }
 #ifdef CSQC
     ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
 #endif
+    ATTRIB(FreezeTag, m_legacydefaults, string, "10 20 0");
 ENDCLASS(FreezeTag)
 REGISTER_GAMETYPE(FREEZETAG, NEW(FreezeTag));
 #define g_freezetag IS_GAMETYPE(FREEZETAG)
@@ -443,7 +541,7 @@ void HUD_Mod_Keepaway(vector pos, vector mySize);
 CLASS(Keepaway, Gametype)
     INIT(Keepaway)
     {
-        this.gametype_init(this, _("Keepaway"),"ka","g_keepaway",false,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
+        this.gametype_init(this, _("Keepaway"),"ka","g_keepaway",false,true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
     }
     METHOD(Keepaway, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
     {
@@ -458,7 +556,7 @@ REGISTER_GAMETYPE(KEEPAWAY, NEW(Keepaway));
 CLASS(Invasion, Gametype)
     INIT(Invasion)
     {
-        this.gametype_init(this, _("Invasion"),"inv","g_invasion",false,"","pointlimit=50 teams=0 type=0",_("Survive against waves of monsters"));
+        this.gametype_init(this, _("Invasion"),"inv","g_invasion",false,true,"","pointlimit=50 teams=0 type=0",_("Survive against waves of monsters"));
     }
     METHOD(Invasion, m_parse_mapinfo, bool(string k, string v))
     {
@@ -477,9 +575,35 @@ CLASS(Invasion, Gametype)
         if(v == "invasion_spawnpoint")
             MapInfo_Map_supportedGametypes |= this.m_flags;
     }
+    METHOD(Invasion, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns))
+    {
+        TC(Gametype, this);
+        returns(menu, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null);
+    }
 ENDCLASS(Invasion)
 REGISTER_GAMETYPE(INVASION, NEW(Invasion));
 
+CLASS(Duel, Gametype)
+    INIT(Duel)
+    {
+        this.gametype_init(this, _("Duel"),"duel","g_duel",false,true,"","timelimit=10 pointlimit=0 leadlimit=0",_("Fight in a one versus one arena battle to decide the winner"));
+    }
+    METHOD(Duel, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        return (diameter < 16384);
+    }
+    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;
+        return false;
+    }
+ENDCLASS(Duel)
+REGISTER_GAMETYPE(DUEL, NEW(Duel));
+#define g_duel IS_GAMETYPE(DUEL)
+
 const int MAPINFO_FEATURE_WEAPONS       = 1; // not defined for instagib-only maps
 const int MAPINFO_FEATURE_VEHICLES      = 2;
 const int MAPINFO_FEATURE_TURRETS       = 4;
@@ -550,4 +674,4 @@ void MapInfo_ClearTemps(); // call this when done with mapinfo for this frame
 void MapInfo_Shutdown(); // call this in the shutdown handler
 
 #define MAPINFO_SETTEMP_ACL_USER cvar_string("g_mapinfo_settemp_acl")
-#define MAPINFO_SETTEMP_ACL_SYSTEM "-g_mapinfo_* -rcon_* -_* -g_ban* +*"
+#define MAPINFO_SETTEMP_ACL_SYSTEM "-g_mapinfo_* -rcon_* -_* -g_ban* -r_water +*"
index b647e15a826e48164f03db46c5f62114a8e6afc6..60920fafb8c5c95599af7b2090570bfc30ae84d6 100644 (file)
@@ -48,6 +48,8 @@ spawnfunc(func_bobbing)
 
        this.active = ACTIVE_ACTIVE;
 
+       this.draggable = drag_undraggable;
+
        // damage when blocked
        setblocked(this, generic_plat_blocked);
        if(this.dmg && (this.message == ""))
index 44e31284336aae99eb35f580dff390b5db98797b..024d5cfd873cfb37d288785876d4e4c0684a681f 100644 (file)
@@ -5,6 +5,43 @@
 void button_wait(entity this);
 void button_return(entity this);
 
+// in case button is deactivated by a relay_deactivate while it pressed down
+// set both fields to -1 in button_return!!
+.float wait_remaining;
+.float activation_time;
+
+void button_setactive(entity this, int astate)
+{
+       int oldstate = this.active;
+       if (astate == ACTIVE_TOGGLE)
+       {
+               if (this.active == ACTIVE_ACTIVE)
+                       this.active = ACTIVE_NOT;
+               else
+                       this.active = ACTIVE_ACTIVE;
+       }
+       else
+               this.active = astate;
+
+       if (this.active == ACTIVE_ACTIVE && oldstate == ACTIVE_NOT)
+       {
+               // button was deactivated while it was pressed
+               if (this.wait_remaining >= 0)
+               {
+                       this.nextthink =  this.wait_remaining + this.ltime;
+                       setthink(this, button_return);
+               }
+       }
+       else if (this.active == ACTIVE_NOT && oldstate == ACTIVE_ACTIVE)
+       {
+               // check if button is in pressed state
+               if (this.activation_time >= 0)
+               {
+                       this.wait_remaining = this.wait - (time - this.activation_time);
+               }
+       }
+}
+
 void button_wait(entity this)
 {
        this.state = STATE_TOP;
@@ -24,11 +61,17 @@ void button_done(entity this)
 
 void button_return(entity this)
 {
+       if (this.active != ACTIVE_ACTIVE)
+       {
+               return;
+       }
        this.state = STATE_DOWN;
        SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, button_done);
        this.frame = 0;                 // use normal textures
        if (GetResourceAmount(this, RESOURCE_HEALTH))
                this.takedamage = DAMAGE_YES;   // can be shot again
+       this.wait_remaining = -1;
+       this.activation_time = -1;
 }
 
 
@@ -46,6 +89,8 @@ void button_fire(entity this)
        if (this.state == STATE_UP || this.state == STATE_TOP)
                return;
 
+       this.activation_time = time;
+
        if (this.noise != "")
                _sound (this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
 
@@ -60,6 +105,9 @@ void button_reset(entity this)
        this.frame = 0;                 // use normal textures
        this.state = STATE_BOTTOM;
        this.velocity = '0 0 0';
+       this.wait_remaining = -1;
+       this.activation_time = -1;
+       this.active = ACTIVE_ACTIVE;
        setthink(this, func_null);
        this.nextthink = 0;
        if (GetResourceAmount(this, RESOURCE_HEALTH))
@@ -77,6 +125,8 @@ void button_use(entity this, entity actor, entity trigger)
 
 void button_touch(entity this, entity toucher)
 {
+       if (this.active != ACTIVE_ACTIVE)
+               return;
        if (!toucher)
                return;
        if (!toucher.iscreature)
@@ -91,6 +141,8 @@ void button_touch(entity this, entity toucher)
 
 void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
+       if (this.active != ACTIVE_ACTIVE)
+               return;
        if(this.spawnflags & NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
@@ -157,7 +209,9 @@ spawnfunc(func_button)
     if(this.noise != "")
         precache_sound(this.noise);
 
-       this.active = ACTIVE_ACTIVE;
+       this.draggable = drag_undraggable;
+
+       this.setactive = button_setactive;
 
        this.pos1 = this.origin;
        this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
index 9ad326cfa225f7ef9b0c08151e96f4feeacdff39..4c40598d35339676829c7f1de7f69a92de7f5545 100644 (file)
@@ -106,8 +106,6 @@ void conveyor_init(entity this)
        this.reset = generic_netlinked_reset;
        this.reset(this);
 
-       FixSize(this);
-
        Net_LinkEntity(this, 0, false, conveyor_send);
 
        this.SendFlags |= SF_TRIGGER_INIT;
index 8d40a377be081fbc583f3adef2486a129530d694..1ba7bad3aa633a12556f1476ad5f5efb78eb471b 100644 (file)
@@ -277,7 +277,7 @@ void door_damage(entity this, entity inflictor, entity attacker, float damage, i
        {
                SetResourceAmountExplicit(this.owner, RESOURCE_HEALTH, this.owner.max_health);
                this.owner.takedamage = DAMAGE_NO;      // will be reset upon return
-               door_use(this.owner, NULL, NULL);
+               door_use(this.owner, attacker, NULL);
        }
 }
 
@@ -595,8 +595,6 @@ float door_send(entity this, entity to, float sf)
 
 void door_link()
 {
-       // set size now, as everything is loaded
-       //FixSize(this);
        //Net_LinkEntity(this, false, 0, door_send);
 }
 #endif
@@ -715,9 +713,6 @@ spawnfunc(func_door)
        setblocked(this, door_blocked);
        this.use = door_use;
 
-       this.pos1 = this.origin;
-       this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
-
        if(this.spawnflags & DOOR_NONSOLID)
                this.solid = SOLID_NOT;
 
@@ -728,6 +723,9 @@ spawnfunc(func_door)
 
        door_init_shared(this);
 
+       this.pos1 = this.origin;
+       this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
+
        if (!this.speed)
        {
                this.speed = 100;
index b052336217990a32a646d852679bc3c0d1d83c20..53dbed02fa42a50580b69efe7ef80143ba0b0f5e 100644 (file)
@@ -103,6 +103,7 @@ spawnfunc(func_plat)
        this.angles = '0 0 0';
 
        this.classname = "plat";
+       this.draggable = drag_undraggable;
        if (!InitMovingBrushTrigger(this))
                return;
        this.effects |= EF_LOWPRECISION;
index 498f6c521e941c861d7049855699324bfd502666..c7f1619ad54faba790ac59e5533974e7d1e7a495 100644 (file)
@@ -2,5 +2,6 @@
 #include <common/mapobjects/misc/corner.qc>
 #include <common/mapobjects/misc/dynlight.qc>
 #include <common/mapobjects/misc/follow.qc>
+#include <common/mapobjects/misc/keys.qc>
 #include <common/mapobjects/misc/laser.qc>
 #include <common/mapobjects/misc/teleport_dest.qc>
index 3415919f8993799be9acc23fdb1c16a54a6508ef..617db807b9c1f3d68e6e1209bcff3e7dc0afcd17 100644 (file)
@@ -2,5 +2,6 @@
 #include <common/mapobjects/misc/corner.qh>
 #include <common/mapobjects/misc/dynlight.qh>
 #include <common/mapobjects/misc/follow.qh>
+#include <common/mapobjects/misc/keys.qh>
 #include <common/mapobjects/misc/laser.qh>
 #include <common/mapobjects/misc/teleport_dest.qh>
diff --git a/qcsrc/common/mapobjects/misc/keys.qc b/qcsrc/common/mapobjects/misc/keys.qc
new file mode 100644 (file)
index 0000000..2c85742
--- /dev/null
@@ -0,0 +1,292 @@
+#include "keys.qh"
+
+#ifdef CSQC
+bool item_keys_usekey(entity l, entity p)
+{
+       int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything!
+       l.itemkeys &= ~valid; // only some of the needed keys were given
+       return valid != 0;
+}
+#endif
+
+#ifdef SVQC
+/*
+TODO:
+- add an unlock sound (here to trigger_keylock and to func_door)
+- display available keys on the HUD
+- make more tests
+- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
+- should keys have a trigger?
+*/
+
+bool item_keys_usekey(entity l, entity p)
+{
+       int valid = l.itemkeys & p.itemkeys;
+
+       if (!valid) {
+               // player has none of the needed keys
+               return false;
+       } else if (l.itemkeys == valid) {
+               // ALL needed keys were given
+               l.itemkeys = 0;
+               return true;
+       } else {
+               // only some of the needed keys were given
+               l.itemkeys &= ~valid;
+               return true;
+       }
+}
+
+string item_keys_keylist(float keylist) {
+       // no keys
+       if (!keylist)
+               return "";
+
+       // one key
+       if ((keylist & (keylist-1)) == 0)
+               return strcat("the ", item_keys_names[lowestbit(keylist)]);
+
+       string n = "";
+       int base = 0;
+       while (keylist) {
+               int l = lowestbit(keylist);
+               if (n)
+                       n = strcat(n, ", the ", item_keys_names[base + l]);
+               else
+                       n = strcat("the ", item_keys_names[base + l]);
+
+               keylist = bitshift(keylist,  -(l + 1));
+               base+= l + 1;
+       }
+
+       return n;
+}
+
+
+/*
+================================
+item_key
+================================
+*/
+
+/**
+ * Key touch handler.
+ */
+void item_key_touch(entity this, entity toucher)
+{
+       if (!IS_PLAYER(toucher))
+               return;
+
+       // player already picked up this key
+       if (PS(toucher).itemkeys & this.itemkeys)
+               return;
+
+       PS(toucher).itemkeys |= this.itemkeys;
+       play2(toucher, this.noise);
+
+       centerprint(toucher, this.message);
+
+       string oldmsg = this.message;
+       this.message = "";
+       SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here?
+       this.message = oldmsg;
+}
+
+/**
+ * Spawn a key with given model, key code and color.
+ */
+void spawn_item_key(entity this)
+{
+       precache_model(this.model);
+
+       if (this.spawnflags & 1) // FLOATING
+               this.noalign = 1;
+
+       if (this.noalign)
+               set_movetype(this, MOVETYPE_NONE);
+       else
+               set_movetype(this, MOVETYPE_TOSS);
+
+       precache_sound(this.noise);
+
+       this.mdl = this.model;
+       this.effects = EF_LOWPRECISION;
+       _setmodel(this, this.model);
+       //setsize(this, '-16 -16 -24', '16 16 32');
+       setorigin(this, this.origin + '0 0 32');
+       setsize(this, '-16 -16 -56', '16 16 0');
+       this.modelflags |= MF_ROTATE;
+       this.solid = SOLID_TRIGGER;
+
+       if (!this.noalign)
+       {
+               // first nudge it off the floor a little bit to avoid math errors
+               setorigin(this, this.origin + '0 0 1');
+               // note droptofloor returns false if stuck/or would fall too far
+               droptofloor(this);
+       }
+
+       settouch(this, item_key_touch);
+}
+
+
+/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+A key entity.
+The itemkeys should contain one of the following key IDs:
+1 - GOLD key -
+2 - SILVER key
+4 - BRONZE key
+8 - RED keycard
+16 - BLUE keycard
+32 - GREEN keycard
+Custom keys:
+... - last key is 1<<23
+Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+itemkeys: a key Id.
+message: message to print when player picks up this key.
+model: custom key model to use.
+netname: the display name of the key.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+This is the only correct way to put keys on the map!
+
+itemkeys MUST always have exactly one bit set.
+*/
+spawnfunc(item_key)
+{
+       string _netname;
+       vector _colormod;
+
+       // reject this entity if more than one key was set!
+       if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) {
+               objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
+               delete(this);
+               return;
+       }
+
+       // find default netname and colormod
+       switch(this.itemkeys) {
+       case BIT(0):
+               _netname = "GOLD key";
+               _colormod = '1 .9 0';
+               break;
+
+       case BIT(1):
+               _netname = "SILVER key";
+               _colormod = '.9 .9 .9';
+               break;
+
+       case BIT(2):
+               _netname = "BRONZE key";
+               _colormod = '.6 .25 0';
+               break;
+
+       case BIT(3):
+               _netname = "RED keycard";
+               _colormod = '.9 0 0';
+               break;
+
+       case BIT(4):
+               _netname = "BLUE keycard";
+               _colormod = '0 0 .9';
+               break;
+
+       case BIT(5):
+               _netname = "GREEN keycard";
+               _colormod = '0 .9 0';
+               break;
+
+       default:
+               _netname = "FLUFFY PINK keycard";
+               _colormod = '1 1 1';
+
+               if (this.netname == "") {
+                       objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!");
+                       delete(this);
+                       return;
+               }
+               break;
+
+       }
+
+       // find default model
+       string _model = string_null;
+       if (this.itemkeys <= ITEM_KEY_BIT(2)) {
+               _model = "models/keys/key.md3";
+       } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) {
+               _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
+       } else if (this.model == "") {
+               objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!");
+               delete(this);
+               return;
+       }
+
+       // set defailt netname
+       if (this.netname == "")
+               this.netname = _netname;
+
+       // set default colormod
+       if (!this.colormod)
+               this.colormod = _colormod;
+
+       // set default model
+       if (this.model == "")
+               this.model = _model;
+
+       // set default pickup message
+       if (this.message == "")
+               this.message = strzone(strcat("You've picked up the ", this.netname, "!"));
+
+       if (this.noise == "")
+               this.noise = strzone(SND(ITEMPICKUP));
+
+       // save the name for later
+       item_keys_names[lowestbit(this.itemkeys)] = this.netname;
+
+       // put the key on the map
+       spawn_item_key(this);
+}
+
+/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+SILVER key.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+spawnfunc(item_key1)
+{
+       this.classname = "item_key";
+       this.itemkeys = ITEM_KEY_BIT(1);
+       spawnfunc_item_key(this);
+}
+
+/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+GOLD key.
+-----------KEYS------------
+colormod: color of the key (default: '1 .9 0').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+spawnfunc(item_key2)
+{
+       this.classname = "item_key";
+       this.itemkeys = ITEM_KEY_BIT(0);
+       spawnfunc_item_key(this);
+}
+
+#endif
diff --git a/qcsrc/common/mapobjects/misc/keys.qh b/qcsrc/common/mapobjects/misc/keys.qh
new file mode 100644 (file)
index 0000000..50be5f8
--- /dev/null
@@ -0,0 +1,26 @@
+#pragma once
+
+/**
+ * Returns the bit ID of a key
+ */
+#define ITEM_KEY_BIT(n)        ( bitshift(1, n) )
+
+#define ITEM_KEY_MAX   24
+
+/**
+ * list of key names.
+ */
+#ifdef SVQC
+string item_keys_names[ITEM_KEY_MAX];
+
+/**
+ * Use keys from p on l.
+ * Returns true if any new keys were given, false otherwise.
+ */
+float item_keys_usekey(entity l, entity p);
+
+/**
+ * Returns a string with a comma separated list of key names, as specified in keylist.
+ */
+string item_keys_keylist(float keylist);
+#endif
index 92ff464b71016951d4f675e0c667b11429b5e13f..10c3900408e1dd3cd818f9c2715729c5c52060b7 100644 (file)
@@ -41,6 +41,11 @@ void g_clientmodel_setcolormaptoactivator(entity this, entity actor, entity trig
 
 void g_clientmodel_use(entity this, entity actor, entity trigger)
 {
+       // Flag to set func_clientwall state
+       // 1 == deactivate, 2 == activate, 0 == do nothing
+       if(this.classname == "func_clientwall" || this.classname == "func_clientillusionary")
+               this.antiwall_flag = trigger.antiwall_flag;
+
        if (this.antiwall_flag == 1)
        {
                this.inactive = 1;
@@ -148,10 +153,10 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
                        WriteVector(MSG_ENTITY, this.movedir);
                        WriteByte(MSG_ENTITY, floor(this.lip * 255));
                }
-               WriteByte(MSG_ENTITY, this.fade_start);
-               WriteByte(MSG_ENTITY, this.fade_end);
-               WriteByte(MSG_ENTITY, this.alpha_max);
-               WriteByte(MSG_ENTITY, this.alpha_min);
+               WriteShort(MSG_ENTITY, bound(0, this.fade_start, 65535));
+               WriteShort(MSG_ENTITY, bound(0, this.fade_end, 65535));
+               WriteByte(MSG_ENTITY, floor(this.alpha_max * 256));
+               WriteByte(MSG_ENTITY, floor(this.alpha_min * 256));
                WriteByte(MSG_ENTITY, this.inactive);
                WriteShort(MSG_ENTITY, this.fade_vertical_offset);
        }
@@ -199,42 +204,42 @@ spawnfunc(func_clientwall)        { G_CLIENTMODEL_INIT(this, SOLID_BSP) } // bru
 
 void Ent_Wall_PreDraw(entity this)
 {
+       float alph = this.alpha;
        if (this.inactive)
        {
-               this.alpha = 0;
+               alph = 0;
        }
        else
        {
                vector org = getpropertyvec(VF_ORIGIN);
                if(!checkpvs(org, this))
-                       this.alpha = 0;
+                       alph = 0;
                else if(this.fade_start || this.fade_end) {
                        vector offset = '0 0 0';
                        offset_z = this.fade_vertical_offset;
-                       float player_dist = vlen(org - this.origin - 0.5 * (this.mins + this.maxs) + offset);
+                       vector player_dist_math = org - this.origin - 0.5 * (this.mins + this.maxs) + offset;
                        if (this.fade_end == this.fade_start)
                        {
-                               if (player_dist >= this.fade_start)
-                                       this.alpha = 0;
+                               if (vdist(player_dist_math, >=, this.fade_start))
+                                       alph = 0;
                                else
-                                       this.alpha = 1;
+                                       alph = 1;
                        }
                        else
                        {
-                               this.alpha = (this.alpha_min + this.alpha_max * bound(0,
+                               float player_dist = vlen(player_dist_math);
+                               alph = (this.alpha_min + this.alpha_max * bound(0,
                                                           (this.fade_end - player_dist)
                                                           / (this.fade_end - this.fade_start), 1)) / 100.0;
                        }
                }
                else
                {
-                       this.alpha = 1;
+                       alph = 1;
                }
        }
-       if(this.alpha <= 0)
-               this.drawmask = 0;
-       else
-               this.drawmask = MASK_NORMAL;
+       this.alpha = alph;
+       this.drawmask = (alph <= 0) ? 0 : MASK_NORMAL;
 }
 
 void Ent_Wall_Draw(entity this)
@@ -390,10 +395,10 @@ NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
                        this.movedir = ReadVector();
                        this.lip = ReadByte() / 255.0;
                }
-               this.fade_start = ReadByte();
-               this.fade_end = ReadByte();
-               this.alpha_max = ReadByte();
-               this.alpha_min = ReadByte();
+               this.fade_start = ReadShort();
+               this.fade_end = ReadShort();
+               this.alpha_max = ReadByte() / 255.0;
+               this.alpha_min = ReadByte() / 255.0;
                this.inactive = ReadByte();
                this.fade_vertical_offset = ReadShort();
                BGMScript_InitEntity(this);
index 0fa7db2f1c6eab6a59bc39ad39e4dbaf348d08a2..861d73e72f28d6522ea9c488d91a6ae465f6a87d 100644 (file)
@@ -24,6 +24,7 @@ SUB_SetFade
 Fade 'ent' out when time >= 'when'
 ==================
 */
+.float fade_rate;
 void SUB_SetFade(entity ent, float when, float fading_time);
 
 .vector                finaldest, finalangle;          //plat.qc stuff
index 4c89c4c27ed20efc86f73a678c615d68aa82673b..9156439f99e3bf19bb9bdc8425efe1fdcd06d53d 100644 (file)
@@ -4,13 +4,21 @@ void counter_reset(entity this);
 
 void counter_use(entity this, entity actor, entity trigger)
 {
-       this.count -= 1;
-       if (this.count < 0)
+       entity store = this;
+       if(this.spawnflags & COUNTER_PER_PLAYER)
+       {
+               if(!IS_PLAYER(actor))
+                       return;
+               store = actor;
+       }
+
+       store.counter_cnt += 1;
+       if (store.counter_cnt > this.count)
                return;
 
        bool doactivate = (this.spawnflags & COUNTER_FIRE_AT_COUNT);
 
-       if (this.count == 0)
+       if (store.counter_cnt == this.count)
        {
                if(IS_PLAYER(actor) && !(this.spawnflags & SPAWNFLAG_NOMESSAGE))
                        Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COMPLETED);
@@ -27,10 +35,10 @@ void counter_use(entity this, entity actor, entity trigger)
        {
                if(IS_PLAYER(actor) && !(this.spawnflags & SPAWNFLAG_NOMESSAGE))
                {
-                       if(this.count >= 4)
+                       if((this.count - store.counter_cnt) >= 4)
                                Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER);
                        else
-                               Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, this.count);
+                               Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, this.count - store.counter_cnt);
                }
        }
 
@@ -42,7 +50,7 @@ void counter_reset(entity this)
 {
        setthink(this, func_null);
        this.nextthink = 0;
-       this.count = this.cnt;
+       this.counter_cnt = 0;
 }
 
 /*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT
@@ -59,8 +67,8 @@ spawnfunc(trigger_counter)
 {
        if (!this.count)
                this.count = 2;
-       this.cnt = this.count;
 
+       this.counter_cnt = 0;
        this.use = counter_use;
        this.reset = counter_reset;
 }
index 394d15472cdbc68f289b9476ec00311e6dd22e09..d36bd0293cc933ead43f3e2248b46d157cdc91c3 100644 (file)
@@ -1,4 +1,10 @@
 #pragma once
 
+#ifdef SVQC
+spawnfunc(trigger_counter);
+
+.float counter_cnt;
+#endif
 
 const int COUNTER_FIRE_AT_COUNT = BIT(2);
+const int COUNTER_PER_PLAYER = BIT(3);
index 966e0cfb0fe6657287ee8135c9f9411f732de18d..ccdf2c7d0b96a291086be949e2c53db8180b725d 100644 (file)
@@ -25,7 +25,7 @@ void trigger_hurt_touch(entity this, entity toucher)
                if (toucher.triggerhurttime < time)
                {
                        EXACTTRIGGER_TOUCH(this, toucher);
-                       toucher.triggerhurttime = time + 1;
+                       toucher.triggerhurttime = time + ((autocvar_sv_vq3compat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
 
                        entity own;
                        own = this.enemy;
@@ -53,7 +53,7 @@ void trigger_hurt_touch(entity this, entity toucher)
 /*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
 Any object touching this will be hurt
 set dmg to damage amount
-default dmg = 1000
+default dmg = 10000
 */
 .entity trigger_hurt_next;
 entity trigger_hurt_last;
@@ -66,7 +66,7 @@ spawnfunc(trigger_hurt)
        this.use = trigger_hurt_use;
        this.enemy = world; // I hate you all
        if (!this.dmg)
-               this.dmg = 1000;
+               this.dmg = ((autocvar_sv_vq3compat) ? 5 : 10000);
        if (this.message == "")
                this.message = "was in the wrong place";
        if (this.message2 == "")
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..e992154aa97fd6a76cd6d7fc6d856ebb356eda4a 100644 (file)
@@ -1 +1,3 @@
 #pragma once
+
+const int HURT_SLOW = BIT(4);
index 5ffdf2d1066085d9bd47fd1dd5d541af179b4671..ca1faeaf93c2ddd97e8c3ef052c3d770122cde26 100644 (file)
@@ -133,9 +133,20 @@ bool jumppad_push(entity this, entity targ)
        if (!isPushable(targ))
                return false;
 
+       vector org = targ.origin;
+#ifdef SVQC
+       if(autocvar_sv_vq3compat)
+#elif defined(CSQC)
+       if(STAT(VQ3COMPAT))
+#endif
+       {
+               org.z += targ.mins_z;
+               org.z += 1; // off by 1!
+       }
+
        if(this.enemy)
        {
-               targ.velocity = trigger_push_calculatevelocity(targ.origin, this.enemy, this.height, targ);
+               targ.velocity = trigger_push_calculatevelocity(org, this.enemy, this.height, targ);
        }
        else if(this.target && this.target != "")
        {
@@ -148,7 +159,7 @@ bool jumppad_push(entity this, entity targ)
                        else
                                RandomSelection_AddEnt(e, 1, 1);
                }
-               targ.velocity = trigger_push_calculatevelocity(targ.origin, RandomSelection_chosen_ent, this.height, targ);
+               targ.velocity = trigger_push_calculatevelocity(org, RandomSelection_chosen_ent, this.height, targ);
        }
        else
        {
index 67db14421662c2d0c40483b328ee3dd30ee6babe..f7ecd7c1f1ab8c5c0e3afd1e202085c2e27fd460 100644 (file)
@@ -30,7 +30,14 @@ void trigger_keylock_touch(entity this, entity toucher)
 
        // check silver key
        if(this.itemkeys)
-               key_used = item_keys_usekey(this, toucher);
+       {
+#ifdef SVQC
+               entity store = PS(toucher);
+#elif defined(CSQC)
+               entity store = toucher;
+#endif
+               key_used = item_keys_usekey(this, store);
+       }
 
        if(this.itemkeys)
        {
index 904c3fa3d4a7404d5d4c0535fbc59858b2d6cc42..6f70f09beec2219624baeca92e2cd7deaa104fb4 100644 (file)
@@ -1,10 +1 @@
 #pragma once
-
-#ifdef CSQC
-bool item_keys_usekey(entity l, entity p)
-{
-       int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything!
-       l.itemkeys &= ~valid; // only some of the needed keys were given
-       return valid != 0;
-}
-#endif
index c7ed6643de207b68d1dad094d9673ac75955f85a..9a7181d3a2250a530466a1d3dcbf59a9e9d1f0d8 100644 (file)
@@ -1,7 +1,4 @@
 #include "triggers.qh"
-#ifdef SVQC
-       #include <server/item_key.qh>
-#endif
 
 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
 
@@ -13,17 +10,6 @@ void DelayThink(entity this)
        delete(this);
 }
 
-void FixSize(entity e)
-{
-       e.mins_x = rint(e.mins_x);
-       e.mins_y = rint(e.mins_y);
-       e.mins_z = rint(e.mins_z);
-
-       e.maxs_x = rint(e.maxs_x);
-       e.maxs_y = rint(e.maxs_y);
-       e.maxs_z = rint(e.maxs_z);
-}
-
 #ifdef SVQC
 void generic_setactive(entity this, int act)
 {
@@ -316,12 +302,9 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe
                }
                if (s != "")
                {
-                       // Flag to set func_clientwall state
-                       // 1 == deactivate, 2 == activate, 0 == do nothing
-                       int aw_flag = this.antiwall_flag;
                        for(entity t = NULL; (t = find(t, targetname, s)); )
                        {
-                               if(t.use && (t.sub_target_used != time || !preventReuse))
+                               if(t != this && t.use && (t.sub_target_used != time || !preventReuse))
                                {
                                        if(this.target_random)
                                        {
@@ -329,9 +312,6 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe
                                        }
                                        else
                                        {
-                                               if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
-                                                       t.antiwall_flag = aw_flag;
-
                                                t.use(t, actor, this);
                                                if(preventReuse)
                                                        t.sub_target_used = time;
index 82e7d54f0283781eb42fde552e99adfc14c6b4da..b9baf63f1c70ed30fcaaaf89559d298b45c93084 100644 (file)
@@ -40,8 +40,6 @@ void generic_netlinked_legacy_use(entity this, entity actor, entity trigger);
 
 .vector dest;
 
-void FixSize(entity e);
-
 #ifdef CSQC
 void trigger_common_read(entity this, bool withtarget);
 void trigger_remove_generic(entity this);
index 2049dc9eae601b8b03598fb74c2e49efbcba65bf..f299af3c3a086c2cae4735b989c2c7396044a77a 100644 (file)
@@ -357,9 +357,6 @@ void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
                HUD_MinigameMenu_entries = NULL;
                HUD_MinigameMenu_last_entry = NULL;
                HUD_MinigameMenu_activeitem = NULL;
-               if(autocvar_hud_cursormode)
-               if ( !autocvar__hud_configure )
-                       setcursormode(0);
        }
 }
 
@@ -420,8 +417,6 @@ void HUD_MinigameMenu_Open()
                        HUD_MinigameMenu_last_entry );
                HUD_MinigameMenu_CurrentButton();
                HUD_MinigameMenu_activeitem = NULL;
-               if(autocvar_hud_cursormode)
-                       setcursormode(1);
        }
 }
 
@@ -683,11 +678,6 @@ void HUD_Minigame_Mouse()
        if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure || mv_active )
                return;
 
-       if (!autocvar_hud_cursormode)
-               update_mousepos();
-
        if ( HUD_MinigameMenu_IsOpened() && HUD_mouse_over(HUD_PANEL(MINIGAMEMENU)) )
                HUD_MinigameMenu_MouseInput();
-
-       draw_cursor_normal(mousepos, '1 1 1', panel_fg_alpha);
 }
index b4195c05774eec2f08d780de5b4ddbff6cc687c5..91fa9cbda908509116acab6ed4c13adc022682cd 100644 (file)
@@ -1370,7 +1370,7 @@ int bd_client_event(entity minigame, string event, ...)
                                {
                                        sent.message = bd_turn_to_string(sent.minigame_flags);
                                        //if ( sent.minigame_flags & minigame_self.team )
-                                               minigame_prompt();
+                                               //minigame_prompt();
                                }
                        }
                        else if(sent.classname == "minigame_board_piece")
index c8851f2ac4bad90e9f437751a20482182736050c..b5b900b8a18a1d10fbf959368b92f8321f512db4 100644 (file)
@@ -606,8 +606,8 @@ int ps_client_event(entity minigame, string event, ...)
                                if ( sf & MINIG_SF_UPDATE )
                                {
                                        sent.message = ps_turn_to_string(sent.minigame_flags);
-                                       if ( sent.minigame_flags & minigame_self.team )
-                                               minigame_prompt();
+                                       //if ( sent.minigame_flags & minigame_self.team )
+                                               //minigame_prompt();
                                }
                        }
 
index 5e2cc0513851594d70a64167656be7196135500d..d847cf4e6cd2942494bb8beeb61d45abae40ad81 100644 (file)
@@ -168,9 +168,9 @@ void M_Spider_Attack_Web(entity this)
 
 bool M_Spider_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
+       Weapon wep = WEP_SPIDER_ATTACK;
        switch(attack_type)
        {
-               Weapon wep = WEP_SPIDER_ATTACK;
                case MONSTER_ATTACK_MELEE:
                {
                        wep.wr_think(wep, actor, weaponentity, 2);
index 84355c7f3530ffddcf3dccde86781d487c7fd717..004fbf92b659a8c5641f20f8eea173770c676771 100644 (file)
@@ -695,7 +695,6 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra
 }
 
 .entity draggedby;
-.entity target2;
 
 void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
 {
@@ -895,7 +894,7 @@ void Monster_Reset(entity this)
        setorigin(this, this.pos1);
        this.angles = this.pos2;
 
-       Unfreeze(this); // remove any icy remains
+       Unfreeze(this, false); // remove any icy remains
 
        SetResourceAmountExplicit(this, RESOURCE_HEALTH, this.max_health);
        this.velocity = '0 0 0';
@@ -931,10 +930,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed)
        this.monster_lifetime = time + 5;
 
        if(STAT(FROZEN, this))
-       {
-               Unfreeze(this); // remove any icy remains
-               SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0); // reset by Unfreeze (TODO)
-       }
+               Unfreeze(this, false); // remove any icy remains
 
        monster_dropitem(this, attacker);
 
@@ -1161,7 +1157,7 @@ void Monster_Anim(entity this)
 
 void Monster_Frozen_Think(entity this)
 {
-       if(STAT(FROZEN, this) == 2)
+       if (STAT(FROZEN, this) == FROZEN_TEMP_REVIVING)
        {
                STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) + this.ticrate * this.revive_speed, 1);
                SetResourceAmountExplicit(this, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, this) * this.max_health));
@@ -1171,9 +1167,9 @@ void Monster_Frozen_Think(entity this)
                        WaypointSprite_UpdateHealth(this.sprite, GetResourceAmount(this, RESOURCE_HEALTH));
 
                if(STAT(REVIVE_PROGRESS, this) >= 1)
-                       Unfreeze(this);
+                       Unfreeze(this, false);
        }
-       else if(STAT(FROZEN, this) == 3)
+       else if (STAT(FROZEN, this) == FROZEN_TEMP_DYING)
        {
                STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) - this.ticrate * this.revive_speed, 1);
                SetResourceAmountExplicit(this, RESOURCE_HEALTH, max(0, autocvar_g_nades_ice_health + (this.max_health-autocvar_g_nades_ice_health) * STAT(REVIVE_PROGRESS, this)));
@@ -1183,14 +1179,12 @@ void Monster_Frozen_Think(entity this)
 
                if(GetResourceAmount(this, RESOURCE_HEALTH) < 1)
                {
-                       Unfreeze(this);
-                       SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0);
+                       Unfreeze(this, false);
                        if(this.event_damage)
                                this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, DMG_NOWEP, this.origin, '0 0 0');
                }
-
                else if ( STAT(REVIVE_PROGRESS, this) <= 0 )
-                       Unfreeze(this);
+                       Unfreeze(this, false);
        }
        // otherwise, no revival!
 
index b7cdbf05b83c171ad278e61a3eb7e9c021ff78d6..9338c986c9d6ca3e3cd571c51895697a113e0543 100644 (file)
@@ -423,7 +423,7 @@ void buff_Medic_Heal(entity this)
 {
        FOREACH_CLIENT(IS_PLAYER(it) && it != this && vdist(it.origin - this.origin, <=, autocvar_g_buffs_medic_heal_range),
        {
-               if (!SAME_TEAM(it, this))
+               if (DIFF_TEAM(it, this))
                {
                        continue;
                }
index d9eacaae0c4e7a1cf2821d4574bb255a572c3bd5..0e0aa13fd0404412f13e612743d648bc1d436cca 100644 (file)
@@ -10,12 +10,12 @@ REGISTER_MUTATOR(damagetext, true);
 #define SV_DAMAGETEXT_ALL()             (autocvar_sv_damagetext >= 3)
 MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
     if (SV_DAMAGETEXT_DISABLED()) return;
-    const entity attacker = M_ARGV(0, entity);
-    const entity hit = M_ARGV(1, entity); if (hit == attacker) return;
-    const float health = M_ARGV(2, float);
-    const float armor = M_ARGV(3, float);
-    const int deathtype = M_ARGV(5, int);
-    const float potential_damage = M_ARGV(6, float);
+    entity attacker = M_ARGV(0, entity);
+    entity hit = M_ARGV(1, entity); if (hit == attacker) return;
+    float health = M_ARGV(2, float);
+    float armor = M_ARGV(3, float);
+    int deathtype = M_ARGV(5, int);
+    float potential_damage = M_ARGV(6, float);
     if(DEATH_WEAPONOF(deathtype) == WEP_VAPORIZER) return;
     FOREACH_CLIENT(IS_REAL_CLIENT(it), {
         if (
index d5d3ba40f8ee233127078a6e4ff735d855f9f05a..4cfc0dd23779d4f5babee08a864b2fcce14dfdcd 100644 (file)
@@ -32,13 +32,13 @@ float DynamicHandicap_ClampHandicap(float handicap);
 void DynamicHandicap_UpdateHandicap()
 {
        float total_score = 0;
-       float total_players = 0;
+       float totalplayers = 0;
        FOREACH_CLIENT(IS_PLAYER(it),
        {
                total_score += PlayerScore_Get(it, SP_SCORE);
-               ++total_players;
+               ++totalplayers;
        });
-       float mean_score = total_score / total_players;
+       float mean_score = total_score / totalplayers;
        FOREACH_CLIENT(true,
        {
                float score = PlayerScore_Get(it, SP_SCORE);
index 68a3af3baf76d5ae65f46819004a865c91ce604e..43de3b8cdc6482a91d8f561aec1a9b52f0c81bae 100644 (file)
@@ -383,7 +383,7 @@ void nade_ice_freeze(entity freezefield, entity frost_target, float freezetime)
 {
        frost_target.frozen_by = freezefield.realowner;
        Send_Effect(EFFECT_ELECTRO_IMPACT, frost_target.origin, '0 0 0', 1);
-       Freeze(frost_target, 1 / freezetime, 3, false);
+       Freeze(frost_target, 1 / freezetime, FROZEN_TEMP_DYING, false);
 
        Drop_Special_Items(frost_target);
 }
@@ -1021,7 +1021,7 @@ void nades_GiveBonus(entity player, float score)
        if (autocvar_g_nades_bonus)
        if (IS_REAL_CLIENT(player))
        if (IS_PLAYER(player) && STAT(NADE_BONUS, player) < autocvar_g_nades_bonus_max)
-       if (STAT(FROZEN, player) == 0)
+       if (!STAT(FROZEN, player))
        if (!IS_DEAD(player))
        {
                if ( STAT(NADE_BONUS_SCORE, player) < 1 )
@@ -1103,7 +1103,8 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        n.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
 
        setmodel(fn, MDL_NADE_VIEW);
-       setattachment(fn, player.(weaponentity), "");
+       //setattachment(fn, player.(weaponentity), "");
+       fn.viewmodelforclient = player;
        fn.realowner = fn.owner = player;
        fn.colormod = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_color;
        fn.colormap = player.colormap;
@@ -1258,6 +1259,15 @@ MUTATOR_HOOKFUNCTION(nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
        }
 }
 
+#ifdef IS_REVIVING
+       #undef IS_REVIVING
+#endif
+
+// returns true if player is reviving it
+#define IS_REVIVING(player, it, revive_extra_size) \
+       (it != player && !STAT(FROZEN, it) && !IS_DEAD(it) && SAME_TEAM(it, player) \
+       && boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
+
 MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
 {
        entity player = M_ARGV(0, entity);
@@ -1329,43 +1339,43 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
        }
 
        int n = 0;
-       entity o = NULL;
+
+       IntrusiveList reviving_players = NULL;
+
        if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
                n = -1;
-       else if(STAT(FROZEN, player) == 3)
+       else if (STAT(FROZEN, player) == FROZEN_TEMP_DYING)
        {
                vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
                n = 0;
-               FOREACH_CLIENT(IS_PLAYER(it) && it != player, {
-                       if(!IS_DEAD(it) && STAT(FROZEN, it) == 0 && SAME_TEAM(it, player))
-                       if(boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
-                       {
-                               if(!o)
-                                       o = it;
-                               it.reviving = true;
-                               ++n;
-                       }
+               FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
+                       if (!reviving_players)
+                               reviving_players = IL_NEW();
+                       IL_PUSH(reviving_players, it);
+                       ++n;
                });
        }
 
-       if(n > 0 && STAT(FROZEN, player) == 3) // OK, there is at least one teammate reviving us
+       if (n > 0 && STAT(FROZEN, player) == FROZEN_TEMP_DYING) // OK, there is at least one teammate reviving us
        {
                STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
                SetResourceAmount(player, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * start_health));
 
                if(STAT(REVIVE_PROGRESS, player) >= 1)
                {
-                       Unfreeze(player);
+                       Unfreeze(player, false);
 
-                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, o.netname);
-                       Send_Notification(NOTIF_ONE, o, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
+                       entity first = IL_FIRST(reviving_players);
+                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
+                       Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
                }
 
-               FOREACH_CLIENT(IS_PLAYER(it) && it.reviving, {
+               IL_EACH(reviving_players, true, {
                        STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
-                       it.reviving = false;
                });
        }
+       if (reviving_players)
+               IL_DELETE(reviving_players);
 }
 
 MUTATOR_HOOKFUNCTION(nades, PlayerPhysics_UpdateStats)
@@ -1468,7 +1478,7 @@ MUTATOR_HOOKFUNCTION(nades, Damage_Calculate)
        if(autocvar_g_freezetag_revive_nade && STAT(FROZEN, frag_target) && frag_attacker == frag_target && frag_deathtype == DEATH_NADE.m_id)
        if(time - frag_inflictor.toss_time <= 0.1)
        {
-               Unfreeze(frag_target);
+               Unfreeze(frag_target, false);
                SetResourceAmount(frag_target, RESOURCE_HEALTH, autocvar_g_freezetag_revive_nade_health);
                Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3);
                M_ARGV(4, float) = 0;
index d278ca9d444b052f4a2a9a3151321be48b78460f..688928ce1425b23a4a1294de87788d66b1406b07 100644 (file)
@@ -36,7 +36,7 @@ void W_OverkillHeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity
        }
 
        float okhmg_spread = bound(WEP_CVAR_PRI(okhmg, spread_min), WEP_CVAR_PRI(okhmg, spread_min) + (WEP_CVAR_PRI(okhmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR_PRI(okhmg, spread_max));
-       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okhmg_spread, WEP_CVAR_PRI(okhmg, solidpenetration), WEP_CVAR_PRI(okhmg, damage), WEP_CVAR_PRI(okhmg, force), WEP_OVERKILL_HMG.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okhmg_spread, WEP_CVAR_PRI(okhmg, solidpenetration), WEP_CVAR_PRI(okhmg, damage), WEP_CVAR_PRI(okhmg, force), WEP_OVERKILL_HMG.m_id, EFFECT_RIFLE);
 
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
@@ -51,8 +51,7 @@ void W_OverkillHeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity
                SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
-       int slot = weaponslot(weaponentity);
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(okhmg, refire) * W_WeaponRateFactor(actor);
+       ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(okhmg, refire) * W_WeaponRateFactor(actor);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okhmg, refire), W_OverkillHeavyMachineGun_Attack_Auto);
 }
 
index 63c1e245b4ad1121cfbf593ac4e563da67c6b2b0..aa872f1541a64f052d79d7c73751a6c7e46a984c 100644 (file)
@@ -30,7 +30,7 @@ void W_OverkillMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weap
        }
 
        okmachinegun_spread = bound(WEP_CVAR_PRI(okmachinegun, spread_min), WEP_CVAR_PRI(okmachinegun, spread_min) + (WEP_CVAR_PRI(okmachinegun, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR_PRI(okmachinegun, spread_max));
-       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okmachinegun_spread, WEP_CVAR_PRI(okmachinegun, solidpenetration), WEP_CVAR_PRI(okmachinegun, damage), WEP_CVAR_PRI(okmachinegun, force), WEP_OVERKILL_MACHINEGUN.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okmachinegun_spread, WEP_CVAR_PRI(okmachinegun, solidpenetration), WEP_CVAR_PRI(okmachinegun, damage), WEP_CVAR_PRI(okmachinegun, force), WEP_OVERKILL_MACHINEGUN.m_id, EFFECT_RIFLE);
 
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
@@ -45,8 +45,7 @@ void W_OverkillMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weap
                SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
-       int slot = weaponslot(weaponentity);
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(okmachinegun, refire) * W_WeaponRateFactor(actor);
+       ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(okmachinegun, refire) * W_WeaponRateFactor(actor);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okmachinegun, refire), W_OverkillMachineGun_Attack_Auto);
 }
 
@@ -153,4 +152,3 @@ METHOD(OverkillMachineGun, wr_impacteffect, void(entity thiswep, entity actor))
 }
 
 #endif
-
index 997b49de9d6161aab5b74374d8498f790b6107e3..32176da90a3b1713080854ec37508d1700a75b7f 100644 (file)
@@ -4,7 +4,7 @@ CLASS(OverkillMachineGun, Weapon)
 /* spawnfunc */ ATTRIB(OverkillMachineGun, m_canonical_spawnfunc, string, "weapon_okmachinegun");
 /* ammotype  */ ATTRIB(OverkillMachineGun, ammo_type, int, RESOURCE_BULLETS);
 /* impulse   */ ATTRIB(OverkillMachineGun, impulse, int, 3);
-/* flags        */ ATTRIB(OverkillMachineGun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_PENETRATEWALLS | WEP_FLAG_MUTATORBLOCKED);
+/* flags        */ ATTRIB(OverkillMachineGun, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_PENETRATEWALLS | WEP_FLAG_MUTATORBLOCKED);
 /* rating      */ ATTRIB(OverkillMachineGun, bot_pickupbasevalue, float, 7000);
 /* color        */ ATTRIB(OverkillMachineGun, wpcolor, vector, '1 1 0');
 /* modelname */ ATTRIB(OverkillMachineGun, mdl, string, "ok_mg");
index 0f67ddba2b0e8bca1318e35c7f75461cff7ae9da..4fbd200b699321160defd98d9259311ec8de60a2 100644 (file)
@@ -82,7 +82,7 @@ void W_OverkillNex_Attack(Weapon thiswep, entity actor, .entity weaponentity, fl
        mydmg *= charge;
        myforce *= charge;
 
-       W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg, WEP_OVERKILL_NEX.m_id);
+       W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg, thiswep.m_id);
        if(charge > WEP_CVAR(oknex, charge_animlimit) && WEP_CVAR(oknex, charge_animlimit)) // if the OverkillNex is overcharged, we play an extra sound
        {
                sound(actor, CH_WEAPON_B, SND_NEXCHARGE, VOL_BASE * (charge - 0.5 * WEP_CVAR(oknex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(oknex, charge_animlimit)), ATTN_NORM);
@@ -90,7 +90,7 @@ void W_OverkillNex_Attack(Weapon thiswep, entity actor, .entity weaponentity, fl
 
        yoda = 0;
        damage_goodhits = 0;
-       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_OVERKILL_NEX.m_id);
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, thiswep.m_id);
 
        if(yoda && flying)
                Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
@@ -269,7 +269,7 @@ METHOD(OverkillNex, wr_setup, void(entity thiswep, entity actor, .entity weapone
 METHOD(OverkillNex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
        float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(oknex, ammo);
-       ammo_amount += (autocvar_g_balance_oknex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_OVERKILL_NEX.m_id]) >= WEP_CVAR_PRI(oknex, ammo));
+       ammo_amount += (autocvar_g_balance_oknex_reload_ammo && actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(oknex, ammo));
        return ammo_amount;
 }
 
@@ -279,7 +279,7 @@ METHOD(OverkillNex, wr_checkammo2, bool(entity thiswep, entity actor, .entity we
        {
                // don't allow charging if we don't have enough ammo
                float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(oknex, ammo);
-               ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_NEX.m_id]) >= WEP_CVAR_SEC(oknex, ammo);
+               ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(oknex, ammo);
                return ammo_amount;
        }
        else
index f38588e39e6a9a2ef11804b6edea7711e821d30e..ec8ceeb3902df4ed2cbdc7affa69d654cc9448c8 100644 (file)
@@ -4,7 +4,7 @@ CLASS(OverkillNex, Weapon)
 /* spawnfunc */ ATTRIB(OverkillNex, m_canonical_spawnfunc, string, "weapon_oknex");
 /* ammotype  */ ATTRIB(OverkillNex, ammo_type, int, RESOURCE_CELLS);
 /* impulse   */ ATTRIB(OverkillNex, impulse, int, 7);
-/* flags     */ ATTRIB(OverkillNex, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(OverkillNex, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_MUTATORBLOCKED);
 /* rating    */ ATTRIB(OverkillNex, bot_pickupbasevalue, float, 8000);
 /* color     */ ATTRIB(OverkillNex, wpcolor, vector, '0.5 1 1');
 /* modelname */ ATTRIB(OverkillNex, mdl, string, "ok_sniper");
index 3174fa7ff31ee4006231c4f45fbba5395619fe74..50c842d9844144c6c5da0b60ed31f41c9c7cd33b 100644 (file)
@@ -14,7 +14,7 @@ void W_OverkillRocketPropelledChainsaw_Explode(entity this, entity directhitenti
        {
                // if chainsaw hit something, it removed fired damage (so that direct hit is 100%)
                // now that we also damaged something by explosion we'd go over 100% so let's add the fired damage back
-               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, WEP_CVAR(okrpc, damage), 0);
+               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype), WEP_CVAR(okrpc, damage), 0);
        }
 
        delete(this);
@@ -71,7 +71,7 @@ void W_OverkillRocketPropelledChainsaw_Think(entity this)
                                // We remove it here so that a direct hit that passes through and doesn't damage anything by the explosion later is still 100%.
                                float fired_damage = WEP_CVAR_PRI(okrpc, damage2) - WEP_CVAR_PRI(okrpc, damage);
                                float hit_damage = WEP_CVAR_PRI(okrpc, damage2);
-                               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, fired_damage, hit_damage);
+                               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype), fired_damage, hit_damage);
                        }
                        this.m_chainsaw_damage += WEP_CVAR_PRI(okrpc, damage2);
                }
@@ -84,13 +84,13 @@ void W_OverkillRocketPropelledChainsaw_Think(entity this)
        this.nextthink = time;
 }
 
-void W_OverkillRocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity weaponentity)
+void W_OverkillRocketPropelledChainsaw_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
        entity flash = spawn ();
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(okrpc, ammo), weaponentity);
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(okrpc, damage), WEP_OVERKILL_RPC.m_id);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(okrpc, damage), thiswep.m_id);
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
 
@@ -106,7 +106,7 @@ void W_OverkillRocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .en
        IL_PUSH(g_damagedbycontents, missile);
        set_movetype(missile, MOVETYPE_FLY);
 
-       missile.projectiledeathtype = WEP_OVERKILL_RPC.m_id;
+       missile.projectiledeathtype = thiswep.m_id;
        missile.weaponentity_fld = weaponentity;
        setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
 
@@ -192,14 +192,14 @@ METHOD(OverkillRocketPropelledChainsaw, wr_think, void(entity thiswep, entity ac
 METHOD(OverkillRocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
        float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(okrpc, ammo);
-       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_RPC.m_id]) >= WEP_CVAR_PRI(okrpc, ammo);
+       ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(okrpc, ammo);
        return ammo_amount;
 }
 
 METHOD(OverkillRocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
        float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(okrpc, ammo);
-       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_RPC.m_id]) >= WEP_CVAR_SEC(okrpc, ammo);
+       ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(okrpc, ammo);
        return ammo_amount;
 }
 
index 2f1651776fdab25a67b98a42b0f9e386b44805ea..2461ba0cb09dd1098019bd1929a08fccbf6accbb 100644 (file)
@@ -45,7 +45,7 @@ METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity wea
        }
        if (fire & 1) // Primary attack
        {
-               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, animtime)))
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, refire)))
                {
                        return;
                }
@@ -55,7 +55,8 @@ METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity wea
                        WEP_CVAR_PRI(okshotgun, bullets),
                        WEP_CVAR_PRI(okshotgun, spread),
                        WEP_CVAR_PRI(okshotgun, solidpenetration),
-                       WEP_CVAR_PRI(okshotgun, force));
+                       WEP_CVAR_PRI(okshotgun, force),
+                       EFFECT_RIFLE_WEAK);
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okshotgun, animtime), w_ready);
                return;
        }
index a383c9d7a8b1bef15311879e438bd60ccc9c0649..1124baa68bff28fc72e75c9c4d4d2529384d3e7a 100644 (file)
@@ -4,7 +4,7 @@ CLASS(OverkillShotgun, Weapon)
 /* spawnfunc */ ATTRIB(OverkillShotgun, m_canonical_spawnfunc, string, "weapon_okshotgun");
 /* ammotype  */ ATTRIB(OverkillShotgun, ammo_type, int, RESOURCE_SHELLS);
 /* impulse   */ ATTRIB(OverkillShotgun, impulse, int, 2);
-/* flags     */ ATTRIB(OverkillShotgun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_MUTATORBLOCKED);
+/* flags     */ ATTRIB(OverkillShotgun, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_MUTATORBLOCKED);
 /* rating    */ ATTRIB(OverkillShotgun, bot_pickupbasevalue, float, 6000);
 /* color     */ ATTRIB(OverkillShotgun, wpcolor, vector, '0.5 0.25 0');
 /* modelname */ ATTRIB(OverkillShotgun, mdl, string, "ok_shotgun");
index 9fa66e8b2a18c12523da72e4c45820d0c711fe7e..c8e4398b0d7c502e845cecfa5b0547f7fceb7eb4 100644 (file)
@@ -102,7 +102,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies)
        entity frag_attacker = M_ARGV(1, entity);
        entity frag_target = M_ARGV(2, entity);
 
-       entity targ = ((frag_attacker) ? frag_attacker : frag_target);
+       entity targ = ((IS_PLAYER(frag_attacker)) ? frag_attacker : frag_target);
 
        ok_DropItem(frag_target, targ);
 
index ee2a5be7f504d11c376bd85b31ec28b505b7eeec..fdcc4beee5fb51ab89c4ca8774638aa435241d14 100644 (file)
@@ -90,7 +90,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
                        if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_max && tested >= autocvar_g_spawn_near_teammate_ignore_spawnpoint_max) break;
 
                        if (PHYS_INPUT_BUTTON_CHAT(it)) continue;
-                       if (!SAME_TEAM(player, it)) continue;
+                       if (DIFF_TEAM(player, it)) continue;
                        if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && GetResourceAmount(it, RESOURCE_HEALTH) < autocvar_g_balance_health_regenstable) continue;
                        if (IS_DEAD(it)) continue;
                        if (time < it.msnt_timer) continue;
index 7cb218412f8897dec276c561b06ce5bbd0b188bf..1b93cbf35986f4e62cdb127486095f8cd5f55b89 100644 (file)
 #define A_ALWAYS 2
 
 // MSG_CHOICE_NOTIFICATIONS
-    MULTITEAM_CHOICE(CTF_CAPTURE_BROKEN, 4,     N__NORMAL, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_BROKEN)
-    MULTITEAM_CHOICE(CTF_CAPTURE_TIME, 4,       N__NORMAL, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_TIME)
-    MULTITEAM_CHOICE(CTF_CAPTURE_UNBROKEN, 4,   N__NORMAL, A_ALWAYS,  MSG_INFO,   INFO_CTF_CAPTURE,                   INFO_CTF_CAPTURE_UNBROKEN)
+    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)
     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)
index 9ac3e4299901db21051d4ea2f206fe8636bbfa30..ef9fbdf0f16b4e66388a9d6bf8312b106c065a70 100644 (file)
@@ -36,11 +36,15 @@ 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
 {
+       if(dt <= 0)
+               return 0;
+
        int blocked = 0;
        int i, j, numplanes = 0;
        float time_left = dt, grav = 0;
        vector push;
-       vector primal_velocity, original_velocity, restore_velocity;
+       vector primal_velocity, original_velocity;
+       vector restore_velocity = this.velocity;
 
        for(i = 0; i < MAX_CLIP_PLANES; ++i)
                planes[i] = '0 0 0';
@@ -59,7 +63,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                }
        }
 
-       original_velocity = primal_velocity = restore_velocity = this.velocity;
+       original_velocity = primal_velocity = this.velocity;
 
        for(int bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
        {
@@ -67,8 +71,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        break;
 
                push = this.velocity * time_left;
-               _Movetype_PushEntity(this, push, true);
-               if(trace_startsolid)
+               if(!_Movetype_PushEntity(this, push, true, false))
                {
                        // we got teleported by a touch function
                        // let's abort the move
@@ -113,22 +116,19 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        vector org = this.origin;
                        vector steppush = '0 0 1' * stepheight;
 
-                       _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid)
+                       if(!_Movetype_PushEntity(this, steppush, true, false))
                        {
                                blocked |= 8;
                                break;
                        }
-                       _Movetype_PushEntity(this, push, true);
-                       if(trace_startsolid)
+                       if(!_Movetype_PushEntity(this, push, true, false))
                        {
                                blocked |= 8;
                                break;
                        }
                        float trace2_fraction = trace_fraction;
-                       steppush = '0 0 1' * (org.z - this.origin_z);
-                       _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid)
+                       steppush = vec3(0, 0, org.z - this.origin_z);
+                       if(!_Movetype_PushEntity(this, steppush, true, false))
                        {
                                blocked |= 8;
                                break;
@@ -232,6 +232,9 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        if(GAMEPLAYFIX_EASIERWATERJUMP(this) && (this.flags & FL_WATERJUMP) && !(blocked & 8))
                this.velocity = primal_velocity;
 
+       if(PHYS_WALLCLIP(this) && this.pm_time && !(this.flags & FL_WATERJUMP) && !(blocked & 8))
+               this.velocity = primal_velocity;
+
        if(applygravity)
        {
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
@@ -403,11 +406,11 @@ entity _Movetype_TestEntityPosition_ent;
 bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
 {
     entity this = _Movetype_TestEntityPosition_ent;
-//     vector org = this.origin + ofs;
+       vector org = this.origin + ofs;
 
        int cont = this.dphitcontentsmask;
        this.dphitcontentsmask = DPCONTENTS_SOLID;
-       tracebox(this.origin, this.mins, this.maxs, this.origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
+       tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
        this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
@@ -418,11 +421,11 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
        return false;
 }
 
-bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
+int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
 {
     _Movetype_TestEntityPosition_ent = this;
        if (!_Movetype_TestEntityPosition(' 0  0  0')) {
-           return true;
+           return UNSTICK_FINE;
        }
        #define X(v) if (_Movetype_TestEntityPosition(v))
        X('-1  0  0') X(' 1  0  0')
@@ -441,13 +444,32 @@ bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
         {
             LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)",
                 etof(this), this.classname, vtos(this.origin));
-            return false;
+            return UNSTICK_STUCK;
         }
        }
        LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
        _Movetype_LinkEdict(this, true);
-       return true;
+       return UNSTICK_FIXED;
+}
+
+void _Movetype_CheckStuck(entity this)  // SV_CheckStuck
+{
+       int unstick = _Movetype_UnstickEntity(this); // sets test position entity
+       switch(unstick)
+       {
+               case UNSTICK_FINE:
+                       this.oldorigin = this.origin;
+                       break;
+               case UNSTICK_FIXED:
+                       break; // already sorted
+               case UNSTICK_STUCK:
+                       vector offset = this.oldorigin - this.origin;
+                       if(!_Movetype_TestEntityPosition(offset))
+                               _Movetype_LinkEdict(this, false);
+                       // couldn't unstick, should we warn about this?
+                       break;
+       }
 }
 
 vector _Movetype_ClipVelocity(vector vel, vector norm, float f)  // SV_ClipVelocity
@@ -479,20 +501,32 @@ void _Movetype_PushEntityTrace(entity this, vector push)
        tracebox(this.origin, this.mins, this.maxs, end, type, this);
 }
 
-float _Movetype_PushEntity(entity this, vector push, bool failonstartsolid)  // SV_PushEntity
+bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool dolink)  // SV_PushEntity
 {
        _Movetype_PushEntityTrace(this, push);
 
        if(trace_startsolid && failonstartsolid)
-               return trace_fraction;
+       {
+               int oldtype = this.move_nomonsters;
+               this.move_nomonsters = MOVE_NOMONSTERS;
+               _Movetype_PushEntityTrace(this, push);
+               this.move_nomonsters = oldtype;
+               if(trace_startsolid)
+                       return true;
+       }
 
        this.origin = trace_endpos;
 
+       vector last_origin = this.origin;
+
+       if(dolink)
+               _Movetype_LinkEdict(this, true);
+
        if(trace_fraction < 1)
                if(this.solid >= SOLID_TRIGGER && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
                        _Movetype_Impact(this, trace_ent);
 
-       return trace_fraction;
+       return (this.origin == last_origin); // false if teleported by touch
 }
 
 
index 85912ee1c33f915ebdf59f907c616ef2f571c4f3..1eb2d95e47b8ab98c8ae6d96e4c24b6135f16b7a 100644 (file)
@@ -26,6 +26,8 @@ const int WATERLEVEL_SUBMERGED = 3;
 #define PHYS_JUMPSTEP(s)                    STAT(MOVEVARS_JUMPSTEP)
 #define PHYS_WALLFRICTION(s)                STAT(MOVEVARS_WALLFRICTION)
 
+#define PHYS_WALLCLIP(s)                                       STAT(MOVEVARS_WALLCLIP)
+
 #ifdef CSQC
 .float bouncestop;
 .float bouncefactor;
@@ -55,6 +57,8 @@ const int WATERLEVEL_SUBMERGED = 3;
 
 void set_movetype(entity this, int mt);
 
+.float pm_time;
+
 .float move_movetype;
 .float move_time;
 //.vector move_origin;
@@ -76,16 +80,22 @@ void set_movetype(entity this, int mt);
 .float move_suspendedinair;
 .float move_didgravity;
 
+// unsticking
+const int UNSTICK_FINE = 0;
+const int UNSTICK_FIXED = 1;
+const int UNSTICK_STUCK = 2;
+
 void _Movetype_WallFriction(entity this, vector stepnormal);
 int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight);
 void _Movetype_CheckVelocity(entity this);
 void _Movetype_CheckWaterTransition(entity ent);
+void _Movetype_CheckStuck(entity this);
 float _Movetype_CheckWater(entity ent);
 void _Movetype_LinkEdict_TouchAreaGrid(entity this);
 void _Movetype_LinkEdict(entity this, float touch_triggers);
 vector _Movetype_ClipVelocity(vector vel, vector norm, float f);
 void _Movetype_PushEntityTrace(entity this, vector push);
-float _Movetype_PushEntity(entity this, vector push, float failonstartsolid);
+bool _Movetype_PushEntity(entity this, vector push, float failonstartsolid, bool dolink);
 
 void Movetype_Physics_NoMatchTicrate(entity this, float movedt, bool isclient);
 void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy);
@@ -94,7 +104,7 @@ void Movetype_Physics_NoMatchServer(entity this);
 void _Movetype_LinkEdict(entity this, float touch_triggers);
 void _Movetype_LinkEdict_TouchAreaGrid(entity this);
 
-float _Movetype_UnstickEntity(entity this);
+int _Movetype_UnstickEntity(entity this);
 
 const int MAX_CLIP_PLANES = 5;
 
@@ -122,6 +132,8 @@ const int MOVETYPE_ANGLENOCLIP      = 1;
 const int MOVETYPE_ANGLECLIP        = 2;
 #endif
 
+const int MOVETYPE_QCPLAYER = 150; // QC-driven player physics, no think functions!
+
 const int FL_ONSLICK = BIT(20);
 
 const int MOVETYPE_FAKEPUSH         = 13;
index 71e7fa9d08c9032e14abe5bb9bdcd10824b84121..fc3de0859bba0a22e91c87afec51e63384d8fd59 100644 (file)
@@ -44,14 +44,14 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
        for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
        {
                vector move = this.velocity * movetime;
-               _Movetype_PushEntity(this, move, true);
+               _Movetype_PushEntity(this, move, true, false);
                if (wasfreed(this))
                        return;
 
                if (trace_startsolid)
                {
                        _Movetype_UnstickEntity(this);
-                       _Movetype_PushEntity(this, move, false);
+                       _Movetype_PushEntity(this, move, false, false);
                        if (wasfreed(this))
                                return;
                }
index c20e82e8342825a9282142d288281ceffea2583d..5c7ae9ee2a6e2797e7c2b4db9f09d8a42e1c3548 100644 (file)
@@ -8,7 +8,7 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
                return;
 
        if (GAMEPLAYFIX_UNSTICKPLAYERS(this))
-               _Movetype_UnstickEntity(this);
+               _Movetype_CheckStuck(this);
 
        bool applygravity = (!_Movetype_CheckWater(this) && this.move_movetype == MOVETYPE_WALK && !(this.flags & FL_WATERJUMP));
 
@@ -20,6 +20,14 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        vector start_origin = this.origin;
        vector start_velocity = this.velocity;
 
+       if(PHYS_WALLCLIP(this) && this.pm_time)
+       {
+               if(dt >= this.pm_time || (this.flags & FL_WATERJUMP))
+                       this.pm_time = 0;
+               else
+                       this.pm_time -= dt;
+       }
+
        int clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES(this) ? PHYS_STEPHEIGHT(this) : 0);
 
        if (GAMEPLAYFIX_DOWNTRACEONGROUND(this) && !(clip & 1))
@@ -45,6 +53,8 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        // if the move did not hit the ground at any point, we're not on ground
        if (!(clip & 1))
                UNSET_ONGROUND(this);
+       else if(PHYS_WALLCLIP(this) && !this.groundentity && (PHYS_WALLCLIP(this) == 2 || start_velocity.z < -200)) // don't do landing time if we were just going down a slope
+               this.pm_time = 0.25;
 
        _Movetype_CheckVelocity(this);
        _Movetype_LinkEdict(this, true);
@@ -90,10 +100,7 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 
                // move up
                vector upmove = '0 0 1' * PHYS_STEPHEIGHT(this);
-               _Movetype_PushEntity(this, upmove, true);
-               if(wasfreed(this))
-                       return;
-               if(trace_startsolid)
+               if(!_Movetype_PushEntity(this, upmove, true, true))
                {
                        // we got teleported when upstepping... must abort the move
                        return;
@@ -144,12 +151,9 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        }
 
        // move down
-       vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT(this) + start_velocity.z * dt);
-       _Movetype_PushEntity(this, downmove, true);
-       if(wasfreed(this))
-               return;
-
-       if(trace_startsolid)
+       vector downmove = '0 0 0';
+       downmove.z = -PHYS_STEPHEIGHT(this) + start_velocity.z * dt;
+       if(!_Movetype_PushEntity(this, downmove, true, true))
        {
                // we got teleported when downstepping... must abort the move
                return;
@@ -159,6 +163,13 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        {
                // this has been disabled so that you can't jump when you are stepping
                // up while already jumping (also known as the Quake2 double jump bug)
+               // LordHavoc: disabled this check so you can walk on monsters/players
+               //if (PRVM_serveredictfloat(ent, solid) == SOLID_BSP)
+               if(GAMEPLAYFIX_STEPDOWN(this) == 2)
+               {
+                       SET_ONGROUND(this);
+                       this.groundentity = trace_ent;
+               }
        }
        else
        {
index 572bee349f205ca81caac2d23d0ff6da1d839696..87d456c018fb4ad7b5f52243b73d9e13c4f7c569 100644 (file)
 // client side physics
 bool Physics_Valid(string thecvar)
 {
-       return autocvar_g_physics_clientselect && thecvar != "" && thecvar && thecvar != "default" && strhasword(autocvar_g_physics_clientselect_options, thecvar);
+       return thecvar != "" && thecvar && thecvar != "default" && strhasword(autocvar_g_physics_clientselect_options, thecvar);
 }
 
 float Physics_ClientOption(entity this, string option, float defaultval)
 {
+       if(!autocvar_g_physics_clientselect)
+               return defaultval;
+
        if(IS_REAL_CLIENT(this) && Physics_Valid(CS(this).cvar_cl_physics))
        {
                string s = strcat("g_physics_", CS(this).cvar_cl_physics, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
-       if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default && autocvar_g_physics_clientselect_default != "")
+       if(autocvar_g_physics_clientselect_default && autocvar_g_physics_clientselect_default != "" && autocvar_g_physics_clientselect_default != "default")
        {
+               // NOTE: not using Physics_Valid here, so the default can be forced to something normally unavailable
                string s = strcat("g_physics_", autocvar_g_physics_clientselect_default, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
@@ -45,12 +49,13 @@ void Physics_UpdateStats(entity this)
        STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
        STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
 
-       STAT(PL_MIN, this) = autocvar_sv_player_mins;
-       STAT(PL_MAX, this) = autocvar_sv_player_maxs;
-       STAT(PL_VIEW_OFS, this) = autocvar_sv_player_viewoffset;
-       STAT(PL_CROUCH_MIN, this) = autocvar_sv_player_crouch_mins;
-       STAT(PL_CROUCH_MAX, this) = autocvar_sv_player_crouch_maxs;
-       STAT(PL_CROUCH_VIEW_OFS, this) = autocvar_sv_player_crouch_viewoffset;
+       bool vq3compat = autocvar_sv_vq3compat && autocvar_sv_vq3compat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences
+       STAT(PL_MIN, this) = (vq3compat) ? '-15 -15 -24' : autocvar_sv_player_mins;
+       STAT(PL_MAX, this) = (vq3compat) ? '15 15 32' : autocvar_sv_player_maxs;
+       STAT(PL_VIEW_OFS, this) = (vq3compat) ? '0 0 26' : autocvar_sv_player_viewoffset;
+       STAT(PL_CROUCH_MIN, this) = (vq3compat) ? '-15 -15 -24' : autocvar_sv_player_crouch_mins;
+       STAT(PL_CROUCH_MAX, this) = (vq3compat) ? '15 15 16' : autocvar_sv_player_crouch_maxs;
+       STAT(PL_CROUCH_VIEW_OFS, this) = (vq3compat) ? '0 0 12' : autocvar_sv_player_crouch_viewoffset;
 
        // old stats
        // fix some new settings
index 478789dc2e784d51d708382273ac1a106f84a5da..29c028f03267500aed3f84994ff0b524e14c6c7c 100644 (file)
@@ -109,6 +109,7 @@ bool IsFlying(entity a);
 #define PHYS_INPUT_BUTTON_ZOOMSCRIPT(s)     PHYS_INPUT_BUTTON_BUTTON9(s)
 #define PHYS_INPUT_BUTTON_JETPACK(s)        PHYS_INPUT_BUTTON_BUTTON10(s)
 #define PHYS_INPUT_BUTTON_DODGE(s)                     PHYS_INPUT_BUTTON_BUTTON11(s)
+#define PHYS_INPUT_BUTTON_MINIGAME(s)          PHYS_INPUT_BUTTON_BUTTON14(s)
 
 #ifdef CSQC
 STATIC_INIT(PHYS_INPUT_BUTTON)
index 869af4da96533bb90f31f382b35ef0b3ac243a43..2c9bbcde805eb9770015c385877971563b872731 100644 (file)
@@ -258,6 +258,7 @@ void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that
 }
 
 // this... is a hack, a temporary one until we get a proper duel gametype
+// TODO: remove duel hack after servers have migrated to the proper duel gametype!
 string PlayerStats_GetGametype()
 {
        if(IS_GAMETYPE(DEATHMATCH) && autocvar_g_maxplayers == 2)
index 328486d35470cfc3594e437742d6428d2426a14c..fcd4d9a459983fc06a2e35fdb1cd5e8db753e8b9 100644 (file)
@@ -8,6 +8,7 @@ bool autocvar_bot_sound_monopoly;
 .entity realowner;
 bool sound_allowed(int to, entity e)
 {
+       if(!e) return true; // save on a few checks
        for ( ; ; )
        {
                if (e.classname == "body") e = e.enemy;
index 772dbccbd58d870137b69ab4143fc053e3b02e81..2e3a262a59e9662c2456e77a7277f2cb9bd9acef 100644 (file)
@@ -7,7 +7,7 @@ void PlayerState_attach(entity this)
 {
        this._ps = NEW(PlayerState, this);
 
-       Inventory_new(this);
+       Inventory_new(PS(this));
 }
 
 void PlayerState_detach(entity this)
@@ -18,11 +18,10 @@ void PlayerState_detach(entity this)
 
        if (ps.m_client != this) return;  // don't own state, spectator
        ps.ps_push(ps, this);
+    Inventory_delete(ps);
 
        FOREACH_CLIENT(PS(it) == ps, { PS(it) = NULL; });
        delete(ps);
-
-    Inventory_delete(this);
 }
 
 void GetCvars(entity this, entity store, int);
index 9b8f04041780fd55f707331540c74ab99b0e8e88..cf51ea66b3ebf7b24d86c16c89756347fa5bca0c 100644 (file)
@@ -301,6 +301,11 @@ bool autocvar_sv_slick_applygravity;
 #endif
 REGISTER_STAT(SLICK_APPLYGRAVITY, bool, autocvar_sv_slick_applygravity)
 
+#ifdef SVQC
+bool autocvar_sv_vq3compat;
+#endif
+REGISTER_STAT(VQ3COMPAT, bool, autocvar_sv_vq3compat)
+
 #ifdef SVQC
 #include "physics/movetypes/movetypes.qh"
 float warmup_limit;
@@ -360,6 +365,10 @@ REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
 REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
 REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
 REGISTER_STAT(MOVEVARS_SPECIALCOMMAND, bool)
+#ifdef SVQC
+int autocvar_sv_wallclip;
+#endif
+REGISTER_STAT(MOVEVARS_WALLCLIP, int, autocvar_sv_wallclip)
 
 
 #ifdef CSQC
index 0d4d2b92ab2c7221621379a5bf0b77b2d0730146..9675816cc5701d5ae103765e36c5823fffe3dbe9 100644 (file)
@@ -856,7 +856,7 @@ float Item_GiveTo(entity item, entity player)
                return 0;
 
        // crude hack to enforce switching weapons
-       if(g_cts && item.itemdef.instanceOfWeaponPickup)
+       if(g_cts && item.itemdef.instanceOfWeaponPickup && !CS(player).cvar_cl_cts_noautoswitch)
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1401,7 +1401,7 @@ int group_count = 1;
 
 void setItemGroup(entity this)
 {
-       if(!IS_SMALL(this.itemdef))
+       if(!IS_SMALL(this.itemdef) || Item_IsLoot(this))
                return;
 
        FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
index d3994fd8369436f20024506b1c71ba8880e149bf..37fb5f0d524d78bc7b8180d049213ab407fd72da 100644 (file)
@@ -731,18 +731,17 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
                return -5;
 
        // Cant touch this
+       if (GetResourceAmount(e_target, RESOURCE_HEALTH) <= 0)
+               return -6;
+       else if (STAT(FROZEN, e_target))
+               return -6;
+
+       // vehicle
        if(IS_VEHICLE(e_target))
        {
-               if (e_target.vehicle_health <= 0)
-                       return -6;
-
                if ((validate_flags & TFL_TARGETSELECT_VEHICLES) && !e_target.owner)
                        return -7;
        }
-       else if (GetResourceAmount(e_target, RESOURCE_HEALTH) <= 0)
-               return -6;
-       else if(STAT(FROZEN, e_target) > 0)
-               return -6;
 
        // player
        if (IS_CLIENT(e_target))
index 619d7a9072d9a1e127e8e4698caa0c99bd8fc6f2..a56e7de3833a6fe4d997cda5fa4081de332c95c8 100644 (file)
@@ -17,7 +17,7 @@ METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, .ent
             actor.tur_head = actor;
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
         }
-        fireBullet (actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN.m_id, 0);
+        fireBullet(actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN.m_id, EFFECT_BULLET);
         W_MachineGun_MuzzleFlash(actor, weaponentity);
         setattachment(actor.(weaponentity).muzzle_flash, actor.tur_head, "tag_fire");
     }
index d81b738ed4510b8565584752f76c50c785765471..bbe59aeac90aeca4980be687fb8257eb60ae545e 100644 (file)
@@ -16,7 +16,7 @@ METHOD(WalkerTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
         }
         sound (actor, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
-        fireBullet (actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN.m_id, 0);
+        fireBullet(actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN.m_id, EFFECT_BULLET);
         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
     }
 }
index 183302b3a1e0460c246c9c1c8357edfbace43c53..a7e9c42104d222e04d7b6d1d5884c6376eb7b060 100644 (file)
@@ -1298,6 +1298,7 @@ float matchacl(string acl, string str)
                if(s == t)
                {
                        r = d;
+                       break; // if we found a killing case, apply it! other settings may be allowed in the future, but this one is caught
                }
        }
        return r;
index 716dfe8d0c130225041502345a182873aa7c111f..be8d468fa78dca4048312bc69df8fc4c52fe6c6f 100644 (file)
@@ -385,7 +385,7 @@ bool vehicle_addplayerslot( entity _owner,
 
 vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
                                                 float _pichlimit_min, float _pichlimit_max,
-                                                float _rotlimit_min, float _rotlimit_max, float _aimspeed)
+                                                float _rotlimit_min, float _rotlimit_max, float _aimspeed, float dt)
 {
        vector vtmp, vtag;
        float ftmp;
@@ -393,7 +393,7 @@ vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string
        vtmp = vectoangles(normalize(_target - vtag));
        vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles;
        vtmp = AnglesTransform_Normalize(vtmp, true);
-       ftmp = _aimspeed * frametime;
+       ftmp = _aimspeed * dt;
        vtmp_y = bound(-ftmp, vtmp_y, ftmp);
        vtmp_x = bound(-ftmp, vtmp_x, ftmp);
        _turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max);
@@ -587,7 +587,7 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma
        if(timer + rpause < time)
        {
                if(_healthscale)
-                       regen = regen * (this.vehicle_health / this.max_health);
+                       regen = regen * (GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health);
 
                this.(regen_field) = min(this.(regen_field) + regen * delta_time, field_max);
 
@@ -596,6 +596,23 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma
        }
 }
 
+void vehicles_regen_resource(entity this, float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale, int resource)
+{
+       float resource_amount = GetResourceAmount(this, resource);
+
+       if(resource_amount < field_max)
+       if(timer + rpause < time)
+       {
+               if(_healthscale)
+                       regen = regen * (resource_amount / this.max_health);
+
+               SetResourceAmount(this, resource, min(resource_amount + regen * delta_time, field_max));
+
+               if(this.owner)
+                       this.owner.(regen_field) = (GetResourceAmount(this, resource) / field_max) * 100;
+       }
+}
+
 void shieldhit_think(entity this)
 {
        this.alpha -= 0.1;
@@ -613,7 +630,7 @@ void shieldhit_think(entity this)
 
 void vehicles_painframe(entity this)
 {
-       int myhealth = ((this.owner) ? this.owner.vehicle_health : ((this.vehicle_health / this.max_health) * 100));
+       int myhealth = ((this.owner) ? this.owner.vehicle_health : ((GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health) * 100));
 
        if(myhealth <= 50)
        if(this.pain_frame < time)
@@ -684,7 +701,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
 
                if(this.vehicle_shield < 0)
                {
-                       this.vehicle_health -= fabs(this.vehicle_shield);
+                       TakeResource(this, RESOURCE_HEALTH, fabs(this.vehicle_shield));
                        this.vehicle_shieldent.colormod = '2 0 0';
                        this.vehicle_shield = 0;
                        this.vehicle_shieldent.alpha = 0.75;
@@ -699,7 +716,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
        }
        else
        {
-               this.vehicle_health -= damage;
+               TakeResource(this, RESOURCE_HEALTH, damage);
 
                if(sound_allowed(MSG_BROADCAST, attacker))
                        spamsound (this, CH_PAIN, SND_ONS_HIT2, VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
@@ -710,7 +727,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
        else
                this.velocity += force;
 
-       if(this.vehicle_health <= 0)
+       if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0)
        {
                if(this.owner)
                        if(this.vehicle_flags & VHF_DEATHEJECT)
@@ -730,14 +747,12 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
 bool vehicles_heal(entity targ, entity inflictor, float amount, float limit)
 {
        float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health);
-       //if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
-       if(targ.vehicle_health <= 0 || targ.vehicle_health >= true_limit)
+       if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
                return false;
 
-       targ.vehicle_health = min(targ.vehicle_health + amount, true_limit);
-       //GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
-       //if(targ.owner)
-               //targ.owner.vehicle_health = (targ.vehicle_health / targ.max_health) * 100;
+       GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
+       if(targ.owner)
+               targ.owner.vehicle_health = (GetResourceAmount(targ, RESOURCE_HEALTH) / targ.max_health) * 100;
        return true;
 }
 
@@ -951,7 +966,7 @@ bool vehicle_impulse(entity this, int imp)
 
 void vehicles_enter(entity pl, entity veh)
 {
-   // Remove this when bots know how to use vehicles
+       // Remove this when bots know how to use vehicles
        if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
                return;
 
index 0cc9da56ea11a57779850fc85f1bdd53ca0864e1..a1f23c1dfcc1b95522a3300296737dc4a927b026 100644 (file)
@@ -45,7 +45,7 @@ float autocvar_g_vehicles_weapon_damagerate = 2;
 .entity gunner1;
 .entity gunner2;
 
-.float vehicle_health = _STAT(VEHICLESTAT_HEALTH);  /// If ent is player this is 0..100 indicating precentage of health left on vehicle. If ent is vehicle, this is the real health value.
+.float vehicle_health = _STAT(VEHICLESTAT_HEALTH);  /// If ent is player this is 0..100 indicating precentage of health left on vehicle. Vehicle's value is the health resource
 .float vehicle_energy = _STAT(VEHICLESTAT_ENERGY);  /// If ent is player this is 0..100 indicating precentage of energy left on vehicle. If ent is vehicle, this is the real energy value.
 .float vehicle_shield = _STAT(VEHICLESTAT_SHIELD);  /// If ent is player this is 0..100 indicating precentage of shield left on vehicle. If ent is vehicle, this is the real shield value.
 
@@ -99,6 +99,9 @@ float vehicles_exit_running;
 #define VEHICLE_UPDATE_PLAYER(ply,vehi,fld,vhname) \
        ply.vehicle_##fld = (vehi.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
 
+#define VEHICLE_UPDATE_PLAYER_RESOURCE(ply,vehi,fld,vhname,res) \
+       ply.vehicle_##fld = (GetResourceAmount(vehi, res) / autocvar_g_vehicle_##vhname##_##fld) * 100
+
 .float vehicle_enter_delay; // prevent players jumping to and from vehicles instantly
 
 void vehicles_exit(entity vehic, int eject);
index c340d947035617492da6d224bbede286baf8e7be..84f5e144bfa6cb257ef272a97822c99fd8eb2aa5 100644 (file)
@@ -33,9 +33,9 @@ float autocvar_g_vehicle_bumblebee_cannon_ammo = 100;
 float autocvar_g_vehicle_bumblebee_cannon_ammo_regen = 100;
 float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause = 1;
 
-float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
+float autocvar_g_vehicle_bumblebee_cannon_lock = 1;
 
-float autocvar_g_vehicle_bumblebee_cannon_turnspeed = 160;
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed = 260;
 float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down = 60;
 float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up = 60;
 float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in = 20;
@@ -105,20 +105,28 @@ bool bumblebee_gunner_frame(entity this, float dt)
 
        if(autocvar_g_vehicle_bumblebee_cannon_lock)
        {
-               if(gun.lock_time < time)
+               if(gun.lock_time < time || IS_DEAD(gun.enemy) || STAT(FROZEN, gun.enemy))
                        gun.enemy = NULL;
 
                if(trace_ent)
-                       if(trace_ent.move_movetype)
-                               if(trace_ent.takedamage)
-                                       if(!IS_DEAD(trace_ent) && !STAT(FROZEN, trace_ent))
-                                       {
-                                               if(DIFF_TEAM(trace_ent, this))
-                                               {
-                                                       gun.enemy = trace_ent;
-                                                       gun.lock_time = time + 5;
-                                               }
-                                       }
+               if(trace_ent.move_movetype)
+               if(trace_ent.takedamage)
+               if(!IS_DEAD(trace_ent) && !STAT(FROZEN, trace_ent))
+               {
+                       if(teamplay)
+                       {
+                               if(DIFF_TEAM(trace_ent, this))
+                               {
+                                       gun.enemy = trace_ent;
+                                       gun.lock_time = time + 2.5;
+                               }
+                       }
+                       else
+                       {
+                               gun.enemy = trace_ent;
+                               gun.lock_time = time + 0.5;
+                       }
+               }
        }
 
        if(gun.enemy)
@@ -141,13 +149,13 @@ bool bumblebee_gunner_frame(entity this, float dt)
                UpdateAuxiliaryXhair(this, ad, '1 0 1', 1);
                vehicle_aimturret(vehic, trace_endpos, gun, "fire",
                                                  autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
-                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed, dt);
 
        }
        else
                vehicle_aimturret(vehic, _ct, gun, "fire",
                                                  autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
-                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed, dt);
 
        if(!forbidWeaponUse(this))
        if(PHYS_INPUT_BUTTON_ATCK(this))
@@ -160,7 +168,7 @@ bool bumblebee_gunner_frame(entity this, float dt)
                                gun.attack_finished_single[0] = time + autocvar_g_vehicle_bumblebee_cannon_refire;
                        }
 
-       VEHICLE_UPDATE_PLAYER(this, vehic, health, bumblebee);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, bumblebee, RESOURCE_HEALTH);
 
        if(vehic.vehicle_flags & VHF_HASSHIELD)
                VEHICLE_UPDATE_PLAYER(this, vehic, shield, bumblebee);
@@ -389,7 +397,7 @@ void bumblebee_regen(entity this, float dt)
                vehicles_regen(this, this.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, dt, true);
 
        if(this.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, dt, false);
+               vehicles_regen_resource(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, dt, false, RESOURCE_HEALTH);
 
        if(this.vehicle_flags  & VHF_ENERGYREGEN)
                vehicles_regen(this, this.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, dt, false);
@@ -521,7 +529,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
 
        vang = vehicle_aimturret(vehic, trace_endpos, vehic.gun3, "fire",
                                          autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
-                                         autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
+                                         autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed, dt);
 
        if(!forbidWeaponUse(this))
        if((PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * PHYS_INPUT_FRAMETIME || autocvar_g_vehicle_bumblebee_raygun == 0))
@@ -555,7 +563,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
 
                                                if(IS_VEHICLE(trace_ent))
                                                {
-                                                       if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
+                                                       if(autocvar_g_vehicle_bumblebee_healgun_sps && GetResourceAmount(trace_ent, RESOURCE_HEALTH) <= trace_ent.max_health)
                                                                trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * dt, trace_ent.tur_head.max_health);
                                                }
                                                else if(IS_CLIENT(trace_ent))
@@ -584,7 +592,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
        }
        */
 
-       VEHICLE_UPDATE_PLAYER(this, vehic, health, bumblebee);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, bumblebee, RESOURCE_HEALTH);
        VEHICLE_UPDATE_PLAYER(this, vehic, energy, bumblebee);
 
        this.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
@@ -879,7 +887,7 @@ METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh, entity instance))
     if(!autocvar_g_vehicle_bumblebee_swim)
        instance.dphitcontentsmask |= DPCONTENTS_LIQUIDSMASK;
 
-    instance.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_bumblebee_health);
     instance.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
     instance.solid = SOLID_BBOX;
     set_movetype(instance, MOVETYPE_TOSS);
@@ -906,8 +914,8 @@ METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh, entity instance))
 
     instance.vehicle_exit = bumblebee_exit;
     instance.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
-    instance.vehicle_health = autocvar_g_vehicle_bumblebee_health;
-    instance.max_health = instance.vehicle_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_bumblebee_health);
+    instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
     instance.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
 }
 
@@ -930,7 +938,7 @@ METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh))
     float hudAlpha = autocvar_hud_panel_fg_alpha;
     float blinkValue = 0.55 + sin(time * 7) * 0.45;
     vector tmpPos  = '0 0 0';
-    vector tmpSize = '1 1 1' * hud_fontsize;
+    vector tmpSize = hud_fontsize;
     tmpPos.x = vehicleHud_Pos.x + vehicleHud_Size.x * (520/768);
 
     if(!AuxiliaryXhair[1].draw2d)
index e9c5bf41d002167c5f3b74b17d99de8fad0ad60a..f6909fb42a2100527a5ec668d34fb8010b1d1a87 100644 (file)
@@ -8,7 +8,7 @@ float autocvar_g_vehicle_bumblebee_cannon_damage = 60;
 float autocvar_g_vehicle_bumblebee_cannon_radius = 225;
 float autocvar_g_vehicle_bumblebee_cannon_refire = 0.2;
 float autocvar_g_vehicle_bumblebee_cannon_speed = 20000;
-float autocvar_g_vehicle_bumblebee_cannon_spread = 0.02;
+float autocvar_g_vehicle_bumblebee_cannon_spread = 0;
 float autocvar_g_vehicle_bumblebee_cannon_force = -35;
 #endif
 
index 18e13bcbbe68d3f23bc558dad7b0e0f9427c4d2b..c7f7af8ac6efa82854bca37985be91fb85afabe2 100644 (file)
@@ -359,12 +359,12 @@ bool racer_frame(entity this, float dt)
                vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, dt, true);
 
        if(vehic.vehicle_flags & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, dt, false);
+               vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, dt, false, RESOURCE_HEALTH);
 
        if(vehic.vehicle_flags & VHF_ENERGYREGEN)
                vehicles_regen(vehic, vehic.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, dt, false);
 
-       VEHICLE_UPDATE_PLAYER(player, vehic, health, racer);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(player, vehic, health, racer, RESOURCE_HEALTH);
        VEHICLE_UPDATE_PLAYER(player, vehic, energy, racer);
 
        if(vehic.vehicle_flags & VHF_HASSHIELD)
@@ -514,7 +514,7 @@ METHOD(Racer, vr_enter, void(Racer thisveh, entity instance))
 {
 #ifdef SVQC
     set_movetype(instance, MOVETYPE_BOUNCE);
-    instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_racer_health)  * 100;
+    instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_racer_health)  * 100;
     instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_racer_shield)  * 100;
 
     if(instance.owner.flagcarried)
@@ -544,7 +544,7 @@ METHOD(Racer, vr_spawn, void(Racer thisveh, entity instance))
 
     setthink(instance, racer_think);
     instance.nextthink   = time;
-    instance.vehicle_health = autocvar_g_vehicle_racer_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
     instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
 
     set_movetype(instance, MOVETYPE_TOSS);
@@ -557,7 +557,7 @@ METHOD(Racer, vr_spawn, void(Racer thisveh, entity instance))
     instance.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
     instance.bouncestop = autocvar_g_vehicle_racer_bouncestop;
     instance.damageforcescale = 0.5;
-    instance.vehicle_health = autocvar_g_vehicle_racer_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
     instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
 #endif
 }
@@ -625,9 +625,9 @@ METHOD(Racer, vr_setup, void(Racer thisveh, entity instance))
         instance.vehicle_flags |= VHF_HEALTHREGEN;
 
     instance.respawntime = autocvar_g_vehicle_racer_respawntime;
-    instance.vehicle_health = autocvar_g_vehicle_racer_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
     instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
-    instance.max_health = instance.vehicle_health;
+    instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
 #endif
 
 #ifdef CSQC
index f44dcc578464e7a2e485c5da437a286bd721bc87..0150ee98f930fe673f2897d0592540c87981ff3e 100644 (file)
@@ -343,11 +343,11 @@ bool raptor_frame(entity this, float dt)
 
        vehicle_aimturret(vehic, trace_endpos, vehic.gun1, "fire1",
                                                  autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
-                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
+                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed, dt);
 
        vehicle_aimturret(vehic, trace_endpos, vehic.gun2, "fire1",
                                                  autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
-                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
+                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed, dt);
 
        /*
        ad = ad * 0.5;
@@ -369,7 +369,7 @@ bool raptor_frame(entity this, float dt)
                vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
+               vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false, RESOURCE_HEALTH);
 
        if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
                vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
@@ -427,7 +427,7 @@ bool raptor_frame(entity this, float dt)
        }
 
 
-       VEHICLE_UPDATE_PLAYER(this, vehic, health, raptor);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, raptor, RESOURCE_HEALTH);
        VEHICLE_UPDATE_PLAYER(this, vehic, energy, raptor);
        if(vehic.vehicle_flags & VHF_HASSHIELD)
                VEHICLE_UPDATE_PLAYER(this, vehic, shield, raptor);
@@ -471,7 +471,7 @@ bool raptor_takeoff(entity this, float dt)
                vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
+               vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false, RESOURCE_HEALTH);
 
        if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
                vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
@@ -481,7 +481,7 @@ bool raptor_takeoff(entity this, float dt)
        this.vehicle_reload2 = bound(0, vehic.bomb1.alpha * 100, 100);
        this.vehicle_ammo2 = (this.vehicle_reload2 == 100) ? 100 : 0;
 
-       VEHICLE_UPDATE_PLAYER(this, vehic, health, raptor);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, raptor, RESOURCE_HEALTH);
        VEHICLE_UPDATE_PLAYER(this, vehic, energy, raptor);
        if(vehic.vehicle_flags & VHF_HASSHIELD)
                VEHICLE_UPDATE_PLAYER(this, vehic, shield, raptor);
@@ -594,7 +594,7 @@ METHOD(Raptor, vr_enter, void(Raptor thisveh, entity instance))
     instance.owner.PlayerPhysplug = raptor_takeoff;
     set_movetype(instance, MOVETYPE_BOUNCEMISSILE);
     instance.solid               = SOLID_SLIDEBOX;
-    instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
+    instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_raptor_health) * 100;
     instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
     instance.velocity = '0 0 1'; // nudge upwards so takeoff sequence can work
     instance.tur_head.exteriormodeltoclient = instance.owner;
@@ -701,7 +701,7 @@ METHOD(Raptor, vr_spawn, void(Raptor thisveh, entity instance))
     }
 
     instance.frame               = 0;
-    instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
     instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
     set_movetype(instance, MOVETYPE_TOSS);
     instance.solid               = SOLID_SLIDEBOX;
@@ -720,7 +720,7 @@ METHOD(Raptor, vr_spawn, void(Raptor thisveh, entity instance))
     instance.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
     instance.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
     instance.damageforcescale = 0.25;
-    instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
     instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
 }
 METHOD(Raptor, vr_setup, void(Raptor thisveh, entity instance))
@@ -739,9 +739,9 @@ METHOD(Raptor, vr_setup, void(Raptor thisveh, entity instance))
 
     instance.vehicle_exit = raptor_exit;
     instance.respawntime = autocvar_g_vehicle_raptor_respawntime;
-    instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
     instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
-    instance.max_health = instance.vehicle_health;
+    instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
 
     if(!autocvar_g_vehicle_raptor_swim)
        instance.dphitcontentsmask |= DPCONTENTS_LIQUIDSMASK;
index 09d0eb2af9175c6012b0a903677483e2e7c6d0cc..323b025e0ebb5769d434004073a1fb04598176c5 100644 (file)
@@ -264,7 +264,7 @@ bool spiderbot_frame(entity this, float dt)
 
                        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                        fireBullet(this, weaponentity, v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
-                               autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN.m_id, 0);
+                               autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN.m_id, EFFECT_BULLET);
 
                        sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
                        //trailparticles(this, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
@@ -294,7 +294,7 @@ bool spiderbot_frame(entity this, float dt)
                vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, dt, false);
+               vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, dt, false, RESOURCE_HEALTH);
 
        PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
        //this.vehicle_ammo2 = vehic.tur_head.frame;
@@ -309,7 +309,7 @@ bool spiderbot_frame(entity this, float dt)
        this.oldorigin = this.origin; // negate fall damage
        this.velocity = vehic.velocity;
 
-       VEHICLE_UPDATE_PLAYER(this, vehic, health, spiderbot);
+       VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, spiderbot, RESOURCE_HEALTH);
 
        if(vehic.vehicle_flags & VHF_HASSHIELD)
                VEHICLE_UPDATE_PLAYER(this, vehic, shield, spiderbot);
@@ -524,7 +524,7 @@ METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh, entity instance))
     STAT(VEHICLESTAT_W2MODE, instance) = SBRM_GUIDE;
     set_movetype(instance, MOVETYPE_WALK);
     CSQCVehicleSetup(instance.owner, 0);
-    instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
+    instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_spiderbot_health) * 100;
     instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
 
     if(instance.owner.flagcarried)
@@ -582,7 +582,7 @@ METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh, entity instance))
     setorigin(instance, instance.pos1 + '0 0 128');
     instance.angles = instance.pos2;
     instance.damageforcescale = 0.03;
-    instance.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_spiderbot_health);
     instance.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
 
     instance.PlayerPhysplug = spiderbot_frame;
@@ -599,9 +599,9 @@ METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh, entity instance))
         instance.vehicle_flags |= VHF_HEALTHREGEN;
 
     instance.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
-    instance.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+    SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_spiderbot_health);
     instance.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
-    instance.max_health = instance.vehicle_health;
+    instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
     instance.pushable = true; // spiderbot can use jumppads
 }
 
index 9b4c0b46814308dfb037375345a6100c14d444f4..9a32b4277839b32ddfdcb8368747615387556f06 100644 (file)
@@ -130,7 +130,7 @@ REGISTER_WEAPON(Null, NEW(Weapon));
 Weapon Weapons_fromstr(string s)
 {
     FOREACH(Weapons, it != WEP_Null && it.netname == s, return it);
-    return NULL;
+    return WEP_Null;
 }
 
 
index d2443f1670d360767cbc6721f6a2722d2764997c..b53e25fde9c95cbdaddc1b987fd30fa16f8f8d16 100644 (file)
@@ -25,7 +25,10 @@ float W_Config_Queue_Compare(int root, int child, entity pass)
 void Dump_Weapon_Settings()
 {
        int totalweapons = 0, totalsettings = 0;
+       int wepcount = 1;
        FOREACH(Weapons, it != WEP_Null, {
+               if((it.spawnflags & WEP_FLAG_HIDDEN) && (it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_NORMAL))
+                       continue; // never include the attacks
                // step 1: clear the queue
                WEP_CONFIG_COUNT = 0;
                for (int x = 0; x <= MAX_CONFIG_SETTINGS; ++x)
@@ -40,7 +43,7 @@ void Dump_Weapon_Settings()
                // step 4: write queue
                WEP_CONFIG_WRITETOFILE(sprintf(
                        "// {{{ #%d: %s%s\n",
-                       i,
+                       wepcount,
                        it.m_name,
                        ((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
                ));
@@ -51,6 +54,7 @@ void Dump_Weapon_Settings()
                LOG_INFOF("#%d: %s: %d settings...", i, it.m_name, WEP_CONFIG_COUNT);
                totalweapons += 1;
                totalsettings += WEP_CONFIG_COUNT;
+               wepcount += 1;
        });
 
        // clear queue now that we're finished
index a3f2336a9487b275a8a130a031295c462072d77b..cdf5748e678bf62388ffd85c793cd9194f8656d1 100644 (file)
@@ -162,9 +162,9 @@ CLASS(WeaponPickup, Pickup)
     METHOD(WeaponPickup, giveTo, bool(entity this, entity item, entity player))
     {
         bool b = Item_GiveTo(item, player);
-        if (b) {
-            LOG_TRACEF("entity %i picked up %s", player, this.m_name);
-        }
+        //if (b) {
+            //LOG_TRACEF("entity %i picked up %s", player, this.m_name);
+        //}
         return b;
     }
 #endif
index e78e10a3641d772427a9c053170db903a70e2fb0..ef4e3eb7d7709e19b709396f0a30cf0d234820e4 100644 (file)
@@ -236,8 +236,8 @@ void W_Arc_Beam_Think(entity this)
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(own, weaponentity);
-                       own.(weaponentity).arc_BUTTON_ATCK_prev = false; // hax
                }
+               own.(weaponentity).arc_BUTTON_ATCK_prev = false; // allow switching weapons
                delete(this);
                return;
        }
@@ -265,14 +265,14 @@ void W_Arc_Beam_Think(entity this)
 
        W_SetupShot_Range(
                own,
-               weaponentity, // TODO
+               weaponentity,
                true,
                0,
                SND_Null,
                0,
                WEP_CVAR(arc, beam_damage) * coefficient,
                WEP_CVAR(arc, beam_range),
-               WEP_ARC.m_id
+               thiswep.m_id
        );
 
        // After teleport, "lock" the beam until the teleport is confirmed.
@@ -322,7 +322,10 @@ void W_Arc_Beam_Think(entity this)
                                (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
                                min(WEP_CVAR(arc, beam_maxangle) / angle, 1)
                        );
-                       this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
+                       if(vdist(this.beam_dir - w_shotdir, <, 0.01))
+                               this.beam_dir = w_shotdir;
+                       else
+                               this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
                }
                else
                {
@@ -332,7 +335,10 @@ void W_Arc_Beam_Think(entity this)
                                (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
                                1
                        );
-                       this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
+                       if(vdist(this.beam_dir - w_shotdir, <, 0.01))
+                               this.beam_dir = w_shotdir;
+                       else
+                               this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
                }
 
                // network information: beam direction
@@ -467,7 +473,7 @@ void W_Arc_Beam_Think(entity this)
                                {
                                        accuracy_add(
                                                own,
-                                               WEP_ARC.m_id,
+                                               WEP_ARC,
                                                0,
                                                rootdamage * coefficient * falloff
                                        );
@@ -533,17 +539,33 @@ void W_Arc_Beam(float burst, entity actor, .entity weaponentity)
 
        getthink(beam)(beam);
 }
-void Arc_Smoke(entity actor, .entity weaponentity)
+void W_Arc_Attack(Weapon thiswep, entity actor, .entity weaponentity, int fire)
+{
+       if(!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
+       {
+               w_ready(thiswep, actor, weaponentity, fire);
+               return;
+       }
+
+       // attack handled by the beam itself, this is just a loop to keep the attack happening!
+
+       // NOTE: arc doesn't use a refire
+       //ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(arc, refire) * W_WeaponRateFactor(actor);
+       actor.(weaponentity).wframe = WFRAME_FIRE1;
+       weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), W_Arc_Attack);
+}
+void Arc_Smoke(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
+       // TODO: spamming this without checking any refires is asking for trouble!
        makevectors(actor.v_angle);
-       W_SetupShot_Range(actor,weaponentity,true,0,SND_Null,0,0,0,WEP_ARC.m_id); // TODO: probably doesn't need deathtype, since this is just a prefire effect
+       W_SetupShot_Range(actor,weaponentity,false,0,SND_Null,0,0,0,thiswep.m_id); // TODO: probably doesn't need deathtype, since this is just a prefire effect
 
        vector smoke_origin = w_shotorg + actor.velocity*frametime;
        if ( actor.arc_overheat > time )
        {
                if ( random() < actor.(weaponentity).arc_heat_percent )
                        Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1 );
-               if ( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) )
+               if ( (fire & 1) || (fire & 2) )
                {
                        Send_Effect(EFFECT_ARC_OVERHEAT_FIRE, smoke_origin, w_shotdir, 1 );
                        if ( !actor.arc_smoke_sound )
@@ -562,7 +584,7 @@ void Arc_Smoke(entity actor, .entity weaponentity)
        }
 
        if (  actor.arc_smoke_sound && ( actor.arc_overheat <= time ||
-               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || actor.(weaponentity).m_switchweapon != WEP_ARC )
+               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || actor.(weaponentity).m_switchweapon != thiswep )
        {
                actor.arc_smoke_sound = 0;
                sound(actor, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
@@ -597,14 +619,14 @@ METHOD(Arc, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     Arc_Player_SetHeat(actor, weaponentity);
-    Arc_Smoke(actor, weaponentity);
+    Arc_Smoke(thiswep, actor, weaponentity, fire);
 
     bool beam_fire2 = ((fire & 2) && !WEP_CVAR(arc, bolt));
 
     if (time >= actor.arc_overheat)
     if ((fire & 1) || beam_fire2 || actor.(weaponentity).arc_beam.beam_bursting)
     {
-
+       #if 0
         if(actor.(weaponentity).arc_BUTTON_ATCK_prev)
         {
             #if 0
@@ -614,6 +636,7 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
             #endif
                 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
         }
+        #endif
 
         if((!actor.(weaponentity).arc_beam) || wasfreed(actor.(weaponentity).arc_beam))
         {
@@ -623,7 +646,8 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
 
                 if(!actor.(weaponentity).arc_BUTTON_ATCK_prev)
                 {
-                    weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                       actor.(weaponentity).wframe = WFRAME_FIRE1;
+                    weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), W_Arc_Attack);
                     actor.(weaponentity).arc_BUTTON_ATCK_prev = true;
                 }
             }
@@ -642,10 +666,9 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
 
     if(actor.(weaponentity).arc_BUTTON_ATCK_prev)
     {
-       int slot = weaponslot(weaponentity);
         sound(actor, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-        ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(actor);
+        ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(actor);
     }
     actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
 
index 5a41666bdb74ba1a58b4a09eae9adf341e2a7d8a..064668ca6cafa443c2260cf00c11d8e9ce51c643 100644 (file)
@@ -297,7 +297,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        if(WEP_CVAR_PRI(crylink, joinexplode))
                maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
 
-       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg, WEP_CRYLINK.m_id);
+       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg, thiswep.m_id);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -336,7 +336,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
                set_movetype(proj, MOVETYPE_BOUNCEMISSILE);
                PROJECTILE_MAKETRIGGER(proj);
-               proj.projectiledeathtype = WEP_CRYLINK.m_id;
+               proj.projectiledeathtype = thiswep.m_id;
                //proj.gravity = 0.001;
 
                setorigin(proj, w_shotorg);
@@ -409,7 +409,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        if(WEP_CVAR_SEC(crylink, joinexplode))
                maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
 
-       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg, WEP_CRYLINK.m_id | HITTYPE_SECONDARY);
+       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg, thiswep.m_id | HITTYPE_SECONDARY);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -448,7 +448,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 
                set_movetype(proj, MOVETYPE_BOUNCEMISSILE);
                PROJECTILE_MAKETRIGGER(proj);
-               proj.projectiledeathtype = WEP_CRYLINK.m_id | HITTYPE_SECONDARY;
+               proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
                //proj.gravity = 0.001;
 
                setorigin(proj, w_shotorg);
@@ -571,7 +571,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
             {
                 // ran out of ammo!
-                actor.cnt = WEP_CRYLINK.m_id;
+                actor.cnt = thiswep.m_id;
                 actor.(weaponentity).m_switchweapon = w_getbestweapon(actor, weaponentity);
             }
         }
@@ -584,7 +584,7 @@ METHOD(Crylink, wr_checkammo1, bool(entity thiswep, entity actor, .entity weapon
         return true;
 
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(crylink, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
     return ammo_amount;
 }
 METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
@@ -594,7 +594,7 @@ METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor, .entity weapon
         return true;
 
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(crylink, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
     return ammo_amount;
 }
 METHOD(Crylink, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index ab97e3d7f0b6c5c16ba538092b3ece2bd2aeb4df..f8539b14c36b7eeb800830de893c625581e06337 100644 (file)
@@ -49,9 +49,8 @@ void W_Devastator_Explode(entity this, entity directhitentity)
                if(GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
                if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       this.realowner.cnt = WEP_DEVASTATOR.m_id;
-                       int slot = weaponslot(weaponentity);
-                       ATTACK_FINISHED(this.realowner, slot) = time;
+                       this.realowner.cnt = thiswep.m_id;
+                       ATTACK_FINISHED(this.realowner, weaponentity) = time;
                        this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner, weaponentity);
                }
        }
@@ -143,9 +142,8 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
                if(GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
                if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       this.realowner.cnt = WEP_DEVASTATOR.m_id;
-                       int slot = weaponslot(weaponentity);
-                       ATTACK_FINISHED(this.realowner, slot) = time;
+                       this.realowner.cnt = thiswep.m_id;
+                       ATTACK_FINISHED(this.realowner, weaponentity) = time;
                        this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner, weaponentity);
                }
        }
@@ -306,7 +304,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity, int
 {
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(devastator, ammo), weaponentity);
 
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage), WEP_DEVASTATOR.m_id);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage), thiswep.m_id);
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
@@ -331,7 +329,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity, int
 
        set_movetype(missile, MOVETYPE_FLY);
        PROJECTILE_MAKETRIGGER(missile);
-       missile.projectiledeathtype = WEP_DEVASTATOR.m_id;
+       missile.projectiledeathtype = thiswep.m_id;
        setsize(missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
 
        setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
@@ -464,7 +462,7 @@ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponen
             actor.(weaponentity).rl_release = 1;
 
         if(fire & 2)
-        if(actor.(weaponentity).m_switchweapon == WEP_DEVASTATOR)
+        if(actor.(weaponentity).m_switchweapon == thiswep)
         {
             bool rockfound = false;
             IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket",
@@ -488,7 +486,7 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor, .entity wea
 {
     #if 0
     // don't switch while guiding a missile
-    if(ATTACK_FINISHED(actor, slot) <= time || PS(actor).m_weapon != WEP_DEVASTATOR)
+    if(ATTACK_FINISHED(actor, weaponentity) <= time || PS(actor).m_weapon != WEP_DEVASTATOR)
     {
         ammo_amount = false;
         if(WEP_CVAR(devastator, reload_ammo))
@@ -516,7 +514,7 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor, .entity wea
     }
     #else
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(devastator, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(devastator, ammo);
     return ammo_amount;
     #endif
 }
index 89738289f2b84b0205020e9ae0b4f33eeca05afb..e22b5e941270b7f2757b407675b6db7c6ead44a5 100644 (file)
@@ -205,7 +205,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
                SND_ELECTRO_FIRE,
                CH_WEAPON_A,
                WEP_CVAR_PRI(electro, damage),
-               WEP_ELECTRO.m_id
+               thiswep.m_id
        );
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -219,7 +219,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        proj.nextthink = time;
        proj.ltime = time + WEP_CVAR_PRI(electro, lifetime);
        PROJECTILE_MAKETRIGGER(proj);
-       proj.projectiledeathtype = WEP_ELECTRO.m_id;
+       proj.projectiledeathtype = thiswep.m_id;
        proj.weaponentity_fld = weaponentity;
        setorigin(proj, w_shotorg);
 
@@ -279,14 +279,14 @@ void W_Electro_Orb_Stick(entity this, entity to)
        delete(this);
 
        if(to)
-               SetMovetypeFollow(this, to);
+               SetMovetypeFollow(newproj, to);
 }
 
 void W_Electro_Orb_Touch(entity this, entity toucher)
 {
        PROJECTILE_TOUCH(this, toucher);
-       if(toucher.takedamage == DAMAGE_AIM)
-               { if(WEP_CVAR_SEC(electro, touchexplode)) { W_Electro_Explode(this, toucher); } }
+       if(toucher.takedamage == DAMAGE_AIM && WEP_CVAR_SEC(electro, touchexplode))
+               { W_Electro_Explode(this, toucher); }
        else if(toucher.owner != this.owner && toucher.classname != this.classname) // don't stick to player's other projectiles!
        {
                //UpdateCSQCProjectile(this);
@@ -354,7 +354,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
                SND_ELECTRO_FIRE2,
                CH_WEAPON_A,
                WEP_CVAR_SEC(electro, damage),
-               WEP_ELECTRO.m_id | HITTYPE_SECONDARY
+               thiswep.m_id | HITTYPE_SECONDARY
        );
 
        w_shotdir = v_forward; // no TrueAim for grenades please
@@ -369,7 +369,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
        proj.bot_dodgerating = WEP_CVAR_SEC(electro, damage);
        proj.nextthink = time + WEP_CVAR_SEC(electro, lifetime);
        PROJECTILE_MAKETRIGGER(proj);
-       proj.projectiledeathtype = WEP_ELECTRO.m_id | HITTYPE_SECONDARY;
+       proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        proj.weaponentity_fld = weaponentity;
        setorigin(proj, w_shotorg);
 
@@ -394,14 +394,6 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
        proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop);
        proj.missile_flags = MIF_SPLASH | MIF_ARC;
 
-#if 0
-       entity p2;
-       p2 = spawn();
-       copyentity(proj, p2);
-       setmodel(p2, MDL_PROJECTILE_ELECTRO);
-       setsize(p2, proj.mins, proj.maxs);
-#endif
-
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound
 
        MUTATOR_CALLHOOK(EditProjectile, actor, proj);
@@ -413,7 +405,7 @@ void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, i
        if(PHYS_INPUT_BUTTON_ATCK2(actor))
        if(weapon_prepareattack(thiswep, actor, weaponentity, true, -1))
        {
-               W_Electro_Attack_Orb(WEP_ELECTRO, actor, weaponentity);
+               W_Electro_Attack_Orb(thiswep, actor, weaponentity);
                actor.(weaponentity).electro_count -= 1;
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
                return;
@@ -492,7 +484,7 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit
 METHOD(Electro, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(electro, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(electro, ammo);
     return ammo_amount;
 }
 METHOD(Electro, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
@@ -501,12 +493,12 @@ METHOD(Electro, wr_checkammo2, bool(entity thiswep, entity actor, .entity weapon
     if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
     }
     else
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(electro, ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(electro, ammo);
     }
     return ammo_amount;
 }
index 84113b7020f210352d85360cfc5f6b0d6d488d61..ea7f5b8aea19e1031d1506847a0a117940701f1c 100644 (file)
@@ -42,7 +42,7 @@ void W_Fireball_Explode(entity this, entity directhitentity)
                        dir = normalize(e.origin + e.view_ofs - this.origin);
 
                        if(accuracy_isgooddamage(this.realowner, e))
-                               accuracy_add(this.realowner, WEP_FIREBALL.m_id, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
+                               accuracy_add(this.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
 
                        Damage(e, this, this.realowner, WEP_CVAR_PRI(fireball, bfgdamage) * points, this.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, this.weaponentity_fld, e.origin + e.view_ofs, WEP_CVAR_PRI(fireball, bfgforce) * dir);
                        Send_Effect(EFFECT_FIREBALL_BFGDAMAGE, e.origin, -1 * dir, 1);
index 861def9c733a12562f001c710e1c2cad254bc664..58be8f835f490ff3eac82c615a8257c8d047c27a 100644 (file)
@@ -81,7 +81,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo), weaponentity);
 
-       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage), WEP_HAGAR.m_id);
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage), thiswep.m_id);
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -102,7 +102,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        setthink(missile, adaptor_think2use_hittype_splash);
        missile.nextthink = time + WEP_CVAR_PRI(hagar, lifetime);
        PROJECTILE_MAKETRIGGER(missile);
-       missile.projectiledeathtype = WEP_HAGAR.m_id;
+       missile.projectiledeathtype = thiswep.m_id;
        missile.weaponentity_fld = weaponentity;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
@@ -127,7 +127,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
 
-       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage), WEP_HAGAR.m_id | HITTYPE_SECONDARY);
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage), thiswep.m_id | HITTYPE_SECONDARY);
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -149,7 +149,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        setthink(missile, adaptor_think2use_hittype_splash);
        missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
        PROJECTILE_MAKETRIGGER(missile);
-       missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
+       missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        missile.weaponentity_fld = weaponentity;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
@@ -169,7 +169,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 }
 
 .float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
-void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
+void W_Hagar_Attack2_Load_Release(Weapon thiswep, entity actor, .entity weaponentity)
 {
        // time to release the rockets we've loaded
 
@@ -184,7 +184,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
        weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
 
        shots = actor.(weaponentity).hagar_load;
-       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage) * shots, WEP_HAGAR.m_id | HITTYPE_SECONDARY);
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage) * shots, thiswep.m_id | HITTYPE_SECONDARY);
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        forward = v_forward;
@@ -211,7 +211,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
                setthink(missile, adaptor_think2use_hittype_splash);
                missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
                PROJECTILE_MAKETRIGGER(missile);
-               missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
+               missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
                missile.weaponentity_fld = weaponentity;
                setorigin(missile, w_shotorg);
                setsize(missile, '0 0 0', '0 0 0');
@@ -267,7 +267,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
        if(actor.items & IT_UNLIMITED_WEAPON_AMMO)
                enough_ammo = true;
        else if(autocvar_g_balance_hagar_reload_ammo)
-               enough_ammo = actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+               enough_ammo = actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
        else
                enough_ammo = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hagar, ammo);
 
@@ -342,7 +342,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
                if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.(weaponentity).hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
                {
                        actor.(weaponentity).state = WS_READY;
-                       W_Hagar_Attack2_Load_Release(actor, weaponentity);
+                       W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
                }
        }
        else
@@ -363,7 +363,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
 
 void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != WEP_HAGAR || !weapon_prepareattack_check(thiswep, actor, weaponentity, false, -1))
+       if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != thiswep || !weapon_prepareattack_check(thiswep, actor, weaponentity, false, -1))
        {
                w_ready(thiswep, actor, weaponentity, fire);
                return;
@@ -379,16 +379,9 @@ void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int
 
        W_Hagar_Attack(thiswep, actor, weaponentity);
 
-       int slot = weaponslot(weaponentity);
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hagar, refire) * W_WeaponRateFactor(actor);
-       int theframe = WFRAME_FIRE1;
-       entity this = actor.(weaponentity);
-       if(this)
-       {
-               if(this.wframe == WFRAME_FIRE1)
-                       theframe = WFRAME_DONTCHANGE;
-       }
-       weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
+       ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(hagar, refire) * W_WeaponRateFactor(actor);
+       actor.(weaponentity).wframe = WFRAME_FIRE1;
+       weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
 }
 
 METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
@@ -428,7 +421,7 @@ METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponent
     if(actor.(weaponentity).hagar_load)
     {
        actor.(weaponentity).state = WS_READY;
-       W_Hagar_Attack2_Load_Release(actor, weaponentity);
+       W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
     }
 }
 METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
@@ -443,13 +436,13 @@ METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity)
 METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hagar, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
     return ammo_amount;
 }
 METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hagar, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
     return ammo_amount;
 }
 METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
@@ -464,7 +457,7 @@ METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weapone
 {
     // if we have any rockets loaded when we die, release them
     if(actor.(weaponentity).hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
-       W_Hagar_Attack2_Load_Release(actor, weaponentity);
+       W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
 }
 METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
index 8f501653869caad8908a2723ad435dbfd70ff243..816ddae3655d523387571a2e9e23b850881be710 100644 (file)
@@ -30,7 +30,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
     if(actor.crouch)
         spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
 
-       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage), WEP_HLAC.m_id);
+       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage), thiswep.m_id);
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        if(!autocvar_g_norecoil)
        {
@@ -61,7 +61,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
        IL_PUSH(g_bot_dodge, missile);
-       missile.projectiledeathtype = WEP_HLAC.m_id;
+       missile.projectiledeathtype = thiswep.m_id;
        missile.weaponentity_fld = weaponentity;
 
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
@@ -69,7 +69,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-void W_HLAC_Attack2(entity actor, .entity weaponentity)
+void W_HLAC_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
     float spread;
@@ -80,7 +80,7 @@ void W_HLAC_Attack2(entity actor, .entity weaponentity)
     if(actor.crouch)
         spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
 
-       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage), WEP_HLAC.m_id | HITTYPE_SECONDARY);
+       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage), thiswep.m_id | HITTYPE_SECONDARY);
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        missile = new(hlacbolt);
@@ -107,7 +107,7 @@ void W_HLAC_Attack2(entity actor, .entity weaponentity)
        IL_PUSH(g_projectiles, missile);
        IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
-       missile.projectiledeathtype = WEP_HLAC.m_id | HITTYPE_SECONDARY;
+       missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        missile.weaponentity_fld = weaponentity;
 
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
@@ -134,9 +134,8 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
                        return;
                }
 
-               int slot = weaponslot(weaponentity);
-               ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
-               W_HLAC_Attack(WEP_HLAC, actor, weaponentity);
+               ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
+               W_HLAC_Attack(thiswep, actor, weaponentity);
                actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
        }
@@ -153,7 +152,7 @@ void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor, .entity weaponentity)
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo), weaponentity);
 
     for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
-        W_HLAC_Attack2(actor, weaponentity);
+        W_HLAC_Attack2(thiswep, actor, weaponentity);
 
        if(!autocvar_g_norecoil)
        {
@@ -192,13 +191,13 @@ METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
 METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hlac, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
     return ammo_amount;
 }
 METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hlac, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
     return ammo_amount;
 }
 METHOD(HLAC, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index 6319dc36ae3ba04b6c5324e6bb6743e547b47e86..607f1fcddfedfda1e80b7048aa0729fd7b22569d 100644 (file)
@@ -56,14 +56,13 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
                actor.punchangle_x = random() - 0.5;
                actor.punchangle_y = random() - 0.5;
        }
-       int slot = weaponslot(weaponentity);
        // this attack_finished just enforces a cooldown at the end of a burst
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(actor);
+       ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(actor);
 
        if(actor.(weaponentity).misc_bulletcounter == 1)
-               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, 0);
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, EFFECT_BULLET);
        else
-               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0);
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, EFFECT_BULLET);
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -101,7 +100,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit
                        return;
                }
                actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
-               W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id, actor, weaponentity);
+               W_MachineGun_Attack(thiswep, thiswep.m_id, actor, weaponentity);
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
        }
        else
@@ -127,9 +126,9 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo), weaponentity);
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, sustained_ammo), weaponentity);
 
-       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage), WEP_MACHINEGUN.m_id);
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage), thiswep.m_id);
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
@@ -137,7 +136,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
-       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), thiswep.m_id, EFFECT_BULLET);
 
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
@@ -152,21 +151,20 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
                SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
-       int slot = weaponslot(weaponentity);
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(actor);
+       ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(actor);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
 }
 
 void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage), WEP_MACHINEGUN.m_id);
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage), thiswep.m_id);
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
                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), WEP_MACHINEGUN.m_id, 0);
+       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);
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -182,8 +180,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
        if(actor.(weaponentity).misc_bulletcounter == 0)
        {
-               int slot = weaponslot(weaponentity);
-               ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor(actor);
+               ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor(actor);
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
        }
        else
@@ -238,7 +235,7 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
         {
             actor.(weaponentity).misc_bulletcounter = 1;
-            W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id, actor, weaponentity); // sets attack_finished
+            W_MachineGun_Attack(thiswep, thiswep.m_id, actor, weaponentity); // sets attack_finished
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
         }
 
@@ -246,7 +243,7 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
         {
             actor.(weaponentity).misc_bulletcounter = 1;
-            W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY, actor, weaponentity); // sets attack_finished
+            W_MachineGun_Attack(thiswep, thiswep.m_id | HITTYPE_SECONDARY, actor, weaponentity); // sets attack_finished
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
         }
     }
@@ -262,9 +259,9 @@ METHOD(MachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity wea
     if(WEP_CVAR(machinegun, reload_ammo))
     {
         if(WEP_CVAR(machinegun, mode) == 1)
-            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, sustained_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, sustained_ammo);
         else
-            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, first_ammo);
     }
     return ammo_amount;
 }
@@ -279,9 +276,9 @@ METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity wea
     if(WEP_CVAR(machinegun, reload_ammo))
     {
         if(WEP_CVAR(machinegun, mode) == 1)
-            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
         else
-            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, first_ammo);
     }
     return ammo_amount;
 }
index 6d3270a2b22788e6539f82115f93d72a2ef8b18c..6063c666eb5093b0aea9ba9af3b17730948f342d 100644 (file)
@@ -67,19 +67,17 @@ void W_MineLayer_Explode(entity this, entity directhitentity)
        RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), NULL, NULL, WEP_CVAR(minelayer, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
 
        .entity weaponentity = this.weaponentity_fld;
-       if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
+       Weapon thiswep = WEP_MINE_LAYER;
+       if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                entity own = this.realowner;
-               Weapon w = WEP_MINE_LAYER;
-               if(!w.wr_checkammo1(w, own, weaponentity))
+               if(!thiswep.wr_checkammo1(thiswep, own, weaponentity))
                {
-                       own.cnt = WEP_MINE_LAYER.m_id;
-                       int slot = weaponslot(weaponentity);
-                       ATTACK_FINISHED(own, slot) = time;
+                       own.cnt = thiswep.m_id;
+                       ATTACK_FINISHED(own, weaponentity) = time;
                        own.(weaponentity).m_switchweapon = w_getbestweapon(own, weaponentity);
                }
        }
-       this.realowner.(weaponentity).minelayer_mines -= 1;
        delete(this);
 }
 
@@ -100,19 +98,17 @@ void W_MineLayer_DoRemoteExplode(entity this)
                                                NULL, NULL, WEP_CVAR(minelayer, remote_force), this.projectiledeathtype | HITTYPE_BOUNCE, this.weaponentity_fld, NULL);
 
        .entity weaponentity = this.weaponentity_fld;
-       if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
+       Weapon thiswep = WEP_MINE_LAYER;
+       if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                entity own = this.realowner;
-               Weapon w = WEP_MINE_LAYER;
-               if(!w.wr_checkammo1(w, own, weaponentity))
+               if(!thiswep.wr_checkammo1(thiswep, own, weaponentity))
                {
-                       own.cnt = WEP_MINE_LAYER.m_id;
-                       int slot = weaponslot(weaponentity);
-                       ATTACK_FINISHED(own, slot) = time;
+                       own.cnt = thiswep.m_id;
+                       ATTACK_FINISHED(own, weaponentity) = time;
                        own.(weaponentity).m_switchweapon = w_getbestweapon(own, weaponentity);
                }
        }
-       this.realowner.(weaponentity).minelayer_mines -= 1;
        delete(this);
 }
 
@@ -226,15 +222,7 @@ void W_MineLayer_Touch(entity this, entity toucher)
        if(this.move_movetype == MOVETYPE_NONE || this.move_movetype == MOVETYPE_FOLLOW)
                return; // we're already a stuck mine, why do we get called? TODO does this even happen?
 
-       if(WarpZone_Projectile_Touch(this, toucher))
-       {
-               if(wasfreed(this))
-               {
-                       .entity weaponentity = this.weaponentity_fld;
-                       this.realowner.(weaponentity).minelayer_mines -= 1;
-               }
-               return;
-       }
+       PROJECTILE_TOUCH(this, toucher);
 
        if((toucher && IS_PLAYER(toucher) && !IS_DEAD(toucher)) || toucher.owner == this.owner)
        {
@@ -272,7 +260,8 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        // scan how many mines we placed, and return if we reached our limit
        if(WEP_CVAR(minelayer, limit))
        {
-               if(actor.(weaponentity).minelayer_mines >= WEP_CVAR(minelayer, limit))
+               int minecount = W_MineLayer_Count(actor, weaponentity);
+               if(minecount >= WEP_CVAR(minelayer, limit))
                {
                        // the refire delay keeps this message from being spammed
                        Send_Notification(NOTIF_ONE, actor, MSG_MULTI, WEAPON_MINELAYER_LIMIT, WEP_CVAR(minelayer, limit));
@@ -283,7 +272,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(minelayer, ammo), weaponentity);
 
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage), WEP_MINE_LAYER.m_id);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage), thiswep.m_id);
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        mine = WarpZone_RefSys_SpawnSameRefSys(actor);
@@ -307,7 +296,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        set_movetype(mine, MOVETYPE_TOSS);
        PROJECTILE_MAKETRIGGER(mine);
-       mine.projectiledeathtype = WEP_MINE_LAYER.m_id;
+       mine.projectiledeathtype = thiswep.m_id;
        mine.weaponentity_fld = weaponentity;
        setsize(mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
 
@@ -338,8 +327,6 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        // common properties
 
        MUTATOR_CALLHOOK(EditProjectile, actor, mine);
-
-       actor.(weaponentity).minelayer_mines = W_MineLayer_Count(actor, weaponentity);
 }
 
 bool W_MineLayer_PlacedMines(entity this, .entity weaponentity, bool detonate)
@@ -365,7 +352,8 @@ bool W_MineLayer_PlacedMines(entity this, .entity weaponentity, bool detonate)
 METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // aim and decide to fire if appropriate
-    if(actor.(weaponentity).minelayer_mines >= WEP_CVAR(minelayer, limit))
+    int minecount = W_MineLayer_Count(actor, weaponentity);
+    if(minecount >= WEP_CVAR(minelayer, limit))
         PHYS_INPUT_BUTTON_ATCK(actor) = false;
     else
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), false);
@@ -448,6 +436,8 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentit
 }
 METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
+       actor.(weaponentity).minelayer_mines = W_MineLayer_Count(actor, weaponentity);
+
     if(autocvar_g_balance_minelayer_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
     {
         // not if we're holding the minelayer without enough ammo, but can detonate existing mines
@@ -472,12 +462,11 @@ METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponent
 }
 METHOD(MineLayer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    //int slot = 0; // TODO: unhardcode
     // actually do // don't switch while placing a mine
-    //if(ATTACK_FINISHED(actor, slot) <= time || PS(actor).m_weapon != WEP_MINE_LAYER)
+    //if(ATTACK_FINISHED(actor, weaponentity) <= time || PS(actor).m_weapon != WEP_MINE_LAYER)
     //{
         float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(minelayer, ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(minelayer, ammo);
         return ammo_amount;
     //}
     //return true;
index 51267e50d4f80ad7d2d1de58b156328a2bd967ca..6e2bc91cf98631be25a6a5b2bca7c8be659dbc02 100644 (file)
@@ -151,7 +151,7 @@ void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(mortar, ammo), weaponentity);
 
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage), WEP_MORTAR.m_id);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage), thiswep.m_id);
        w_shotdir = v_forward; // no TrueAim for grenades please
 
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -164,7 +164,7 @@ void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
        gren.bouncestop = WEP_CVAR(mortar, bouncestop);
        PROJECTILE_MAKETRIGGER(gren);
-       gren.projectiledeathtype = WEP_MORTAR.m_id;
+       gren.projectiledeathtype = thiswep.m_id;
        gren.weaponentity_fld = weaponentity;
        setorigin(gren, w_shotorg);
        setsize(gren, '-3 -3 -3', '3 3 3');
@@ -203,7 +203,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(mortar, ammo), weaponentity);
 
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage), WEP_MORTAR.m_id | HITTYPE_SECONDARY);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage), thiswep.m_id | HITTYPE_SECONDARY);
        w_shotdir = v_forward; // no TrueAim for grenades please
 
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -216,7 +216,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
        gren.bouncestop = WEP_CVAR(mortar, bouncestop);
        PROJECTILE_MAKETRIGGER(gren);
-       gren.projectiledeathtype = WEP_MORTAR.m_id | HITTYPE_SECONDARY;
+       gren.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        gren.weaponentity_fld = weaponentity;
        setorigin(gren, w_shotorg);
        setsize(gren, '-3 -3 -3', '3 3 3');
@@ -325,13 +325,13 @@ METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity
 METHOD(Mortar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(mortar, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
     return ammo_amount;
 }
 METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(mortar, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
     return ammo_amount;
 }
 METHOD(Mortar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index 243f5bc34af0497394cfd9cf1c83ffe9739f991e..722171b9589555ffba0ce2a734153cf13245f7be 100644 (file)
@@ -198,11 +198,11 @@ void W_Porto_Touch(entity this, entity toucher)
        }
 }
 
-void W_Porto_Attack(entity actor, .entity weaponentity, float type)
+void W_Porto_Attack(Weapon thiswep, entity actor, .entity weaponentity, float type)
 {
        entity gren;
 
-       W_SetupShot(actor, weaponentity, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0, WEP_PORTO.m_id); // TODO: does the deathtype even need to be set here? porto can't hurt people
+       W_SetupShot(actor, weaponentity, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0, thiswep.m_id); // TODO: does the deathtype even need to be set here? porto can't hurt people
        // always shoot from the eye
        w_shotdir = v_forward;
        w_shotorg = actor.origin + actor.view_ofs + ((w_shotorg - actor.origin - actor.view_ofs) * v_forward) * v_forward;
@@ -270,7 +270,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire)))
         {
-            W_Porto_Attack(actor, weaponentity, 0);
+            W_Porto_Attack(thiswep, actor, weaponentity, 0);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
         }
 
@@ -279,7 +279,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(porto, refire)))
         {
-            W_Porto_Attack(actor, weaponentity, 1);
+            W_Porto_Attack(thiswep, actor, weaponentity, 1);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
         }
     }
@@ -306,7 +306,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire)))
         {
-            W_Porto_Attack(actor, weaponentity, -1);
+            W_Porto_Attack(thiswep, actor, weaponentity, -1);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
         }
     }
index d6996042dc56967ebf02c29a946329ea40ce4323..d4d692ec70f0adeab3f7118961bd904dbb66d533 100644 (file)
@@ -19,7 +19,7 @@ void W_Rifle_FireBullet(Weapon thiswep, .entity weaponentity, float pSpread, flo
        }
 
        for(i = 0; i < pShots; ++i)
-               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE));
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EFFECT_RIFLE : EFFECT_RIFLE_WEAK));
 
        if(autocvar_g_casings >= 2)
     {
@@ -28,17 +28,17 @@ void W_Rifle_FireBullet(Weapon thiswep, .entity weaponentity, float pSpread, flo
     }
 }
 
-void W_Rifle_Attack(entity actor, .entity weaponentity)
+void W_Rifle_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_Rifle_FireBullet(WEP_RIFLE, weaponentity, WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), SND_CAMPINGRIFLE_FIRE, actor);
+       W_Rifle_FireBullet(thiswep, weaponentity, WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), thiswep.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), SND_CAMPINGRIFLE_FIRE, actor);
 }
 
-void W_Rifle_Attack2(entity actor, .entity weaponentity)
+void W_Rifle_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_Rifle_FireBullet(WEP_RIFLE, weaponentity, WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), SND_CAMPINGRIFLE_FIRE2, actor);
+       W_Rifle_FireBullet(thiswep, weaponentity, WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), thiswep.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), SND_CAMPINGRIFLE_FIRE2, actor);
 }
 
-.void(entity actor, .entity weaponentity) rifle_bullethail_attackfunc;
+.void(Weapon thiswep, entity actor, .entity weaponentity) rifle_bullethail_attackfunc;
 .WFRAME rifle_bullethail_frame;
 .float rifle_bullethail_animtime;
 .float rifle_bullethail_refire;
@@ -47,28 +47,27 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent
        float r, af;
 
        Weapon sw = actor.(weaponentity).m_switchweapon; // make it not detect weapon changes as reason to abort firing
-       int slot = weaponslot(weaponentity);
-       af = ATTACK_FINISHED(actor, slot);
+       af = ATTACK_FINISHED(actor, weaponentity);
        actor.(weaponentity).m_switchweapon = actor.(weaponentity).m_weapon;
-       ATTACK_FINISHED(actor, slot) = time;
+       ATTACK_FINISHED(actor, weaponentity) = time;
        r = weapon_prepareattack(thiswep, actor, weaponentity, actor.rifle_bullethail_frame == WFRAME_FIRE2, actor.rifle_bullethail_refire);
        if(actor.(weaponentity).m_switchweapon == actor.(weaponentity).m_weapon)
                actor.(weaponentity).m_switchweapon = sw;
        if(r)
        {
-               actor.rifle_bullethail_attackfunc(actor, weaponentity);
+               actor.rifle_bullethail_attackfunc(thiswep, actor, weaponentity);
                weapon_thinkf(actor, weaponentity, actor.rifle_bullethail_frame, actor.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
        }
        else
        {
-               ATTACK_FINISHED(actor, slot) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+               ATTACK_FINISHED(actor, weaponentity) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
        }
 }
 
-void W_Rifle_BulletHail(entity actor, .entity weaponentity, float mode, void(entity actor, .entity weaponentity) AttackFunc, WFRAME fr, float animtime, float refire)
+void W_Rifle_BulletHail(Weapon thiswep, entity actor, .entity weaponentity, float mode, void(Weapon thiswep, entity actor, .entity weaponentity) AttackFunc, WFRAME fr, float animtime, float refire)
 {
        // if we get here, we have at least one bullet to fire
-       AttackFunc(actor, weaponentity);
+       AttackFunc(thiswep, actor, weaponentity);
        if(mode)
        {
                // continue hail
@@ -122,7 +121,7 @@ METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         if(time >= actor.(weaponentity).rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
         {
             weapon_prepareattack_do(actor, weaponentity, false, WEP_CVAR_PRI(rifle, refire));
-            W_Rifle_BulletHail(actor, weaponentity, WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
+            W_Rifle_BulletHail(thiswep, actor, weaponentity, WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
             actor.(weaponentity).rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
         }
         if(fire & 2)
@@ -137,7 +136,7 @@ METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
                     if(time >= actor.(weaponentity).rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
                     {
                         weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(rifle, refire));
-                        W_Rifle_BulletHail(actor, weaponentity, WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
+                        W_Rifle_BulletHail(thiswep, actor, weaponentity, WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
                         actor.(weaponentity).rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
                     }
                 }
@@ -148,13 +147,13 @@ METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
 METHOD(Rifle, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(rifle, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
     return ammo_amount;
 }
 METHOD(Rifle, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(rifle, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
     return ammo_amount;
 }
 METHOD(Rifle, wr_resetplayer, void(entity thiswep, entity actor))
index 10080bbad275bd71b067ffcefcfd333b03998894..784276ef46d8b63f2b1ce4f6c0ad4bee6c3ce4a1 100644 (file)
@@ -169,7 +169,7 @@ void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, v
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, missile_ammo), weaponentity);
 
        makevectors(actor.v_angle);
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_SEEKER_FIRE, CH_WEAPON_A, 0, ((m_target != NULL) ? WEP_SEEKER.m_id | HITTYPE_SECONDARY : WEP_SEEKER.m_id));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_SEEKER_FIRE, CH_WEAPON_A, 0, ((m_target != NULL) ? thiswep.m_id | HITTYPE_SECONDARY : thiswep.m_id));
        w_shotorg += f_diff;
        Send_Effect(EFFECT_SEEKER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -197,9 +197,9 @@ void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, v
        //missile.think           = W_Seeker_Missile_Animate; // csqc projectiles.
 
        if(missile.enemy != NULL)
-               missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
+               missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        else
-               missile.projectiledeathtype = WEP_SEEKER.m_id;
+               missile.projectiledeathtype = thiswep.m_id;
 
 
        setorigin(missile, w_shotorg);
@@ -266,7 +266,7 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
                        f_diff = '+1.25 +3.75 0';
                        break;
        }
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_FLAC_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, flac_damage), WEP_SEEKER.m_id | HITTYPE_SECONDARY);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_FLAC_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, flac_damage), thiswep.m_id | HITTYPE_SECONDARY);
        w_shotorg += f_diff;
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -281,7 +281,7 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
        missile.nextthink               = time + WEP_CVAR(seeker, flac_lifetime) + WEP_CVAR(seeker, flac_lifetime_rand);
        missile.solid                   = SOLID_BBOX;
        set_movetype(missile, MOVETYPE_FLY);
-       missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
+       missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        missile.weaponentity_fld = weaponentity;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
@@ -315,7 +315,7 @@ entity W_Seeker_Tagged_Info(entity isowner, .entity weaponentity, entity istarge
        return NULL;
 }
 
-void W_Seeker_Attack(entity actor, .entity weaponentity)
+void W_Seeker_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity closest_target = NULL;
 
@@ -337,7 +337,7 @@ void W_Seeker_Attack(entity actor, .entity weaponentity)
                        closest_target = NULL;
        }
 
-       W_Seeker_Fire_Missile(WEP_SEEKER, actor, weaponentity, '0 0 0', closest_target);
+       W_Seeker_Fire_Missile(thiswep, actor, weaponentity, '0 0 0', closest_target);
 }
 
 void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seeker_Attack
@@ -348,7 +348,7 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
        Weapon thiswep = WEP_SEEKER;
        .entity weaponentity = this.weaponentity_fld;
-       if((!(this.realowner.items & IT_UNLIMITED_AMMO) && GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (this.realowner.(weaponentity).m_switchweapon != WEP_SEEKER))
+       if((!(this.realowner.items & IT_UNLIMITED_AMMO) && GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (this.realowner.(weaponentity).m_switchweapon != thiswep))
        {
                delete(this);
                return;
@@ -365,17 +365,17 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
        switch(c)
        {
                case 0:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '-1.25 -3.75 0', own.enemy); // TODO
+                       W_Seeker_Fire_Missile(thiswep, own, weaponentity, '-1.25 -3.75 0', own.enemy); // TODO
                        break;
                case 1:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '+1.25 -3.75 0', own.enemy); // TODO
+                       W_Seeker_Fire_Missile(thiswep, own, weaponentity, '+1.25 -3.75 0', own.enemy); // TODO
                        break;
                case 2:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '-1.25 +3.75 0', own.enemy); // TODO
+                       W_Seeker_Fire_Missile(thiswep, own, weaponentity, '-1.25 +3.75 0', own.enemy); // TODO
                        break;
                case 3:
                default:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '+1.25 +3.75 0', own.enemy); // TODO
+                       W_Seeker_Fire_Missile(thiswep, own, weaponentity, '+1.25 +3.75 0', own.enemy); // TODO
                        break;
        }
 
@@ -491,7 +491,7 @@ void W_Seeker_Fire_Tag(Weapon thiswep, entity actor, .entity weaponentity)
 {
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, tag_ammo), weaponentity);
 
-       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_TAG_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count), WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_TAG_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count), thiswep.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY);
 
        entity missile          = new(seeker_tag);
        missile.weaponentity_fld = weaponentity;
@@ -550,7 +550,7 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(seeker, missile_refire)))
             {
-                W_Seeker_Attack(actor, weaponentity);
+                W_Seeker_Attack(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
             }
         }
@@ -590,12 +590,12 @@ METHOD(Seeker, wr_checkammo1, bool(entity thiswep, entity actor, .entity weapone
     if(WEP_CVAR(seeker, type) == 1)
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, missile_ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, missile_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(seeker, missile_ammo);
     }
     else
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, tag_ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(seeker, tag_ammo);
     }
     return ammo_amount;
 }
@@ -605,12 +605,12 @@ METHOD(Seeker, wr_checkammo2, bool(entity thiswep, entity actor, .entity weapone
     if(WEP_CVAR(seeker, type) == 1)
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, tag_ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(seeker, tag_ammo);
     }
     else
     {
         ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, flac_ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, flac_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(seeker, flac_ammo);
     }
     return ammo_amount;
 }
index e9d55b24232353c0a5f086f5b40373f60b17f0c3..7e60667e5350bf1b8bb1c62bb19645df71d1ed42 100644 (file)
@@ -106,7 +106,7 @@ void W_Shockwave_Melee_Think(entity this)
 
                        // handle accuracy
                        if(accuracy_isgooddamage(this.realowner, target_victim))
-                               { accuracy_add(this.realowner, WEP_SHOCKWAVE.m_id, 0, swing_damage); }
+                               { accuracy_add(this.realowner, WEP_SHOCKWAVE, 0, swing_damage); }
 
                        #ifdef DEBUG_SHOCKWAVE
                        LOG_INFOF(
@@ -157,7 +157,7 @@ void W_Shockwave_Melee(Weapon thiswep, entity actor, .entity weaponentity, int f
        setthink(meleetemp, W_Shockwave_Melee_Think);
        meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor(actor);
        meleetemp.weaponentity_fld = weaponentity;
-       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range), WEP_SHOCKWAVE.m_id | HITTYPE_SECONDARY);
+       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range), thiswep.m_id | HITTYPE_SECONDARY);
 }
 
 // SHOCKWAVE ATTACK MODE
@@ -265,7 +265,7 @@ void W_Shockwave_Send(entity actor)
        WriteByte(MSG_BROADCAST, etof(actor));
 }
 
-void W_Shockwave_Attack(entity actor, .entity weaponentity)
+void W_Shockwave_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        // declarations
        float multiplier, multiplier_from_accuracy, multiplier_from_distance;
@@ -276,7 +276,7 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
        float i, queue = 0;
 
        // set up the shot direction
-       W_SetupShot(actor, weaponentity, true, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage), WEP_SHOCKWAVE.m_id);
+       W_SetupShot(actor, weaponentity, true, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage), thiswep.m_id);
        vector attack_endpos = (w_shotorg + (w_shotdir * WEP_CVAR(shockwave, blast_distance)));
        WarpZone_TraceLine(w_shotorg, attack_endpos, MOVE_NOMONSTERS, actor);
        vector attack_hitpos = trace_endpos;
@@ -292,7 +292,7 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
                WEP_CVAR(shockwave, blast_splash_edgedamage),
                WEP_CVAR(shockwave, blast_splash_radius),
                w_shotdir * WEP_CVAR(shockwave, blast_splash_force),
-               WEP_SHOCKWAVE.m_id,
+               thiswep.m_id,
                0,
                actor
        );
@@ -381,7 +381,7 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
                                        actor,
                                        actor,
                                        final_damage,
-                                       WEP_SHOCKWAVE.m_id,
+                                       thiswep.m_id,
                                        weaponentity,
                                        head.origin,
                                        final_force
@@ -566,14 +566,14 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
                        actor,
                        actor,
                        final_damage,
-                       WEP_SHOCKWAVE.m_id,
+                       thiswep.m_id,
                        weaponentity,
                        head.origin,
                        final_force
                );
 
                if(accuracy_isgooddamage(actor, head))
-                       accuracy_add(actor, WEP_SHOCKWAVE.m_id, 0, final_damage);
+                       accuracy_add(actor, thiswep, 0, final_damage);
 
                #ifdef DEBUG_SHOCKWAVE
                LOG_INFOF(
@@ -608,7 +608,7 @@ METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponent
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(shockwave, blast_animtime)))
             {
-                W_Shockwave_Attack(actor, weaponentity);
+                W_Shockwave_Attack(thiswep, actor, weaponentity);
                 actor.(weaponentity).shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(actor);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
             }
index 4acceed7184c924af8ffca37017fe3b8794191b4..8faac3d5d03d7e2a4f2dd8f98e9303a572a36ea5 100644 (file)
@@ -2,14 +2,13 @@
 
 #ifdef SVQC
 
-void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary, float ammocount, float damage, float bullets, float spread, float solidpenetration, float force)
+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, WEP_SHOTGUN.m_id);
+       W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets, thiswep.m_id);
        for(int sc = 0;sc < bullets;sc = sc + 1)
-               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, WEP_SHOTGUN.m_id, 0);
-
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect);
 
        Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, ammocount);
 
@@ -96,7 +95,7 @@ void W_Shotgun_Melee_Think(entity this)
                                this.realowner.origin + this.realowner.view_ofs,
                                v_forward * WEP_CVAR_SEC(shotgun, force));
 
-                       if(accuracy_isgooddamage(this.realowner, target_victim)) { accuracy_add(this.realowner, WEP_SHOTGUN.m_id, 0, swing_damage); }
+                       if(accuracy_isgooddamage(this.realowner, target_victim)) { accuracy_add(this.realowner, WEP_SHOTGUN, 0, swing_damage); }
 
                        // draw large red flash for debugging
                        //te_customflash(targpos, 200, 2, '15 0 0');
@@ -153,13 +152,14 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true,
+       W_Shotgun_Attack(thiswep, actor, weaponentity, true,
                WEP_CVAR_PRI(shotgun, ammo),
                WEP_CVAR_PRI(shotgun, damage),
                WEP_CVAR_PRI(shotgun, bullets),
                WEP_CVAR_PRI(shotgun, spread),
                WEP_CVAR_PRI(shotgun, solidpenetration),
-               WEP_CVAR_PRI(shotgun, force)); // actually is secondary, but we trick the last shot into playing full reload sound
+               WEP_CVAR_PRI(shotgun, force),
+               EFFECT_BULLET_WEAK); // actually is secondary, but we trick the last shot into playing full reload sound
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
 }
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
@@ -172,13 +172,14 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false,
+       W_Shotgun_Attack(thiswep, actor, weaponentity, false,
                WEP_CVAR_PRI(shotgun, ammo),
                WEP_CVAR_PRI(shotgun, damage),
                WEP_CVAR_PRI(shotgun, bullets),
                WEP_CVAR_PRI(shotgun, spread),
                WEP_CVAR_PRI(shotgun, solidpenetration),
-               WEP_CVAR_PRI(shotgun, force));
+               WEP_CVAR_PRI(shotgun, force),
+               EFFECT_BULLET_WEAK);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
 }
 
@@ -215,7 +216,8 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
                                                WEP_CVAR_PRI(shotgun, bullets),
                                                WEP_CVAR_PRI(shotgun, spread),
                                                WEP_CVAR_PRI(shotgun, solidpenetration),
-                                               WEP_CVAR_PRI(shotgun, force));
+                                               WEP_CVAR_PRI(shotgun, force),
+                                               EFFECT_BULLET_WEAK);
                     actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                 }
@@ -233,7 +235,8 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
                                                WEP_CVAR_PRI(shotgun, bullets),
                                                WEP_CVAR_PRI(shotgun, spread),
                                                WEP_CVAR_PRI(shotgun, solidpenetration),
-                                               WEP_CVAR_PRI(shotgun, force));
+                                               WEP_CVAR_PRI(shotgun, force),
+                                               EFFECT_BULLET_WEAK);
                     actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                 }
@@ -252,7 +255,7 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
 METHOD(Shotgun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(shotgun, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
     return ammo_amount;
 }
 METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
@@ -266,7 +269,7 @@ METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weapon
         case 2: // secondary triple shot
         {
             float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(shotgun, ammo);
-            ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
             return ammo_amount;
         }
         default: return false; // secondary unavailable
index 2dd5cae1552e6434c95a6eddd0cdbfa9cb2cd226..cefa4558f2fd9b43f7aa2fa1a9fe94f8cd63582b 100644 (file)
@@ -105,7 +105,7 @@ NET_HANDLE(TE_CSQC_VAPORBEAMPARTICLE, bool isNew)
 void W_RocketMinsta_Explosion(entity actor, .entity weaponentity, vector loc)
 {
        if(accuracy_canbegooddamage(actor))
-               accuracy_add(actor, WEP_DEVASTATOR.m_id, autocvar_g_rm_damage, 0);
+               accuracy_add(actor, WEP_DEVASTATOR, autocvar_g_rm_damage, 0);
        entity dmgent = spawn();
        dmgent.owner = dmgent.realowner = actor;
        setorigin(dmgent, loc);
@@ -118,14 +118,14 @@ void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        bool flying = IsFlying(actor); // do this BEFORE to make the trace values from FireRailgunBullet last
        float vaporizer_damage = ((WEP_CVAR_PRI(vaporizer, damage) > 0) ? WEP_CVAR_PRI(vaporizer, damage) : 10000);
 
-       W_SetupShot(actor, weaponentity, true, 0, SND_Null, CH_WEAPON_A, vaporizer_damage, WEP_VAPORIZER.m_id);
+       W_SetupShot(actor, weaponentity, true, 0, SND_Null, CH_WEAPON_A, vaporizer_damage, thiswep.m_id);
        // handle sound separately so we can change the volume
        // added bonus: no longer plays the strength sound (strength gives no bonus to instakill anyway)
        sound (actor, CH_WEAPON_A, SND_MINSTANEXFIRE, VOL_BASE * 0.8, ATTEN_NORM);
 
        yoda = 0;
        damage_goodhits = 0;
-       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, WEP_CVAR_PRI(vaporizer, force), 0, 0, 0, 0, WEP_VAPORIZER.m_id);
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, WEP_CVAR_PRI(vaporizer, force), 0, 0, 0, 0, thiswep.m_id);
 
        // do this now, as goodhits is disabled below
        SendCSQCVaporizerBeamParticle(actor, damage_goodhits);
@@ -351,7 +351,7 @@ METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weap
 {
     float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= vaporizer_ammo;
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= vaporizer_ammo;
     return ammo_amount;
 }
 METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
@@ -359,7 +359,7 @@ METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep, entity actor, .entity weap
     if(!WEP_CVAR_SEC(vaporizer, ammo))
         return true;
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(vaporizer, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
     return ammo_amount;
 }
 METHOD(Vaporizer, wr_resetplayer, void(entity thiswep, entity actor))
index b8963229710e23266cba03cb023c2a443773d6b1..2e9a60ab85157e68c9c946ea7857a318cd65579d 100644 (file)
@@ -105,7 +105,7 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i
        myforcehalflife = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_forcehalflife);
        myammo = WEP_CVAR_BOTH(vortex, !issecondary, ammo);
 
-    float dtype = WEP_VORTEX.m_id;
+    float dtype = thiswep.m_id;
     if(WEP_CVAR_BOTH(vortex, !issecondary, armorpierce))
         dtype |= HITTYPE_ARMORPIERCE;
 
@@ -228,7 +228,7 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
                                     {
                                         actor.(weaponentity).clip_load = max(WEP_CVAR_SEC(vortex, ammo), actor.(weaponentity).clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
                                     }
-                                    actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) = actor.(weaponentity).clip_load;
+                                    actor.(weaponentity).(weapon_load[thiswep.m_id]) = actor.(weaponentity).clip_load;
                                 }
                                 else
                                 {
@@ -269,7 +269,7 @@ METHOD(Vortex, wr_setup, void(entity thiswep, entity actor, .entity weaponentity
 METHOD(Vortex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(vortex, ammo);
-    ammo_amount += (autocvar_g_balance_vortex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
+    ammo_amount += (autocvar_g_balance_vortex_reload_ammo && actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
     return ammo_amount;
 }
 METHOD(Vortex, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
@@ -278,7 +278,7 @@ METHOD(Vortex, wr_checkammo2, bool(entity thiswep, entity actor, .entity weapone
     {
         // don't allow charging if we don't have enough ammo
         float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(vortex, ammo);
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
         return ammo_amount;
     }
     else
index 9488c4c2c6bc0927a3ba8b30eebeb96baf9a2ccc..6b1797c664e9b38fa36f7eee6d6526d2eea4cd5c 100644 (file)
@@ -20,7 +20,7 @@ MACRO_END
     \
     PROP(false, m_alpha, WEPENT_SET_NORMAL, \
        { WriteByte(chan, rint(bound(-1, 254 * this.m_alpha, 254) - -1)); }, \
-       { (viewmodels[this.m_wepent_slot]).alpha = (ReadByte() + -1) / 254; }) \
+       { (viewmodels[this.m_wepent_slot]).m_alpha = (ReadByte() + -1) / 254; }) \
     \
     PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
        { WriteByte(chan, this.vortex_charge * 255); }, \
index d6db7745b9fe1cc5e1ebc8f0f0edcfca78382214..556f58194f5ed5298d52f0aad3f4e6ca3f046e2a 100644 (file)
@@ -35,6 +35,8 @@ REGISTER_NET_TEMP(CLIENT_WEPENT)
        .Weapon switchingweapon;
        .Weapon switchweapon;
 
+       .float m_alpha;
+
        // only for Porto
        .bool angles_held_status;
        .vector angles_held;
index f87f00033762b4fbe18f2d5305989941a191828b..268b591264208458dcada567c028fbdf102be052 100644 (file)
@@ -210,11 +210,11 @@ bool CSQCPlayer_IsLocalPlayer(entity this)
 /** Called once per CSQC_UpdateView() */
 void CSQCPlayer_SetCamera()
 {
-       const vector v0 = ((intermission && !autocvar_cl_movement_intermissionrunning) ? '0 0 0' : pmove_vel); // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
-       const float vh = PHYS_VIEWHEIGHT(NULL);
-       const vector pl_viewofs = PHYS_PL_VIEWOFS(NULL);
-       const vector pl_viewofs_crouch = PHYS_PL_CROUCH_VIEWOFS(NULL);
-       const entity e = csqcplayer;
+       vector v0 = ((intermission && !autocvar_cl_movement_intermissionrunning) ? '0 0 0' : pmove_vel); // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+       float vh = PHYS_VIEWHEIGHT(NULL);
+       vector pl_viewofs = PHYS_PL_VIEWOFS(NULL);
+       vector pl_viewofs_crouch = PHYS_PL_CROUCH_VIEWOFS(NULL);
+       entity e = csqcplayer;
        if (e)
        {
                if (servercommandframe == 0 || clientcommandframe == 0)
@@ -239,13 +239,13 @@ void CSQCPlayer_SetCamera()
                }
                else
                {
-                       const int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
+                       int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
                        InterpolateOrigin_Do(e);
                        e.iflags = flg;
 
                        if (csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
                        {
-                               const vector o = e.origin;
+                               vector o = e.origin;
                                csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
                                CSQCPlayer_PredictTo(e, servercommandframe + 1, false);
                                CSQCPlayer_SetPredictionError(e.origin - o, e.velocity - v0, pmove_onground - IS_ONGROUND(e));
index 3a6765e9d46fbfc7ed9025238cfe8017a1fc5bde..7f8b0cdc837258a7bb5547d984afbcd960430baa 100644 (file)
@@ -28,6 +28,8 @@ void WarpZone_Fade_PreDraw(entity this)
 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
        warpzone_warpzones_exist = 1;
        if (!this.enemy)
        {
@@ -84,6 +86,8 @@ 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
        warpzone_cameras_exist = 1;
        this.classname = "func_warpzone_camera";
 
index a5c7cfa8544c70219099a4a12079b7a87dd5a408..6d725259d281ffeb8297902f8c4c62712e54b62f 100644 (file)
@@ -3,26 +3,26 @@
 #include "item/container.qh"
 #include "item/borderimage.qh"
 
-       METHOD(Item, destroy, void(Item this))
+       METHOD(MenuItem, destroy, void(MenuItem this))
        {
                // free memory associated with this
        }
 
-       METHOD(Item, relinquishFocus, void(Item this))
+       METHOD(MenuItem, relinquishFocus, void(MenuItem this))
        {
                entity par = this.parent;
                if (!par) return;
                if (par.instanceOfContainer) par.setFocus(par, NULL);
        }
 
-       METHOD(Item, resizeNotify, void(Item this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
+       METHOD(MenuItem, resizeNotify, void(MenuItem this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
        {
                this.origin = absOrigin;
                this.size = absSize;
        }
 
        int autocvar_menu_showboxes;
-       METHOD(Item, draw, void(Item this))
+       METHOD(MenuItem, draw, void(MenuItem this))
        {
                if (!autocvar_menu_showboxes) return;
                vector rgb = '1 0 1';
                }
        }
 
-       METHOD(Item, showNotify, void(Item this))
+       METHOD(MenuItem, showNotify, void(MenuItem this))
        {}
 
-       METHOD(Item, hideNotify, void(Item this))
+       METHOD(MenuItem, hideNotify, void(MenuItem this))
        {}
 
-       METHOD(Item, keyDown, float(Item this, float scan, float ascii, float shift))
+       METHOD(MenuItem, keyDown, float(MenuItem this, float scan, float ascii, float shift))
        {
                return 0;  // unhandled
        }
 
-       METHOD(Item, keyUp, float(Item this, float scan, float ascii, float shift))
+       METHOD(MenuItem, keyUp, float(MenuItem this, float scan, float ascii, float shift))
        {
                return 0;  // unhandled
        }
 
-       METHOD(Item, mouseMove, float(Item this, vector pos))
+       METHOD(MenuItem, mouseMove, float(MenuItem this, vector pos))
        {
                return 0;  // unhandled
        }
 
-       METHOD(Item, mousePress, bool(Item this, vector pos))
+       METHOD(MenuItem, mousePress, bool(MenuItem this, vector pos))
        {
                return false;  // unhandled
        }
 
-       METHOD(Item, mouseDrag, float(Item this, vector pos))
+       METHOD(MenuItem, mouseDrag, float(MenuItem this, vector pos))
        {
                return 0;  // unhandled
        }
 
-       METHOD(Item, mouseRelease, float(Item this, vector pos))
+       METHOD(MenuItem, mouseRelease, float(MenuItem this, vector pos))
        {
                return 0;  // unhandled
        }
 
     void m_play_focus_sound();
 
-       METHOD(Item, focusEnter, void(Item this))
+       METHOD(MenuItem, focusEnter, void(MenuItem this))
        {
                if (this.allowFocusSound) m_play_focus_sound();
        }
 
-       METHOD(Item, focusLeave, void(Item this))
+       METHOD(MenuItem, focusLeave, void(MenuItem this))
        {}
 
-       METHOD(Item, toString, string(Item this))
+       METHOD(MenuItem, toString, string(MenuItem this))
        {
                return string_null;
        }
index 6cee17b3fdd5f9ccd24a66d078f040aaee9110a2..dd1d0679bed6c106e0ff8cad1fd4c9a1064c07e7 100644 (file)
@@ -5,28 +5,28 @@
 #include "draw.qh"
 #include "menu.qh"
 
-CLASS(Item, Object)
-       METHOD(Item, draw, void(Item));
-       METHOD(Item, keyDown, float(Item, float, float, float));
-       METHOD(Item, keyUp, float(Item, float, float, float));
-       METHOD(Item, mouseMove, float(Item, vector));
-       METHOD(Item, mousePress, bool(Item this, vector pos));
-       METHOD(Item, mouseDrag, float(Item, vector));
-       METHOD(Item, mouseRelease, float(Item, vector));
-       METHOD(Item, focusEnter, void(Item));
-       METHOD(Item, focusLeave, void(Item));
-       METHOD(Item, resizeNotify, void(Item, vector, vector, vector, vector));
-       METHOD(Item, relinquishFocus, void(Item));
-       METHOD(Item, showNotify, void(Item));
-       METHOD(Item, hideNotify, void(Item));
-       METHOD(Item, toString, string(Item));
-       METHOD(Item, destroy, void(Item));
-       ATTRIB(Item, focused, float, 0);
-       ATTRIB(Item, focusable, float, 0);
-       ATTRIB(Item, allowFocusSound, float, 0);
-       ATTRIB(Item, parent, entity);
-       ATTRIB(Item, preferredFocusPriority, float, 0);
-       ATTRIB(Item, origin, vector, '0 0 0');
-       ATTRIB(Item, size, vector, '0 0 0');
-       ATTRIB(Item, tooltip, string);
-ENDCLASS(Item)
+CLASS(MenuItem, Object)
+       METHOD(MenuItem, draw, void(MenuItem));
+       METHOD(MenuItem, keyDown, float(MenuItem, float, float, float));
+       METHOD(MenuItem, keyUp, float(MenuItem, float, float, float));
+       METHOD(MenuItem, mouseMove, float(MenuItem, vector));
+       METHOD(MenuItem, mousePress, bool(MenuItem this, vector pos));
+       METHOD(MenuItem, mouseDrag, float(MenuItem, vector));
+       METHOD(MenuItem, mouseRelease, float(MenuItem, vector));
+       METHOD(MenuItem, focusEnter, void(MenuItem));
+       METHOD(MenuItem, focusLeave, void(MenuItem));
+       METHOD(MenuItem, resizeNotify, void(MenuItem, vector, vector, vector, vector));
+       METHOD(MenuItem, relinquishFocus, void(MenuItem));
+       METHOD(MenuItem, showNotify, void(MenuItem));
+       METHOD(MenuItem, hideNotify, void(MenuItem));
+       METHOD(MenuItem, toString, string(MenuItem));
+       METHOD(MenuItem, destroy, void(MenuItem));
+       ATTRIB(MenuItem, focused, float, 0);
+       ATTRIB(MenuItem, focusable, float, 0);
+       ATTRIB(MenuItem, allowFocusSound, float, 0);
+       ATTRIB(MenuItem, parent, entity);
+       ATTRIB(MenuItem, preferredFocusPriority, float, 0);
+       ATTRIB(MenuItem, origin, vector, '0 0 0');
+       ATTRIB(MenuItem, size, vector, '0 0 0');
+       ATTRIB(MenuItem, tooltip, string);
+ENDCLASS(MenuItem)
index b73752685030a8ef57277ddaf3a3b7b7279f26f1..bc2d8e6d0bcce9e991861781e7ff3a76e0f0c760 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <menu/item.qh>
 
-CLASS(Container, Item)
+CLASS(Container, MenuItem)
        METHOD(Container, draw, void(entity));
        METHOD(Container, keyUp, float(entity, float, float, float));
        METHOD(Container, keyDown, float(entity, float, float, float));
index 726f328600d79b570c210b3bb234006868ef2982..0db9c3719ac8ae9135e9662680dfc57ac6686190 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../item.qh"
-CLASS(Image, Item)
+CLASS(Image, MenuItem)
        METHOD(Image, configureImage, void(entity, string));
        METHOD(Image, draw, void(entity));
        METHOD(Image, toString, string(entity));
index d02f4661f5cd84bf891af26a6c1bef694244f463..3272ed54f39ec1953ff8e61b822cced36287b414 100644 (file)
                        }
 
                // skipping SUPER(InputBox).draw(me);
-               Item_draw(me);
+               MenuItem_draw(me);
        }
 
        void InputBox_showNotify(entity me)
index f91ae8ad3cb12a13265d085fe937cf32959f2a95..2439d1d5beafbfa72c206bfe422a25c9135517e3 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../item.qh"
-CLASS(Label, Item)
+CLASS(Label, MenuItem)
        METHOD(Label, configureLabel, void(entity, string, float, float));
        METHOD(Label, draw, void(entity));
        METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector));
index b3f5164a4d0937f769a55c68fb9cfbf474b07a99..f60066cd7b3d941526040fa85cbea64f6c5247de 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../item.qh"
-CLASS(ListBox, Item)
+CLASS(ListBox, MenuItem)
        METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(ListBox, configureListBox, void(entity, float, float));
        METHOD(ListBox, draw, void(entity));
index 7bf363def7f4b42ebf413bcea99b7871a7418a39..7499f4462dab79698e1609d071becad5f80f139f 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../item.qh"
-CLASS(XonoticCrosshairPreview, Item)
+CLASS(XonoticCrosshairPreview, MenuItem)
        METHOD(XonoticCrosshairPreview, configureXonoticCrosshairPreview, void(entity));
        METHOD(XonoticCrosshairPreview, draw, void(entity));
        ATTRIB(XonoticCrosshairPreview, src, string);
index 2a2144598bbfecd56097c0a8efea20b4918228fd..ba09c311e4bf0e3fbf99a69898bf91b7fb70e638 100644 (file)
@@ -52,23 +52,8 @@ void GameType_ConfigureSliders(entity me, string pLabel, float pMin, float pMax,
 
 void GameType_ConfigureSliders_for_CurrentGametype(entity me)
 {
-       switch(MapInfo_CurrentGametype())
-       {
-               case MAPINFO_TYPE_CA:              GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_ca_teams_override",          _("The amount of frags needed before the match will end")); break;
-               case MAPINFO_TYPE_FREEZETAG:       GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_freezetag_teams_override",   _("The amount of frags needed before the match will end")); break;
-               case MAPINFO_TYPE_CTF:             GameType_ConfigureSliders(me, _("Capture limit:"),   1,   20,  1, "capturelimit_override",     string_null,                    _("The amount of captures needed before the match will end")); break;
-               case MAPINFO_TYPE_DOMINATION:      GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, "g_domination_point_limit",  "g_domination_teams_override",  _("The amount of points needed before the match will end")); break;
-               case MAPINFO_TYPE_KEYHUNT:         GameType_ConfigureSliders(me, _("Point limit:"),   200, 1500, 50, "g_keyhunt_point_limit",     "g_keyhunt_teams_override",     _("The amount of points needed before the match will end")); break;
-               case MAPINFO_TYPE_LMS:             GameType_ConfigureSliders(me, _("Lives:"),           3,   50,  1, "g_lms_lives_override",      string_null,                    string_null); break;
-               case MAPINFO_TYPE_RACE:            GameType_ConfigureSliders(me, _("Laps:"),            1,   25,  1, "g_race_laps_limit",         string_null,                    string_null); break;
-               case MAPINFO_TYPE_NEXBALL:         GameType_ConfigureSliders(me, _("Goals:"),           1,   50,  1, "g_nexball_goallimit",       string_null,                    _("The amount of goals needed before the match will end")); break;
-               case MAPINFO_TYPE_ASSAULT:         GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_ONSLAUGHT:       GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_CTS:             GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_INVASION:        GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
-               case MAPINFO_TYPE_TEAM_DEATHMATCH: GameType_ConfigureSliders(me, _("Point limit:"),     5,  100,  5, "g_tdm_point_limit",         "g_tdm_teams_override",         _("The amount of points needed before the match will end")); break;
-               default:                           GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        string_null,                    _("The amount of frags needed before the match will end")); break;
-       }
+       Gametype gt = MapInfo_CurrentGametype();
+       gt.m_configuremenu(gt, me, GameType_ConfigureSliders);
 }
 
 entity makeXonoticServerCreateTab()
index 21e7ecadc454fdc7168a1e0c5314892f5d028749..8b6dd4b731512cec3da19fe489dc512a04245108 100644 (file)
@@ -37,10 +37,11 @@ string WeaponArenaString()
        s = "";
        for(int j = 0; j < n; ++j)
        {
-               FOREACH(Weapons, it != WEP_Null, {
-                       if(argv(j) == it.netname)
-                               s = cons_mid(s, " & ", it.m_name);
-               });
+               Weapon wep = Weapons_fromstr(argv(j));
+               if(wep != WEP_Null)
+               {
+                       s = cons_mid(s, " & ", wep.m_name);
+               }
        }
        s = sprintf(_("%s Arena"), s);
 
index 594b581fe4408d16351225406971870bcda9c2e2..1c7da72919d68934749d76034cef11cd00ae3b97 100644 (file)
@@ -42,7 +42,7 @@ void XonoticMiscSettingsTab_fill(entity me)
                        e.configureXonoticTextSliderValues(e);
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Input packets/s:")));
-               me.TD(me, 1, 2, e = makeXonoticSlider_T(20, 100, 5, "cl_netfps",
+               me.TD(me, 1, 2, e = makeXonoticSlider_T(30, 180, 5, "cl_netfps",
                        _("How many input packets to send to the server each second")));
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Server queries/s:")));
index a14406bcec7202aa518df979bcb29f619f5c90a3..f4417171ff6c6e0b1498bad74f73b5ffd5d4f398 100644 (file)
@@ -103,6 +103,7 @@ void Xonotic_KeyBinds_Read()
        KEYBIND_DEF("+use"                                  , _("drop key / drop flag"));
        KEYBIND_DEF(""                                      , "");
        KEYBIND_DEF(""                                      , _("Misc"));
+       KEYBIND_DEF("kill"                                  , _("respawn"));
        KEYBIND_DEF("quickmenu"                             , _("quick menu"));
        KEYBIND_DEF("menu_showsandboxtools"                 , _("sandbox menu"));
        KEYBIND_DEF("+button8"                              , _("drag object"));
index c98e9fc9b6fa8f082a3bd346dad51c48edd36048..bbff7d551be6b22d04c68b0f2da9a13ba9af9958 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../item.qh"
-CLASS(XonoticPicker, Item)
+CLASS(XonoticPicker, MenuItem)
        METHOD(XonoticPicker, configureXonoticPicker, void(entity));
        METHOD(XonoticPicker, mousePress, bool(XonoticPicker this, vector pos));
        METHOD(XonoticPicker, mouseRelease, float(entity, vector));
index fb4bb92a80b5421e80d65ef05d2cd178c04ef6e7..e994491121a8ae1bf012f6981d7c8fdbc1a7a465 100644 (file)
@@ -689,6 +689,7 @@ float updateCompression()
        GAMETYPE(MAPINFO_TYPE_NEXBALL) \
        GAMETYPE(MAPINFO_TYPE_ONSLAUGHT) \
        GAMETYPE(MAPINFO_TYPE_ASSAULT) \
+       /* GAMETYPE(MAPINFO_TYPE_DUEL) */ \
        /* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
        /**/
 
index 429117ad00cf42f7d73aa7e78a22b737dc17f122..2ec8386955f032bfa6d44bd4396414aea1c27f5b 100644 (file)
@@ -11,7 +11,6 @@
 #include <server/handicap.qc>
 #include <server/impulse.qc>
 #include <server/ipban.qc>
-#include <server/item_key.qc>
 #include <server/items.qc>
 #include <server/mapvoting.qc>
 #include <server/matrix.qc>
index 2bbfb7204df508065c4279227c3ebb92ecf248c1..cc27baf120e93fab2379e7a8643c6e16a1c3c7fe 100644 (file)
@@ -11,7 +11,6 @@
 #include <server/handicap.qh>
 #include <server/impulse.qh>
 #include <server/ipban.qh>
-#include <server/item_key.qh>
 #include <server/items.qh>
 #include <server/mapvoting.qh>
 #include <server/matrix.qh>
index 8a19f06c6e19bb68026cc95a8bba27fcfe97eeb7..b23f6f148175478fbdc9acb885cc71cb3179b045 100644 (file)
@@ -99,6 +99,7 @@ float autocvar_g_ban_sync_timeout;
 string autocvar_g_ban_sync_trusted_servers;
 bool autocvar_g_ban_sync_trusted_servers_verify;
 string autocvar_g_ban_sync_uri;
+bool autocvar_g_ban_telluser = true;
 string autocvar_g_banned_list;
 bool autocvar_g_banned_list_idmode;
 bool autocvar_g_botclip_collisions;
@@ -313,7 +314,6 @@ float autocvar_sv_maxairspeed;
 float autocvar_sv_maxspeed;
 string autocvar_sv_motd;
 bool autocvar_sv_precacheplayermodels;
-//float autocvar_sv_precacheweapons; // WEAPONTODO?
 bool autocvar_sv_q3acompat_machineshotgunswap;
 bool autocvar_sv_servermodelsonly;
 int autocvar_sv_spectate;
@@ -518,4 +518,6 @@ float autocvar_sv_airstopaccelerate;
 float autocvar_sv_track_canjump;
 bool autocvar_sv_showspectators;
 bool autocvar_g_weaponswitch_debug;
+bool autocvar_g_weaponswitch_debug_alternate;
 bool autocvar_g_allow_checkpoints;
+bool autocvar_sv_vq3compat_changehitbox = false;
index b80b498e7253fd0a13008d4ec2f0d214c8178734..0c4668f2f38d3c05eeb5b24e3ff8d44cb861d753 100644 (file)
@@ -594,8 +594,6 @@ float bot_fixcount()
        }
 
        int bots;
-       // add/remove bots if needed to make sure there are at least
-       // minplayers+bot_number, or remove all bots if no one is playing
        // But don't remove bots immediately on level change, as the real players
        // usually haven't rejoined yet
        bots_would_leave = false;
@@ -603,15 +601,17 @@ float bot_fixcount()
                bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
        else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
        {
-               float realminplayers, minplayers;
-               realminplayers = autocvar_minplayers;
-               minplayers = max(0, floor(realminplayers));
+               int minplayers = max(0, floor(autocvar_minplayers));
+               int minbots = max(0, floor(autocvar_bot_number));
 
-               float realminbots, minbots;
-               realminbots = autocvar_bot_number;
-               minbots = max(0, floor(realminbots));
+               // add bots to reach minplayers if needed
+               bots = max(minbots, minplayers - activerealplayers);
+               // cap bots to the max players allowed by the server
+               int player_limit = GetPlayerLimit();
+               if(player_limit)
+                       bots = min(bots, player_limit - activerealplayers);
+               bots = min(bots, maxclients - realplayers);
 
-               bots = min(max(minbots, minplayers - activerealplayers), maxclients - realplayers);
                if(bots > minbots)
                        bots_would_leave = true;
        }
index f5ba20c8a41b1acbe04a1368748eb8cbede98d30..63f1e0179442941435d9dfc6aeb30ef6e8c9d8c4 100644 (file)
@@ -1402,7 +1402,7 @@ void havocbot_chooseweapon(entity this, .entity weaponentity)
        // Should it do a weapon combo?
        float af, ct, combo_time, combo;
 
-       af = ATTACK_FINISHED(this, 0);
+       af = ATTACK_FINISHED(this, weaponentity);
        ct = autocvar_bot_ai_weapon_combo_threshold;
 
        // Bots with no skill will be 4 times more slower than "godlike" bots when doing weapon combos
index 48975b8367e58766668e59027e5e73000b9b4d51..555f6fc58a54c8e898f4472e7ee81577ea99b579 100644 (file)
@@ -1084,12 +1084,12 @@ float bot_cmd_debug_assert_canfire(entity this)
                        LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by weaponentity state");
                }
        }
-       else if(ATTACK_FINISHED(this, slot) > time)
+       else if(ATTACK_FINISHED(this, weaponentity) > time)
        {
                if(f)
                {
                        this.colormod = '8 0 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, weaponentity) - time), " seconds left)");
                }
        }
        else if(this.(weaponentity).tuba_note)
@@ -1105,7 +1105,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(!f)
                {
                        this.colormod = '8 8 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, weaponentity) - time), " seconds left");
                }
        }
 
index e894e85b4fa045026bd09683b8a5dd57f0e02327..5ca5270d614dda0b5212a827c5fa5922162e8f51 100644 (file)
@@ -839,7 +839,7 @@ float Drag(entity this, float force_allow_pick, float ischeat)
                                                }
                                                // Find e and pick
                                                if(e && pick)
-                                                       if(Drag_IsDraggable(e))
+                                                       if(Drag_IsDraggable(e, this))
                                                        {
                                                                if(ischeat)
                                                                        IS_CHEAT(this, 0, 0, CHRAME_DRAG);
@@ -915,31 +915,24 @@ void Drag_Finish(entity dragger)
        }
 }
 
-float Drag_IsDraggable(entity draggee)
+bool drag_undraggable(entity draggee, entity dragger)
+{
+       // stuff probably shouldn't need this, we should figure out why they do!
+       // exceptions of course are observers and weapon entities, where things mess up
+       return false;
+}
+
+float Drag_IsDraggable(entity draggee, entity dragger)
 {
        // TODO add more checks for bad stuff here
        if(draggee == NULL)
                return false;
-       if(draggee.classname == "func_bobbing")
-               return false;
        if(draggee.classname == "door") // FIXME find out why these must be excluded, or work around the problem (trying to drag these causes like 4 fps)
-               return false;
-       if(draggee.classname == "plat")
-               return false;
-       if(draggee.classname == "func_button")
-               return false;
+               return false; // probably due to BSP collision
 //     if(draggee.model == "")
 //             return false;
-       if(IS_SPEC(draggee))
-               return false;
-       if(IS_OBSERVER(draggee))
-               return false;
-       if(draggee.classname == "exteriorweaponentity")
-               return false;
-       if(draggee.classname == "weaponentity")
-               return false;
 
-       return true;
+       return ((draggee.draggable) ? draggee.draggable(draggee, dragger) : true);
 }
 
 float Drag_MayChangeAngles(entity draggee)
@@ -1017,7 +1010,7 @@ float Drag_IsDragging(entity dragger)
                dragger.dragentity = NULL;
                return false;
        }
-       if(!Drag_CanDrag(dragger) || !Drag_IsDraggable(dragger.dragentity))
+       if(!Drag_CanDrag(dragger) || !Drag_IsDraggable(dragger.dragentity, dragger))
        {
                Drag_Finish(dragger);
                return false;
index 0dc6a92d9c45b5f103e432fabaa59f8c3db45bb1..962e017a19d6dad9e4919c86d53b20bb92efb84c 100644 (file)
@@ -14,12 +14,15 @@ float CheatFrame(entity this);
 
 const float CHRAME_DRAG = 8;
 
+bool drag_undraggable(entity draggee, entity dragger);
+
+.bool(entity this, entity dragger) draggable;
 void Drag_MoveDrag(entity from, entity to); // call this from CopyBody
 void DragBox_Think(entity this);
 float Drag(entity this, float force_allow_pick, float ischeat);
 void Drag_Begin(entity dragger, entity draggee, vector touchpoint);
 void Drag_Finish(entity dragger);
-float Drag_IsDraggable(entity draggee);
+bool Drag_IsDraggable(entity draggee, entity dragger);
 float Drag_MayChangeAngles(entity draggee);
 void Drag_MoveForward(entity dragger);
 void Drag_SetSpeed(entity dragger, float s);
index 8b70a633af9ebc59a394e1093684a34d852d7470..01c8222e62de1597fb561a31590f8bcb164e9b04 100644 (file)
 #include "../common/wepent.qh"
 #include <common/state.qh>
 
+#include "compat/quake3.qh"
+
 #include <common/effects/qc/globalsound.qh>
 
 #include "../common/mapobjects/func/conveyor.qh"
 #include "../common/mapobjects/teleporters.qh"
 #include "../common/mapobjects/target/spawnpoint.qh"
+#include <common/mapobjects/trigger/counter.qh>
 
 #include "../common/vehicles/all.qh"
 
@@ -271,7 +274,7 @@ void PutObserverInServer(entity this)
 
     RemoveGrapplingHooks(this);
        Portal_ClearAll(this);
-       Unfreeze(this);
+       Unfreeze(this, false);
        SetSpectatee(this, NULL);
 
        if (this.alivetime)
@@ -344,6 +347,7 @@ void PutObserverInServer(entity this)
        this.crouch = false;
        STAT(REVIVE_PROGRESS, this) = 0;
        this.revival_time = 0;
+       this.draggable = drag_undraggable;
 
        this.items = 0;
        STAT(WEAPONS, this) = '0 0 0';
@@ -674,6 +678,8 @@ void PutPlayerInServer(entity this)
        this.event_damage = PlayerDamage;
        this.event_heal = PlayerHeal;
 
+       this.draggable = func_null;
+
        if(!this.bot_attack)
                IL_PUSH(g_bot_targets, this);
        this.bot_attack = true;
@@ -705,6 +711,9 @@ void PutPlayerInServer(entity this)
 
        this.speedrunning = false;
 
+       this.counter_cnt = 0;
+       this.fragsfilter_cnt = 0;
+
        target_voicescript_clear(this);
 
        // reset fields the weapons may use
@@ -721,13 +730,13 @@ void PutPlayerInServer(entity this)
        });
 
        {
-               string s = spot.target;
-               spot.target = string_null;
+               //string s = spot.target;
+               //spot.target = string_null;
                SUB_UseTargets(spot, this, NULL);
-               spot.target = s;
+               //spot.target = s;
        }
 
-       Unfreeze(this);
+       Unfreeze(this, false);
 
        MUTATOR_CALLHOOK(PlayerSpawn, this, spot);
 
@@ -1137,6 +1146,8 @@ void ClientConnect(entity this)
        if (IS_REAL_CLIENT(this))
                sv_notice_join(this);
 
+       this.move_qcphysics = true;
+
        // update physics stats (players can spawn before physics runs)
        Physics_UpdateStats(this);
 
@@ -1190,7 +1201,7 @@ void ClientDisconnect(entity this)
 
        Portal_ClearAll(this);
 
-       Unfreeze(this);
+       Unfreeze(this, false);
 
        RemoveGrapplingHooks(this);
 
@@ -1230,7 +1241,7 @@ void ChatBubbleThink(entity this)
 
        if ( !IS_DEAD(this.owner) && IS_PLAYER(this.owner) )
        {
-               if ( CS(this.owner).active_minigame )
+               if ( CS(this.owner).active_minigame && PHYS_INPUT_BUTTON_MINIGAME(this.owner) )
                        this.mdl = "models/sprites/minigame_busy.iqm";
                else if (PHYS_INPUT_BUTTON_CHAT(this.owner))
                        this.mdl = "models/misc/chatbubble.spr";
@@ -1905,6 +1916,14 @@ void Join(entity this)
        this.team_selected = false;
 }
 
+int GetPlayerLimit()
+{
+       int player_limit = autocvar_g_maxplayers;
+       MUTATOR_CALLHOOK(GetPlayerLimit, player_limit);
+       player_limit = M_ARGV(0, int);
+       return player_limit;
+}
+
 /**
  * Determines whether the player is allowed to join. This depends on cvar
  * g_maxplayers, if it isn't used this function always return true, otherwise
@@ -1937,11 +1956,13 @@ int nJoinAllowed(entity this, entity ignore)
                        ++currentlyPlaying;
        });
 
+       int player_limit = GetPlayerLimit();
+
        float free_slots = 0;
-       if (!autocvar_g_maxplayers)
+       if (!player_limit)
                free_slots = maxclients - totalClients;
-       else if(currentlyPlaying < autocvar_g_maxplayers)
-               free_slots = min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
+       else if(currentlyPlaying < player_limit)
+               free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying);
 
        static float join_prevent_msg_time = 0;
        if(this && ignore && !free_slots && time > join_prevent_msg_time)
@@ -2398,16 +2419,16 @@ void PlayerPreThink (entity this)
 
        if(IS_PLAYER(this))
        {
-               if (STAT(FROZEN, this) == 2)
+               if (STAT(FROZEN, this) == FROZEN_TEMP_REVIVING)
                {
                        STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) + frametime * this.revive_speed, 1);
                        SetResourceAmountExplicit(this, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, this) * start_health));
                        this.iceblock.alpha = bound(0.2, 1 - STAT(REVIVE_PROGRESS, this), 1);
 
                        if (STAT(REVIVE_PROGRESS, this) >= 1)
-                               Unfreeze(this);
+                               Unfreeze(this, false);
                }
-               else if (STAT(FROZEN, this) == 3)
+               else if (STAT(FROZEN, this) == FROZEN_TEMP_DYING)
                {
                        STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) - frametime * this.revive_speed, 1);
                        SetResourceAmountExplicit(this, RESOURCE_HEALTH, max(0, autocvar_g_nades_ice_health + (start_health-autocvar_g_nades_ice_health) * STAT(REVIVE_PROGRESS, this)));
@@ -2420,7 +2441,7 @@ void PlayerPreThink (entity this)
                                        this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, DMG_NOWEP, this.origin, '0 0 0');
                        }
                        else if (STAT(REVIVE_PROGRESS, this) <= 0)
-                               Unfreeze(this);
+                               Unfreeze(this, false);
                }
        }
 
@@ -2556,7 +2577,7 @@ void DrownPlayer(entity this)
 
 void Player_Physics(entity this)
 {
-       set_movetype(this, this.move_movetype);
+       this.movetype = (this.move_qcphysics) ? MOVETYPE_QCPLAYER : this.move_movetype;
 
        if(!this.move_qcphysics)
                return;
@@ -2661,6 +2682,311 @@ void PlayerPostThink (entity this)
        CSQCMODEL_AUTOUPDATE(this);
 }
 
+/**
+ * message "": do not say, just test flood control
+ * return value:
+ *   1 = accept
+ *   0 = reject
+ *  -1 = fake accept
+ */
+int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
+{
+       if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
+               msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
+
+       if (source)
+               msgin = formatmessage(source, msgin);
+
+       string colorstr;
+       if (!(IS_PLAYER(source) || source.caplayer))
+               colorstr = "^0"; // black for spectators
+       else if(teamplay)
+               colorstr = Team_ColorCode(source.team);
+       else
+       {
+               colorstr = "";
+               teamsay = false;
+       }
+
+       if(game_stopped)
+               teamsay = false;
+
+       if (!source) {
+               colorstr = "";
+               teamsay = false;
+       }
+
+       if(msgin != "")
+               msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
+
+       /*
+        * using bprint solves this... me stupid
+       // how can we prevent the message from appearing in a listen server?
+       // for now, just give "say" back and only handle say_team
+       if(!teamsay)
+       {
+               clientcommand(source, strcat("say ", msgin));
+               return;
+       }
+       */
+
+       string namestr = "";
+       if (source)
+               namestr = playername(source, autocvar_g_chat_teamcolors);
+
+       string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
+
+       string msgstr = "", cmsgstr = "";
+       string privatemsgprefix = string_null;
+       int privatemsgprefixlen = 0;
+       if (msgin != "")
+       {
+               if(privatesay)
+               {
+                       msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
+                       privatemsgprefixlen = strlen(msgstr);
+                       msgstr = strcat(msgstr, msgin);
+                       cmsgstr = strcat(colorstr, colorprefix, namestr, "^3 tells you:\n^7", msgin);
+                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay, autocvar_g_chat_teamcolors), ": ^7");
+               }
+               else if(teamsay)
+               {
+                       if(strstrofs(msgin, "/me", 0) >= 0)
+                       {
+                               //msgin = strreplace("/me", "", msgin);
+                               //msgin = substring(msgin, 3, strlen(msgin));
+                               msgin = strreplace("/me", strcat(colorstr, "(", colorprefix, namestr, colorstr, ")^7"), msgin);
+                               msgstr = strcat("\{1}\{13}^4* ", "^7", msgin);
+                       }
+                       else
+                               msgstr = strcat("\{1}\{13}", colorstr, "(", colorprefix, namestr, colorstr, ") ^7", msgin);
+                       cmsgstr = strcat(colorstr, "(", colorprefix, namestr, colorstr, ")\n^7", msgin);
+               }
+               else
+               {
+                       if(strstrofs(msgin, "/me", 0) >= 0)
+                       {
+                               //msgin = strreplace("/me", "", msgin);
+                               //msgin = substring(msgin, 3, strlen(msgin));
+                               msgin = strreplace("/me", strcat(colorprefix, namestr), msgin);
+                               msgstr = strcat("\{1}^4* ", "^7", msgin);
+                       }
+                       else {
+                               msgstr = "\{1}";
+                               msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
+                               msgstr = strcat(msgstr, msgin);
+                       }
+                       cmsgstr = "";
+               }
+               msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
+       }
+
+       string fullmsgstr = msgstr;
+       string fullcmsgstr = cmsgstr;
+
+       // FLOOD CONTROL
+       int flood = 0;
+       var .float flood_field = floodcontrol_chat;
+       if(floodcontrol && source)
+       {
+               float flood_spl;
+               float flood_burst;
+               float flood_lmax;
+               float lines;
+               if(privatesay)
+               {
+                       flood_spl = autocvar_g_chat_flood_spl_tell;
+                       flood_burst = autocvar_g_chat_flood_burst_tell;
+                       flood_lmax = autocvar_g_chat_flood_lmax_tell;
+                       flood_field = floodcontrol_chattell;
+               }
+               else if(teamsay)
+               {
+                       flood_spl = autocvar_g_chat_flood_spl_team;
+                       flood_burst = autocvar_g_chat_flood_burst_team;
+                       flood_lmax = autocvar_g_chat_flood_lmax_team;
+                       flood_field = floodcontrol_chatteam;
+               }
+               else
+               {
+                       flood_spl = autocvar_g_chat_flood_spl;
+                       flood_burst = autocvar_g_chat_flood_burst;
+                       flood_lmax = autocvar_g_chat_flood_lmax;
+                       flood_field = floodcontrol_chat;
+               }
+               flood_burst = max(0, flood_burst - 1);
+               // to match explanation in default.cfg, a value of 3 must allow three-line bursts and not four!
+
+               // do flood control for the default line size
+               if(msgstr != "")
+               {
+                       getWrappedLine_remaining = msgstr;
+                       msgstr = "";
+                       lines = 0;
+                       while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
+                       {
+                               msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
+                               ++lines;
+                       }
+                       msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
+
+                       if(getWrappedLine_remaining != "")
+                       {
+                               msgstr = strcat(msgstr, "\n");
+                               flood = 2;
+                       }
+
+                       if (time >= source.(flood_field))
+                       {
+                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + lines * flood_spl;
+                       }
+                       else
+                       {
+                               flood = 1;
+                               msgstr = fullmsgstr;
+                       }
+               }
+               else
+               {
+                       if (time >= source.(flood_field))
+                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + flood_spl;
+                       else
+                               flood = 1;
+               }
+
+               if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection
+                       source.(flood_field) = flood = 0;
+       }
+
+       string sourcemsgstr, sourcecmsgstr;
+       if(flood == 2) // cannot happen for empty msgstr
+       {
+               if(autocvar_g_chat_flood_notify_flooder)
+               {
+                       sourcemsgstr = strcat(msgstr, "\n^3FLOOD CONTROL: ^7message too long, trimmed\n");
+                       sourcecmsgstr = "";
+               }
+               else
+               {
+                       sourcemsgstr = fullmsgstr;
+                       sourcecmsgstr = fullcmsgstr;
+               }
+               cmsgstr = "";
+       }
+       else
+       {
+               sourcemsgstr = msgstr;
+               sourcecmsgstr = cmsgstr;
+       }
+
+       if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer))
+       {
+               if (!game_stopped)
+               if (teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
+                       teamsay = -1; // spectators
+       }
+
+       if(flood)
+               LOG_INFO("NOTE: ", playername(source, true), "^7 is flooding.");
+
+       // build sourcemsgstr by cutting off a prefix and replacing it by the other one
+       if(privatesay)
+               sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
+
+       int ret;
+       if(source && CS(source).muted)
+       {
+               // always fake the message
+               ret = -1;
+       }
+       else if(flood == 1)
+       {
+               if (autocvar_g_chat_flood_notify_flooder)
+               {
+                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - time), "^3 seconds\n"));
+                       ret = 0;
+               }
+               else
+                       ret = -1;
+       }
+       else
+       {
+               ret = 1;
+       }
+
+       if (privatesay && source && !(IS_PLAYER(source) || source.caplayer))
+       {
+               if (!game_stopped)
+               if ((privatesay && (IS_PLAYER(privatesay) || privatesay.caplayer)) && ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage)))
+                       ret = -1; // just hide the message completely
+       }
+
+       MUTATOR_CALLHOOK(ChatMessage, source, ret);
+       ret = M_ARGV(1, int);
+
+       if(sourcemsgstr != "" && ret != 0)
+       {
+               if(ret < 0) // faked message, because the player is muted
+               {
+                       sprint(source, sourcemsgstr);
+                       if(sourcecmsgstr != "" && !privatesay)
+                               centerprint(source, sourcecmsgstr);
+               }
+               else if(privatesay) // private message, between 2 people only
+               {
+                       sprint(source, sourcemsgstr);
+                       if (!autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
+                       if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
+                       {
+                               sprint(privatesay, msgstr);
+                               if(cmsgstr != "")
+                                       centerprint(privatesay, cmsgstr);
+                       }
+               }
+               else if ( teamsay && CS(source).active_minigame )
+               {
+                       sprint(source, sourcemsgstr);
+                       dedicated_print(msgstr); // send to server console too
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
+               }
+               else if(teamsay > 0) // team message, only sent to team mates
+               {
+                       sprint(source, sourcemsgstr);
+                       dedicated_print(msgstr); // send to server console too
+                       if(sourcecmsgstr != "")
+                               centerprint(source, sourcecmsgstr);
+                       FOREACH_CLIENT((IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                               if(cmsgstr != "")
+                                       centerprint(it, cmsgstr);
+                       });
+               }
+               else if(teamsay < 0) // spectator message, only sent to spectators
+               {
+                       sprint(source, sourcemsgstr);
+                       dedicated_print(msgstr); // send to server console too
+                       FOREACH_CLIENT(!(IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
+               }
+               else
+               {
+                       if (source) {
+                               sprint(source, sourcemsgstr);
+                               dedicated_print(msgstr); // send to server console too
+                               MX_Say(strcat(playername(source, true), "^7: ", msgin));
+                       }
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
+               }
+       }
+
+       return ret;
+}
+
 // hack to copy the button fields from the client entity to the Client State
 void PM_UpdateButtons(entity this, entity store)
 {
@@ -2668,7 +2994,7 @@ void PM_UpdateButtons(entity this, entity store)
                store.impulse = this.impulse;
        this.impulse = 0;
 
-       bool typing = this.buttonchat;
+       bool typing = this.buttonchat || this.button14;
 
        store.button0 = (typing) ? 0 : this.button0;
        //button1?!
index 099fac9f541f5ae71358f2fad6f2e0894a978e14..f8a7e2ab5fa4063b29ebe4c96c7f32ddfca42127 100644 (file)
@@ -17,7 +17,7 @@ CLASS(Client, Object)
     /** Client IP */
     ATTRIB(Client, netaddress, string, this.netaddress);
     ATTRIB(Client, playermodel, string, this.playermodel);
-    ATTRIB(Client, playerskin, int, this.playerskin);
+    ATTRIB(Client, playerskin, string, this.playerskin);
 
     /** fingerprint of CA key the player used to authenticate */
     ATTRIB(Client, crypto_keyfp, string, this.crypto_keyfp);
@@ -145,6 +145,7 @@ CLASS(Client, Object)
     ATTRIB(Client, cvar_cl_accuracy_data_receive, bool, this.cvar_cl_accuracy_data_receive);
     ATTRIBARRAY(Client, cvar_cl_weaponpriorities, string, 10);
     ATTRIB(Client, cvar_cl_weaponpriority, string, this.cvar_cl_weaponpriority);
+    ATTRIB(Client, cvar_cl_cts_noautoswitch, bool, this.cvar_cl_cts_noautoswitch);
 
     METHOD(Client, m_unwind, bool(Client this));
 
@@ -276,8 +277,12 @@ void FixPlayermodel(entity player);
 
 void ClientInit_misc(entity this);
 
+int GetPlayerLimit();
+
 bool joinAllowed(entity this);
 void Join(entity this);
 
 #define SPECTATE_COPY() ACCUMULATE void SpectateCopy(entity this, entity spectatee)
 #define SPECTATE_COPYFIELD(fld) SPECTATE_COPY() { this.(fld) = spectatee.(fld); }
+
+int Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol);
index 8d7293bb066214c1f5e47535be2ab93453f47c46..08758a06536f706bd722e6ed57549e0ae1b6d154 100644 (file)
@@ -195,8 +195,6 @@ void ClientKill_Silent(entity this, float _delay)
 // Called when a client types 'kill' in the console
 void ClientKill(entity this)
 {
-       // TODO: once .health is removed, will need to check it here for the "already dead" message!
-
        if (game_stopped || this.player_blocked || STAT(FROZEN, this))
                return;
 
index 915fea7ee0ca2ca02ffb14d9341d539b4b4a7d14..80716d811c8e1da75124b95edb4a23b2e2ea5150 100644 (file)
@@ -247,6 +247,36 @@ void ClientCommand_join(entity caller, int request)
        }
 }
 
+void ClientCommand_kill(entity caller, int request)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if(IS_SPEC(caller) || IS_OBSERVER(caller))
+                               return; // no point warning about this, command does nothing
+
+                       if(GetResourceAmount(caller, RESOURCE_HEALTH) <= 0)
+                       {
+                               sprint(caller, "Can't die - you are already dead!\n");
+                               return;
+                       }
+
+                       ClientKill(caller);
+
+                       return;  // never fall through to usage
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(caller, "\nUsage:^3 cmd kill\n");
+                       sprint(caller, "  No arguments required.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_physics(entity caller, int request, int argc)
 {
        switch (request)
@@ -730,6 +760,7 @@ void ClientCommand_(entity caller, int request)
        CLIENT_COMMAND("autoswitch", ClientCommand_autoswitch(ent, request, arguments), "Whether or not to switch automatically when getting a better weapon") \
        CLIENT_COMMAND("clientversion", ClientCommand_clientversion(ent, request, arguments), "Release version of the game") \
        CLIENT_COMMAND("join", ClientCommand_join(ent, request), "Become a player in the game") \
+       CLIENT_COMMAND("kill", ClientCommand_kill(ent, request), "Become a member of the dead") \
        CLIENT_COMMAND("minigame", ClientCommand_minigame(ent, request, arguments, command), "Start a minigame") \
        CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(ent, request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("physics", ClientCommand_physics(ent, request, arguments), "Change physics set") \
index 83c62cd2b004a60fd641f27f401b4fa5ab426c2e..51cf55ce3a1de3ee3c83cc027348ae803f7e072e 100644 (file)
@@ -365,7 +365,7 @@ void reset_map(bool dorespawn)
                if (it.reset2) it.reset2(it);
        });
 
-       FOREACH_CLIENT(IS_PLAYER(it) && STAT(FROZEN, it), { Unfreeze(it); });
+       FOREACH_CLIENT(IS_PLAYER(it) && STAT(FROZEN, it), { Unfreeze(it, false); });
 
        // Moving the player reset code here since the player-reset depends
        // on spawnpoint entities which have to be reset first --blub
@@ -835,14 +835,15 @@ void VoteCommand_call(int request, entity caller, int argc, string vote_command)
                                }
 
                                FOREACH_CLIENT(IS_REAL_CLIENT(it), { ++tmp_playercount; });
-                               if (tmp_playercount > 1)
-                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_VOTE_CALL);
 
                                bprint("\{1}^2* ^3", OriginalCallerName(), "^2 calls a vote for ", vote_called_display, "\n");
                                if (autocvar_sv_eventlog)
                                        GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display));
                                Nagger_VoteChanged();
                                VoteCount(true);  // needed if you are the only one
+
+                               if (tmp_playercount > 1 && vote_called != VOTE_NULL)
+                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_VOTE_CALL);
                        }
 
                        return;
index 4511100581b7d74a89f45e955292f74ce45d04a7..65f231374f56a8053f23a2c2cce49f98df729c15 100644 (file)
@@ -6,6 +6,7 @@
 #include <server/resources.qh>
 #include <common/t_items.qh>
 #include <common/mapobjects/triggers.qh>
+#include <common/mapobjects/trigger/counter.qh>
 #include <common/weapons/_all.qh>
 
 //***********************
@@ -183,6 +184,37 @@ spawnfunc(target_give)
        InitializeEntity(this, target_give_init, INITPRIO_FINDTARGET);
 }
 
+void score_use(entity this, entity actor, entity trigger)
+{
+       if(!IS_PLAYER(actor))
+               return;
+       actor.fragsfilter_cnt += this.count;
+}
+spawnfunc(target_score)
+{
+       if(!g_cts) { delete(this); return; }
+
+       if(!this.count)
+               this.count = 1;
+       this.use = score_use;
+}
+
+void fragsfilter_use(entity this, entity actor, entity trigger)
+{
+       if(!IS_PLAYER(actor))
+               return;
+       if(actor.fragsfilter_cnt >= this.frags)
+               SUB_UseTargets(this, actor, trigger);
+}
+spawnfunc(target_fragsFilter)
+{
+       if(!g_cts) { delete(this); return; }
+
+       if(!this.frags)
+               this.frags = 1;
+       this.use = fragsfilter_use;
+}
+
 //spawnfunc(item_flight)       /* handled by buffs mutator */
 //spawnfunc(item_haste)        /* handled by buffs mutator */
 //spawnfunc(item_health)       /* handled in t_quake.qc */
@@ -233,6 +265,8 @@ bool DoesQ3ARemoveThisEntity(entity this)
                        gametypename = "team";
                if(g_ctf)
                        gametypename = "ctf";
+               if(g_duel)
+                       gametypename = "tournament";
                if(maxclients == 1)
                        gametypename = "single";
                // we do not have the other types (oneflag, obelisk, harvester, teamtournament)
index 342a829a187b12daa84a0b532bc0269aca79c16b..20e4879d9a37596290a2a24258a7d69db623e21a 100644 (file)
@@ -1,3 +1,5 @@
 #pragma once
 
 bool DoesQ3ARemoveThisEntity(entity this);
+
+.int fragsfilter_cnt;
index 58111fb12bcfea9482a8d89b6d0dbceaf31ab42e..e667906f1dddb3351a48b6d9c5543fdadcf39f4d 100644 (file)
@@ -168,6 +168,7 @@ float default_weapon_alpha;
 .float cvar_cl_jetpack_jump;
 .float cvar_cl_movement_track_canjump;
 .float cvar_cl_newusekeysupported;
+.float cvar_cl_cts_noautoswitch;
 
 .string cvar_g_xonoticversion;
 .string cvar_cl_weaponpriority;
@@ -201,10 +202,7 @@ float bot_waypoints_for_items;
 #else
 #define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot])
 #endif
-#define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, ent.(weaponentity).m_weapon.m_id, slot)
-
-// assault game mode: Which team is attacking in this round?
-float assault_attacker_team;
+#define ATTACK_FINISHED(ent, w) ATTACK_FINISHED_FOR(ent, ent.(w).m_weapon.m_id, weaponslot(w))
 
 // speedrun: when 1, player auto teleports back when capture timeout happens
 .float speedrunning;
@@ -340,6 +338,11 @@ string deathmessage;
 
 .float ballistics_density; // wall piercing factor, larger = bullet can pass through more
 
+//const int FROZEN_NOT                         = 0;
+const int FROZEN_NORMAL                                = 1;
+const int FROZEN_TEMP_REVIVING         = 2;
+const int FROZEN_TEMP_DYING                    = 3;
+
 const int ACTIVE_NOT           = 0;
 const int ACTIVE_ACTIVE        = 1;
 const int ACTIVE_IDLE          = 2;
index 4964bf91e71014cea100bed1b76e5c784d8e91c4..e9ab3d79ac945a2fa9cec1cf2a392b16aa72fbe0 100644 (file)
@@ -489,8 +489,8 @@ void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
        float targ_maxhealth = ((IS_MONSTER(targ)) ? targ.max_health : start_health);
 
        STAT(FROZEN, targ) = frozen_type;
-       STAT(REVIVE_PROGRESS, targ) = ((frozen_type == 3) ? 1 : 0);
-       SetResourceAmount(targ, RESOURCE_HEALTH, ((frozen_type == 3) ? targ_maxhealth : 1));
+       STAT(REVIVE_PROGRESS, targ) = ((frozen_type == FROZEN_TEMP_DYING) ? 1 : 0);
+       SetResourceAmount(targ, RESOURCE_HEALTH, ((frozen_type == FROZEN_TEMP_DYING) ? targ_maxhealth : 1));
        targ.revive_speed = revivespeed;
        if(targ.bot_attack)
                IL_REMOVE(g_bot_targets, targ);
@@ -529,16 +529,15 @@ void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
                WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', NULL, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
 }
 
-void Unfreeze(entity targ)
+void Unfreeze(entity targ, bool reset_health)
 {
        if(!STAT(FROZEN, targ))
                return;
 
-       if(STAT(FROZEN, targ) && STAT(FROZEN, targ) != 3) // only reset health if target was frozen
-       {
+       if (reset_health && STAT(FROZEN, targ) != FROZEN_TEMP_DYING)
                SetResourceAmount(targ, RESOURCE_HEALTH, ((IS_PLAYER(targ)) ? start_health : targ.max_health));
-               targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
-       }
+
+       targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
 
        STAT(FROZEN, targ) = 0;
        STAT(REVIVE_PROGRESS, targ) = 0;
@@ -697,7 +696,7 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
                        if(deathtype == DEATH_FALL.m_id)
                        if(damage >= autocvar_g_frozen_revive_falldamage)
                        {
-                               Unfreeze(targ);
+                               Unfreeze(targ, false);
                                SetResourceAmount(targ, RESOURCE_HEALTH, autocvar_g_frozen_revive_falldamage_health);
                                Send_Effect(EFFECT_ICEORGLASS, targ.origin, '0 0 0', 3);
                                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
@@ -1054,7 +1053,7 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
        RadiusDamage_running = 0;
 
        if(!DEATH_ISSPECIAL(deathtype))
-               accuracy_add(attacker, DEATH_WEAPONOF(deathtype).m_id, 0, min(coredamage, stat_damagedone));
+               accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(coredamage, stat_damagedone));
 
        return total_damage_to_creatures;
 }
@@ -1183,7 +1182,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
                                }
                        }
                        if(accuracy_isgooddamage(o, e))
-                               accuracy_add(o, DEATH_WEAPONOF(dt).m_id, 0, max(0, totaldamage - mindamage));
+                               accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage));
                        return max(0, totaldamage - mindamage); // can never be negative, but to make sure
                }
                else
@@ -1197,7 +1196,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
                e.fire_owner = o;
                e.fire_hitsound = false;
                if(accuracy_isgooddamage(o, e))
-                       accuracy_add(o, DEATH_WEAPONOF(dt).m_id, 0, d);
+                       accuracy_add(o, DEATH_WEAPONOF(dt), 0, d);
                return d;
        }
 }
@@ -1236,11 +1235,11 @@ void Fire_ApplyDamage(entity e)
        }
        e.fire_hitsound = true;
 
-       if(!IS_INDEPENDENT_PLAYER(e))
-       if(!STAT(FROZEN, e))
-               FOREACH_CLIENT(IS_PLAYER(it) && it != e, {
-                       if(!IS_DEAD(it))
-                       if(!IS_INDEPENDENT_PLAYER(it))
+       if(!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e))
+       {
+               IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
+               {
+                       if(!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it))
                        if(boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
                        {
                                t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
@@ -1248,6 +1247,7 @@ void Fire_ApplyDamage(entity e)
                                Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
                        }
                });
+       }
 }
 
 void Fire_ApplyEffect(entity e)
index 617eca1985108e4ca82fc2b31167a8b23c69ff9b..1d100e7a5a86874b2be4ed55771584f708581fd0 100644 (file)
@@ -85,7 +85,7 @@ void Ice_Think(entity this);
 
 void Freeze(entity targ, float freeze_time, int frozen_type, bool show_waypoint);
 
-void Unfreeze (entity targ);
+void Unfreeze(entity targ, bool reset_health);
 
 // NOTE: the .weaponentity parameter can be set to DMG_NOWEP if the attack wasn't caused by a weapon or player
 void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
index 038936ee49282bff375700dd76159197aea86d8f..522f4f041cc49af4810c0f53fb2070f30c4e75e4 100644 (file)
@@ -265,6 +265,7 @@ void cvar_changes_init()
                BADCVAR("g_dm");
                BADCVAR("g_domination");
                BADCVAR("g_domination_default_teams");
+               BADCVAR("g_duel");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
                BADCVAR("g_invasion_teams");
@@ -1611,7 +1612,9 @@ float InitiateSuddenDeath()
        // - for this timelimit_overtime needs to be >0 of course
        // - also check the winning condition calculated in the previous frame and only add normal overtime
        //   again, if at the point at which timelimit would be extended again, still no winner was found
-       if (!autocvar_g_campaign && (checkrules_overtimesadded >= 0) && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0) && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
+       if (!autocvar_g_campaign && checkrules_overtimesadded >= 0
+               && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0)
+               && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
        {
                return 1; // need to call InitiateOvertime later
        }
@@ -1634,11 +1637,7 @@ void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
 {
        ++checkrules_overtimesadded;
        //add one more overtime by simply extending the timelimit
-       float tl;
-       tl = autocvar_timelimit;
-       tl += autocvar_timelimit_overtime;
-       cvar_set("timelimit", ftos(tl));
-
+       cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
        Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
 }
 
@@ -1777,7 +1776,7 @@ float WinningCondition_RanOutOfSpawns()
        {
                Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
        }
-       
+
        FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
        {
                if (Team_IsValidTeam(it.team))
index cce5963990893d7a4178e8b7d5e0ddd7895b886e..8a17ef6a1dd44abfca2b064b20434285a5df1054 100644 (file)
@@ -149,7 +149,7 @@ X(9, next)
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) \
                { \
                        .entity weaponentity = weaponentities[slot]; \
-                       W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i), weaponentity); \
+                       W_SwitchWeapon_TryOthers(this, Weapons_from(WEP_FIRST + i), weaponentity); \
                        if(slot == 0 && autocvar_g_weaponswitch_debug != 1) \
                                break; \
                } \
index 7b1f69384461b5d6f3c95e2e8c8054e24562279c..7c6fcbafef635c9aff2bddca7ab30ec8c23d45de 100644 (file)
@@ -446,6 +446,8 @@ bool Ban_MaybeEnforceBan(entity client)
        if (Ban_IsClientBanned(client, -1))
        {
                string s = sprintf("^1NOTE:^7 banned client %s just tried to enter\n", client.netaddress);
+               if(autocvar_g_ban_telluser)
+                       sprint(client, "You are banned from this server.\n");
                dropclient(client);
                bprint(s);
                return true;
diff --git a/qcsrc/server/item_key.qc b/qcsrc/server/item_key.qc
deleted file mode 100644 (file)
index 2bfdc49..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-#include "item_key.qh"
-
-#include "../common/mapobjects/subs.qh"
-#include <common/mapobjects/triggers.qh>
-#include "../common/monsters/_mod.qh"
-#include "../common/notifications/all.qh"
-#include "../common/util.qh"
-#include "../lib/warpzone/util_server.qh"
-
-/*
-TODO:
-- add an unlock sound (here to trigger_keylock and to func_door)
-- display available keys on the HUD
-- make more tests
-- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
-- should keys have a trigger?
-*/
-
-bool item_keys_usekey(entity l, entity p)
-{
-       int valid = l.itemkeys & PS(p).itemkeys;
-
-       if (!valid) {
-               // player has none of the needed keys
-               return false;
-       } else if (l.itemkeys == valid) {
-               // ALL needed keys were given
-               l.itemkeys = 0;
-               return true;
-       } else {
-               // only some of the needed keys were given
-               l.itemkeys &= ~valid;
-               return true;
-       }
-}
-
-string item_keys_keylist(float keylist) {
-       // no keys
-       if (!keylist)
-               return "";
-
-       // one key
-       if ((keylist & (keylist-1)) == 0)
-               return strcat("the ", item_keys_names[lowestbit(keylist)]);
-
-       string n = "";
-       int base = 0;
-       while (keylist) {
-               int l = lowestbit(keylist);
-               if (n)
-                       n = strcat(n, ", the ", item_keys_names[base + l]);
-               else
-                       n = strcat("the ", item_keys_names[base + l]);
-
-               keylist = bitshift(keylist,  -(l + 1));
-               base+= l + 1;
-       }
-
-       return n;
-}
-
-
-/*
-================================
-item_key
-================================
-*/
-
-/**
- * Key touch handler.
- */
-void item_key_touch(entity this, entity toucher)
-{
-       if (!IS_PLAYER(toucher))
-               return;
-
-       // player already picked up this key
-       if (PS(toucher).itemkeys & this.itemkeys)
-               return;
-
-       PS(toucher).itemkeys |= this.itemkeys;
-       play2(toucher, this.noise);
-
-       centerprint(toucher, this.message);
-
-       string oldmsg = this.message;
-       this.message = "";
-       SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here?
-       this.message = oldmsg;
-}
-
-/**
- * Spawn a key with given model, key code and color.
- */
-void spawn_item_key(entity this)
-{
-       precache_model(this.model);
-
-       if (this.spawnflags & 1) // FLOATING
-               this.noalign = 1;
-
-       if (this.noalign)
-               set_movetype(this, MOVETYPE_NONE);
-       else
-               set_movetype(this, MOVETYPE_TOSS);
-
-       precache_sound(this.noise);
-
-       this.mdl = this.model;
-       this.effects = EF_LOWPRECISION;
-       _setmodel(this, this.model);
-       //setsize(this, '-16 -16 -24', '16 16 32');
-       setorigin(this, this.origin + '0 0 32');
-       setsize(this, '-16 -16 -56', '16 16 0');
-       this.modelflags |= MF_ROTATE;
-       this.solid = SOLID_TRIGGER;
-
-       if (!this.noalign)
-       {
-               // first nudge it off the floor a little bit to avoid math errors
-               setorigin(this, this.origin + '0 0 1');
-               // note droptofloor returns false if stuck/or would fall too far
-               droptofloor(this);
-       }
-
-       settouch(this, item_key_touch);
-}
-
-
-/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-A key entity.
-The itemkeys should contain one of the following key IDs:
-1 - GOLD key -
-2 - SILVER key
-4 - BRONZE key
-8 - RED keycard
-16 - BLUE keycard
-32 - GREEN keycard
-Custom keys:
-... - last key is 1<<23
-Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
------------KEYS------------
-colormod: color of the key (default: '.9 .9 .9').
-itemkeys: a key Id.
-message: message to print when player picks up this key.
-model: custom key model to use.
-netname: the display name of the key.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-This is the only correct way to put keys on the map!
-
-itemkeys MUST always have exactly one bit set.
-*/
-spawnfunc(item_key)
-{
-       string _netname;
-       vector _colormod;
-
-       // reject this entity if more than one key was set!
-       if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) {
-               objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
-               delete(this);
-               return;
-       }
-
-       // find default netname and colormod
-       switch(this.itemkeys) {
-       case BIT(0):
-               _netname = "GOLD key";
-               _colormod = '1 .9 0';
-               break;
-
-       case BIT(1):
-               _netname = "SILVER key";
-               _colormod = '.9 .9 .9';
-               break;
-
-       case BIT(2):
-               _netname = "BRONZE key";
-               _colormod = '.6 .25 0';
-               break;
-
-       case BIT(3):
-               _netname = "RED keycard";
-               _colormod = '.9 0 0';
-               break;
-
-       case BIT(4):
-               _netname = "BLUE keycard";
-               _colormod = '0 0 .9';
-               break;
-
-       case BIT(5):
-               _netname = "GREEN keycard";
-               _colormod = '0 .9 0';
-               break;
-
-       default:
-               _netname = "FLUFFY PINK keycard";
-               _colormod = '1 1 1';
-
-               if (this.netname == "") {
-                       objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!");
-                       delete(this);
-                       return;
-               }
-               break;
-
-       }
-
-       // find default model
-       string _model = string_null;
-       if (this.itemkeys <= ITEM_KEY_BIT(2)) {
-               _model = "models/keys/key.md3";
-       } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) {
-               _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
-       } else if (this.model == "") {
-               objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!");
-               delete(this);
-               return;
-       }
-
-       // set defailt netname
-       if (this.netname == "")
-               this.netname = _netname;
-
-       // set default colormod
-       if (!this.colormod)
-               this.colormod = _colormod;
-
-       // set default model
-       if (this.model == "")
-               this.model = _model;
-
-       // set default pickup message
-       if (this.message == "")
-               this.message = strzone(strcat("You've picked up the ", this.netname, "!"));
-
-       if (this.noise == "")
-               this.noise = strzone(SND(ITEMPICKUP));
-
-       // save the name for later
-       item_keys_names[lowestbit(this.itemkeys)] = this.netname;
-
-       // put the key on the map
-       spawn_item_key(this);
-}
-
-/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-SILVER key.
------------KEYS------------
-colormod: color of the key (default: '.9 .9 .9').
-message: message to print when player picks up this key.
-model: custom model to use.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-Don't use this entity on new maps! Use item_key instead.
-*/
-spawnfunc(item_key1)
-{
-       this.classname = "item_key";
-       this.itemkeys = ITEM_KEY_BIT(1);
-       spawnfunc_item_key(this);
-}
-
-/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-GOLD key.
------------KEYS------------
-colormod: color of the key (default: '1 .9 0').
-message: message to print when player picks up this key.
-model: custom model to use.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-Don't use this entity on new maps! Use item_key instead.
-*/
-spawnfunc(item_key2)
-{
-       this.classname = "item_key";
-       this.itemkeys = ITEM_KEY_BIT(0);
-       spawnfunc_item_key(this);
-}
diff --git a/qcsrc/server/item_key.qh b/qcsrc/server/item_key.qh
deleted file mode 100644 (file)
index 50be5f8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-/**
- * Returns the bit ID of a key
- */
-#define ITEM_KEY_BIT(n)        ( bitshift(1, n) )
-
-#define ITEM_KEY_MAX   24
-
-/**
- * list of key names.
- */
-#ifdef SVQC
-string item_keys_names[ITEM_KEY_MAX];
-
-/**
- * Use keys from p on l.
- * Returns true if any new keys were given, false otherwise.
- */
-float item_keys_usekey(entity l, entity p);
-
-/**
- * Returns a string with a comma separated list of key names, as specified in keylist.
- */
-string item_keys_keylist(float keylist);
-#endif
index 4d235da694539179a69b46a67bf4e87dd0d42ee2..b495b4b0d8e8ab3b8cab12800380a615b2750559 100644 (file)
@@ -1,6 +1,6 @@
 #include "matrix.qh"
 
-#include "player.qh"
+#include "client.qh"
 
 var void MX_Handle(int buf, string ancestor)
 {
index f8a2cd79ee60ff26314ce71f9d45502017e05f30..47c0cb2fe4615af49105c651d2bc3192c9452b5f 100644 (file)
@@ -416,6 +416,8 @@ REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
 
 REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
 
+REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
+
 /**
  * @param f -1: cleanup, 0: request, 1: receive
  */
@@ -600,14 +602,12 @@ void readplayerstartcvars()
                for (i = 0; i < t; ++i)
                {
                        s = argv(i);
-                       FOREACH(Weapons, it != WEP_Null, {
-                               if(it.netname == s)
-                               {
-                                       g_weaponarena_weapons |= (it.m_wepset);
-                                       g_weaponarena_list = strcat(g_weaponarena_list, it.m_name, " & ");
-                                       break;
-                               }
-                       });
+                       Weapon wep = Weapons_fromstr(s);
+                       if(wep != WEP_Null)
+                       {
+                               g_weaponarena_weapons |= (wep.m_wepset);
+                               g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & ");
+                       }
                }
                g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
        }
index 58e9ca127dabb4fb3183616f7815885fcfafa861..864623bbae4b888f5c3ca4e56e40d70b0d513246 100644 (file)
@@ -1203,3 +1203,12 @@ MUTATOR_HOOKABLE(Freeze, EV_Freeze);
     /** targ */             i(entity, MUTATOR_ARGV_0_entity) \
     /**/
 MUTATOR_HOOKABLE(Unfreeze, EV_Unfreeze);
+
+/**
+ * Called when a player is trying to join, argument is the number of players allowed to join the match
+ */
+#define EV_GetPlayerLimit(i, o) \
+    /** g_maxplayers */             i(int, MUTATOR_ARGV_0_int) \
+    /**/                            o(int, MUTATOR_ARGV_0_int) \
+    /**/
+MUTATOR_HOOKABLE(GetPlayerLimit, EV_GetPlayerLimit);
index 87005ad4bbf6c0476dab47635e1a34c8db616e04..3805df3f26126375a64a3fc52ce3748c0d362de7 100644 (file)
@@ -468,7 +468,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
                        if (this != attacker) {
                                float realdmg = damage - excess;
-                               if (IS_PLAYER(attacker)) {
+                               if (IS_PLAYER(attacker) && DIFF_TEAM(attacker, this)) {
                                        GameRules_scoring_add(attacker, DMG, realdmg);
                                }
                                if (IS_PLAYER(this)) {
@@ -592,8 +592,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
                // when we get here, player actually dies
 
-               Unfreeze(this); // remove any icy remains
-               SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0); // Unfreeze resets health, so we need to set it back
+               Unfreeze(this, false); // remove any icy remains
 
                // clear waypoints
                WaypointSprite_PlayerDead(this);
@@ -677,308 +676,3 @@ bool PlayerHeal(entity targ, entity inflictor, float amount, float limit)
        GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, limit);
        return true;
 }
-
-/**
- * message "": do not say, just test flood control
- * return value:
- *   1 = accept
- *   0 = reject
- *  -1 = fake accept
- */
-int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
-{
-       if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
-               msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
-
-       if (source)
-               msgin = formatmessage(source, msgin);
-
-       string colorstr;
-       if (!(IS_PLAYER(source) || source.caplayer))
-               colorstr = "^0"; // black for spectators
-       else if(teamplay)
-               colorstr = Team_ColorCode(source.team);
-       else
-       {
-               colorstr = "";
-               teamsay = false;
-       }
-
-       if(game_stopped)
-               teamsay = false;
-
-       if (!source) {
-               colorstr = "";
-               teamsay = false;
-       }
-
-       if(msgin != "")
-               msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
-
-       /*
-        * using bprint solves this... me stupid
-       // how can we prevent the message from appearing in a listen server?
-       // for now, just give "say" back and only handle say_team
-       if(!teamsay)
-       {
-               clientcommand(source, strcat("say ", msgin));
-               return;
-       }
-       */
-
-       string namestr = "";
-       if (source)
-               namestr = playername(source, autocvar_g_chat_teamcolors);
-
-       string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
-
-       string msgstr = "", cmsgstr = "";
-       string privatemsgprefix = string_null;
-       int privatemsgprefixlen = 0;
-       if (msgin != "")
-       {
-               if(privatesay)
-               {
-                       msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
-                       privatemsgprefixlen = strlen(msgstr);
-                       msgstr = strcat(msgstr, msgin);
-                       cmsgstr = strcat(colorstr, colorprefix, namestr, "^3 tells you:\n^7", msgin);
-                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay, autocvar_g_chat_teamcolors), ": ^7");
-               }
-               else if(teamsay)
-               {
-                       if(strstrofs(msgin, "/me", 0) >= 0)
-                       {
-                               //msgin = strreplace("/me", "", msgin);
-                               //msgin = substring(msgin, 3, strlen(msgin));
-                               msgin = strreplace("/me", strcat(colorstr, "(", colorprefix, namestr, colorstr, ")^7"), msgin);
-                               msgstr = strcat("\{1}\{13}^4* ", "^7", msgin);
-                       }
-                       else
-                               msgstr = strcat("\{1}\{13}", colorstr, "(", colorprefix, namestr, colorstr, ") ^7", msgin);
-                       cmsgstr = strcat(colorstr, "(", colorprefix, namestr, colorstr, ")\n^7", msgin);
-               }
-               else
-               {
-                       if(strstrofs(msgin, "/me", 0) >= 0)
-                       {
-                               //msgin = strreplace("/me", "", msgin);
-                               //msgin = substring(msgin, 3, strlen(msgin));
-                               msgin = strreplace("/me", strcat(colorprefix, namestr), msgin);
-                               msgstr = strcat("\{1}^4* ", "^7", msgin);
-                       }
-                       else {
-                               msgstr = "\{1}";
-                               msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
-                               msgstr = strcat(msgstr, msgin);
-                       }
-                       cmsgstr = "";
-               }
-               msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
-       }
-
-       string fullmsgstr = msgstr;
-       string fullcmsgstr = cmsgstr;
-
-       // FLOOD CONTROL
-       int flood = 0;
-       var .float flood_field = floodcontrol_chat;
-       if(floodcontrol && source)
-       {
-               float flood_spl;
-               float flood_burst;
-               float flood_lmax;
-               float lines;
-               if(privatesay)
-               {
-                       flood_spl = autocvar_g_chat_flood_spl_tell;
-                       flood_burst = autocvar_g_chat_flood_burst_tell;
-                       flood_lmax = autocvar_g_chat_flood_lmax_tell;
-                       flood_field = floodcontrol_chattell;
-               }
-               else if(teamsay)
-               {
-                       flood_spl = autocvar_g_chat_flood_spl_team;
-                       flood_burst = autocvar_g_chat_flood_burst_team;
-                       flood_lmax = autocvar_g_chat_flood_lmax_team;
-                       flood_field = floodcontrol_chatteam;
-               }
-               else
-               {
-                       flood_spl = autocvar_g_chat_flood_spl;
-                       flood_burst = autocvar_g_chat_flood_burst;
-                       flood_lmax = autocvar_g_chat_flood_lmax;
-                       flood_field = floodcontrol_chat;
-               }
-               flood_burst = max(0, flood_burst - 1);
-               // to match explanation in default.cfg, a value of 3 must allow three-line bursts and not four!
-
-               // do flood control for the default line size
-               if(msgstr != "")
-               {
-                       getWrappedLine_remaining = msgstr;
-                       msgstr = "";
-                       lines = 0;
-                       while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
-                       {
-                               msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
-                               ++lines;
-                       }
-                       msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
-
-                       if(getWrappedLine_remaining != "")
-                       {
-                               msgstr = strcat(msgstr, "\n");
-                               flood = 2;
-                       }
-
-                       if (time >= source.(flood_field))
-                       {
-                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + lines * flood_spl;
-                       }
-                       else
-                       {
-                               flood = 1;
-                               msgstr = fullmsgstr;
-                       }
-               }
-               else
-               {
-                       if (time >= source.(flood_field))
-                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + flood_spl;
-                       else
-                               flood = 1;
-               }
-
-               if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection
-                       source.(flood_field) = flood = 0;
-       }
-
-       string sourcemsgstr, sourcecmsgstr;
-       if(flood == 2) // cannot happen for empty msgstr
-       {
-               if(autocvar_g_chat_flood_notify_flooder)
-               {
-                       sourcemsgstr = strcat(msgstr, "\n^3FLOOD CONTROL: ^7message too long, trimmed\n");
-                       sourcecmsgstr = "";
-               }
-               else
-               {
-                       sourcemsgstr = fullmsgstr;
-                       sourcecmsgstr = fullcmsgstr;
-               }
-               cmsgstr = "";
-       }
-       else
-       {
-               sourcemsgstr = msgstr;
-               sourcecmsgstr = cmsgstr;
-       }
-
-       if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer))
-       {
-               if (!game_stopped)
-               if (teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
-                       teamsay = -1; // spectators
-       }
-
-       if(flood)
-               LOG_INFO("NOTE: ", playername(source, true), "^7 is flooding.");
-
-       // build sourcemsgstr by cutting off a prefix and replacing it by the other one
-       if(privatesay)
-               sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
-
-       int ret;
-       if(source && CS(source).muted)
-       {
-               // always fake the message
-               ret = -1;
-       }
-       else if(flood == 1)
-       {
-               if (autocvar_g_chat_flood_notify_flooder)
-               {
-                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - time), "^3 seconds\n"));
-                       ret = 0;
-               }
-               else
-                       ret = -1;
-       }
-       else
-       {
-               ret = 1;
-       }
-
-       if (privatesay && source && !(IS_PLAYER(source) || source.caplayer))
-       {
-               if (!game_stopped)
-               if ((privatesay && (IS_PLAYER(privatesay) || privatesay.caplayer)) && ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage)))
-                       ret = -1; // just hide the message completely
-       }
-
-       MUTATOR_CALLHOOK(ChatMessage, source, ret);
-       ret = M_ARGV(1, int);
-
-       if(sourcemsgstr != "" && ret != 0)
-       {
-               if(ret < 0) // faked message, because the player is muted
-               {
-                       sprint(source, sourcemsgstr);
-                       if(sourcecmsgstr != "" && !privatesay)
-                               centerprint(source, sourcecmsgstr);
-               }
-               else if(privatesay) // private message, between 2 people only
-               {
-                       sprint(source, sourcemsgstr);
-                       if (!autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
-                       if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
-                       {
-                               sprint(privatesay, msgstr);
-                               if(cmsgstr != "")
-                                       centerprint(privatesay, cmsgstr);
-                       }
-               }
-               else if ( teamsay && CS(source).active_minigame )
-               {
-                       sprint(source, sourcemsgstr);
-                       dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
-                               sprint(it, msgstr);
-                       });
-               }
-               else if(teamsay > 0) // team message, only sent to team mates
-               {
-                       sprint(source, sourcemsgstr);
-                       dedicated_print(msgstr); // send to server console too
-                       if(sourcecmsgstr != "")
-                               centerprint(source, sourcecmsgstr);
-                       FOREACH_CLIENT((IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
-                               sprint(it, msgstr);
-                               if(cmsgstr != "")
-                                       centerprint(it, cmsgstr);
-                       });
-               }
-               else if(teamsay < 0) // spectator message, only sent to spectators
-               {
-                       sprint(source, sourcemsgstr);
-                       dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(!(IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
-                               sprint(it, msgstr);
-                       });
-               }
-               else
-               {
-                       if (source) {
-                               sprint(source, sourcemsgstr);
-                               dedicated_print(msgstr); // send to server console too
-                               MX_Say(strcat(playername(source, true), "^7: ", msgin));
-                       }
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
-                               sprint(it, msgstr);
-                       });
-               }
-       }
-
-       return ret;
-}
index 276ff1628128bb48ed18d606e8b2afcb20f6f851..514b34726c2edf295dc9c79e00bfca8f6dbc5f00 100644 (file)
@@ -31,5 +31,3 @@ void calculate_player_respawn_time(entity this);
 void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
 
 bool PlayerHeal(entity targ, entity inflictor, float amount, float limit);
-
-int Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol);
index e0e33e4803c87445641359a8c76824cc821a19a8..03b40c5e12864aa7570c19ff0169c0ec107162b2 100644 (file)
@@ -248,7 +248,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
        vector spawn_score = prio * '1 0 0' + shortest * '0 1 0';
 
        // filter out spots for assault
-       if(spot.target != "")
+       if(spot.target && spot.target != "")
        {
                int found = 0;
                for(entity targ = findchain(targetname, spot.target); targ; targ = targ.chain)
index abc5df1d726a0e730e2c55402690112ad2cd9fc4..239fb69f0ca8e0e4b20b1da78d8e44897b4e6e5b 100644 (file)
@@ -585,8 +585,8 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
                        TeamBalance_IsTeamAllowedInternal(balance, i))
                {
                        TeamBalance_BanTeamsExcept(balance, i);
+                       break;
                }
-               break;
        }
        balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
        return balance;
@@ -881,16 +881,16 @@ void TeamBalance_AutoBalanceBots()
                {
                        continue;
                }
-               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
                if (smallest_team_index == 0)
                {
                        smallest_team_index = i;
-                       smallest_team_player_count = player_count;
+                       smallest_team_player_count = playercount;
                }
-               else if (player_count < smallest_team_player_count)
+               else if (playercount < smallest_team_player_count)
                {
                        smallest_team_index = i;
-                       smallest_team_player_count = player_count;
+                       smallest_team_player_count = playercount;
                }
        }
        //PrintToChatAll(sprintf("Smallest team: %f", smallest_team_index));
@@ -949,16 +949,16 @@ int TeamBalance_GetLargestTeamIndex(entity balance, int teams)
                {
                        continue;
                }
-               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
                if (largest_team_index == 0)
                {
                        largest_team_index = i;
-                       largest_team_player_count = player_count;
+                       largest_team_player_count = playercount;
                }
-               else if (player_count > largest_team_player_count)
+               else if (playercount > largest_team_player_count)
                {
                        largest_team_index = i;
-                       largest_team_player_count = player_count;
+                       largest_team_player_count = playercount;
                }
        }
        return largest_team_index;
index 8cd7ab66c346f5bc2041c747f116c8d15b412664..0dc71ddcc01c1faa40be8307487b75a378d23067 100644 (file)
@@ -61,30 +61,31 @@ void accuracy_resend(entity e)
 //.float hit_time;
 .float fired_time;
 
-void accuracy_add(entity this, int w, int fired, int hit)
+void accuracy_add(entity this, Weapon w, int fired, int hit)
 {
        if (IS_INDEPENDENT_PLAYER(this)) return;
        entity a = CS(this).accuracy;
        if (!a) return;
        if (!hit && !fired) return;
-       if (w == WEP_Null.m_id) return;
-       w -= WEP_FIRST;
-       int b = accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]);
-       if (hit)    a.accuracy_hit  [w] += hit;
-       if (fired)  a.accuracy_fired[w] += fired;
+       if (w == WEP_Null) return;
+       int wepid = w.m_id;
+       wepid -= WEP_FIRST;
+       int b = accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid]);
+       if (hit)    a.accuracy_hit  [wepid] += hit;
+       if (fired)  a.accuracy_fired[wepid] += fired;
 
     if (hit && STAT(HIT_TIME, a) != time) { // only run this once per frame
-        a.accuracy_cnt_hit[w] += 1;
+        a.accuracy_cnt_hit[wepid] += 1;
         STAT(HIT_TIME, a) = time;
     }
 
     if (fired && a.fired_time != time) { // only run this once per frame
-        a.accuracy_cnt_fired[w] += 1;
+        a.accuracy_cnt_fired[wepid] += 1;
         a.fired_time = time;
     }
 
-       if (b == accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w])) return; // no change
-       int sf = 1 << (w % 24);
+       if (b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
+       int sf = 1 << (wepid % 24);
        a.SendFlags |= sf;
        FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
 }
@@ -105,12 +106,12 @@ bool accuracy_isgooddamage(entity attacker, entity targ)
        if (mutator_check == MUT_ACCADD_INVALID) return true;
 
        if (mutator_check != MUT_ACCADD_VALID) return false;
-       if (!IS_CLIENT(targ)) return false;
+       if (!IS_CLIENT(targ) || !IS_CLIENT(attacker)) return false;
 
        return true;
 }
 
 bool accuracy_canbegooddamage(entity attacker)
 {
-       return !warmup_stage;
+       return !warmup_stage && IS_CLIENT(attacker);
 }
index d24ee1cf50cf514605e9cc8d1122e854129ffa70..627698aa217c6f0bb21e4edf534cde9ee823833c 100644 (file)
@@ -25,7 +25,7 @@ void accuracy_free(entity e);
 void accuracy_resend(entity e);
 
 // update accuracy stats
-void accuracy_add(entity e, float w, float fired, float hit);
+void accuracy_add(entity e, Weapon w, float fired, float hit);
 
 // helper
 bool accuracy_isgooddamage(entity attacker, entity targ);
index 4af13e10228d101f414d61feae9ad9b4adb9b132..5912261dbf68cf6bca6a47ce8e86db480c2cd2b9 100644 (file)
@@ -266,20 +266,34 @@ void W_SwitchToOtherWeapon(entity this, .entity weaponentity)
        W_SwitchWeapon_Force(this, ww, weaponentity);
 }
 
-void W_SwitchWeapon(entity this, Weapon w, .entity weaponentity)
+bool W_SwitchWeapon(entity this, Weapon w, .entity weaponentity)
 {
        if(this.(weaponentity).m_switchweapon != w)
        {
                if(client_hasweapon(this, w, weaponentity, true, true))
+               {
                        W_SwitchWeapon_Force(this, w, weaponentity);
+                       return true;
+               }
                else
+               {
                        this.(weaponentity).selectweapon = w.m_id; // update selectweapon anyway
+                       return false;
+               }
        }
        else if(!forbidWeaponUse(this))
        {
                entity actor = this;
                w.wr_reload(w, actor, weaponentity);
        }
+
+       return true; // player already has the weapon out or needs to reload
+}
+
+void W_SwitchWeapon_TryOthers(entity this, Weapon w, .entity weaponentity)
+{
+       if(!W_SwitchWeapon(this, w, weaponentity))
+               W_NextWeaponOnImpulse(this, w.impulse, weaponentity);
 }
 
 void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity)
index eea33ddb7b98e71c762a7fc09f9d7f41856c7558..dd21e6419da58f6772f3f541f18c588e782b71d1 100644 (file)
@@ -18,7 +18,8 @@ void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
 void W_SwitchToOtherWeapon(entity this, .entity weaponentity);
-void W_SwitchWeapon(entity this, Weapon imp, .entity weaponentity);
+bool W_SwitchWeapon(entity this, Weapon imp, .entity weaponentity); // returns false if the player does not have the weapon
+void W_SwitchWeapon_TryOthers(entity this, Weapon imp, .entity weaponentity);
 
 void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity);
 
index 204b5a7633669ffeac43adcf5c6da6013939d703..4ab5a43717c14e472bc30f0e5cdf6ab98d6bbbb7 100644 (file)
@@ -56,29 +56,20 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                        for (int i = 1; i < t; ++i)
                        {
                                s = argv(i);
-                               FOREACH(Weapons, it != WEP_Null, {
-                                       if(it.netname == s)
-                                       {
-                                               entity replacement = spawn();
-                                               copyentity(this, replacement);
-                                               replacement.m_isreplaced = true;
-                                               weapon_defaultspawnfunc(replacement, it);
-                                               break;
-                                       }
-                               });
+                               Weapon wep = Weapons_fromstr(s);
+                               if(wep != WEP_Null)
+                               {
+                                       entity replacement = spawn();
+                                       copyentity(this, replacement);
+                                       replacement.m_isreplaced = true;
+                                       weapon_defaultspawnfunc(replacement, wep);
+                               }
                        }
                }
                if (t >= 1) // always the case!
                {
                        s = argv(0);
-                       wpn = WEP_Null;
-                       FOREACH(Weapons, it != WEP_Null, {
-                               if(it.netname == s)
-                               {
-                                       wpn = it;
-                                       break;
-                               }
-                       });
+                       wpn = Weapons_fromstr(s);
                }
                if (wpn == WEP_Null)
                {
index b023180a138b1a9cca08235f950e8e81d633b17b..506bb43c408b847393bd13216a0e79c066130db6 100644 (file)
@@ -26,7 +26,6 @@
 void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range, int deathtype)
 {
        TC(Sound, snd);
-       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?
        float oldsolid = ent.dphitcontentsmask;
        Weapon wep = DEATH_WEAPONOF(deathtype);
        if(!IS_CLIENT(ent))
@@ -57,7 +56,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
 
        // track max damage
        if (IS_PLAYER(ent) && accuracy_canbegooddamage(ent))
-               accuracy_add(ent, wep.m_id, maxdamage, 0);
+               accuracy_add(ent, wep, maxdamage, 0);
 
        if(IS_PLAYER(ent))
                W_HitPlotAnalysis(ent, wep, v_forward, v_right, v_up);
@@ -65,20 +64,20 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
        vector md = ent.(weaponentity).movedir;
        vector vecs = ((md.x > 0) ? md : '0 0 0');
 
-       vector dv = v_right * -vecs.y + v_up * vecs.z;
-       w_shotorg = ent.origin + ent.view_ofs + dv;
+       vector dv = v_forward * vecs.x + v_right * -vecs.y + v_up * vecs.z;
+       w_shotorg = ent.origin + ent.view_ofs;
 
        // now move the shotorg forward as much as requested if possible
        if(antilag)
        {
                if(CS(ent).antilag_debug)
-                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, CS(ent).antilag_debug);
+                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + dv, MOVE_NORMAL, ent, CS(ent).antilag_debug);
                else
-                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
+                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + dv, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
        }
        else
-               tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent);
-       w_shotorg = trace_endpos - v_forward * nudge;
+               tracebox(w_shotorg, mi, ma, w_shotorg + dv, MOVE_NORMAL, ent);
+       w_shotorg = trace_endpos;
        // calculate the shotdir from the chosen shotorg
        if(W_DualWielding(ent))
                w_shotdir = s_forward;
@@ -143,7 +142,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
        }
 
        // nudge w_shotend so a trace to w_shotend hits
-       w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
+       w_shotend = w_shotend + normalize(w_shotend - w_shotorg);
        //if(w_shotend != prevend) { printf("SERVER: shotEND differs: %s - %s\n", vtos(w_shotend), vtos(prevend)); }
        //if(w_shotorg != prevorg) { printf("SERVER: shotORG differs: %s - %s\n", vtos(w_shotorg), vtos(prevorg)); }
        //if(w_shotdir != prevdir) { printf("SERVER: shotDIR differs: %s - %s\n", vtos(w_shotdir), vtos(prevdir)); }
@@ -266,7 +265,7 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector
        //explosion = spawn();
 
        // Find all non-hit players the beam passed close by
-       if(deathtype == WEP_VAPORIZER.m_id || deathtype == WEP_VORTEX.m_id)
+       if(deathtype == WEP_VAPORIZER.m_id || deathtype == WEP_VORTEX.m_id) // WEAPONTODO
        {
                FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
                        if(!it.railgunhit)
@@ -321,7 +320,8 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector
        IL_CLEAR(g_railgunhit);
 
        // calculate hits and fired shots for hitscan
-       accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, min(bdamage, totaldmg));
+       if(this.(weaponentity))
+               accuracy_add(this, this.(weaponentity).m_weapon, 0, min(bdamage, totaldmg));
 
        trace_endpos = endpoint;
        trace_ent = endent;
@@ -336,7 +336,7 @@ 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, int tracereffects)
+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)
 {
        vector  end;
 
@@ -344,16 +344,11 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
        end = start + dir * max_shot_distance;
 
        fireBullet_last_hit = NULL;
+       fireBullet_trace_callback_eff = tracer_effect;
+
        float solid_penetration_left = 1;
        float total_damage = 0;
 
-       if(tracereffects & EF_RED)
-               fireBullet_trace_callback_eff = EFFECT_RIFLE;
-       else if(tracereffects & EF_BLUE)
-               fireBullet_trace_callback_eff = EFFECT_RIFLE_WEAK;
-       else
-               fireBullet_trace_callback_eff = EFFECT_BULLET;
-
        float lag = ((IS_REAL_CLIENT(this)) ? ANTILAG_LATENCY(this) : 0);
        if(lag < 0.001)
                lag = 0;
@@ -426,7 +421,7 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
                                // do not exceed 100%
                                float added_damage = min(damage - total_damage, damage * solid_penetration_left);
                                total_damage += damage * solid_penetration_left;
-                               accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, added_damage);
+                               accuracy_add(this, this.(weaponentity).m_weapon, 0, added_damage);
                        }
                }
 
index 9224a970cf7b8cdfacf25edb582eb5b8adb75d54..9e39ecc350aef29a8fe369baaba53ff513aa4a49 100644 (file)
@@ -57,4 +57,4 @@ 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(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects);
+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 2017e65a760792fd3d8f0db24603729a139e4cc5..d791fc798e3056c1eb8dd6c5931561f4b282871e 100644 (file)
@@ -5,6 +5,7 @@
 #include "../command/common.qh"
 #include <server/mutators/_mod.qh>
 #include "../round_handler.qh"
+#include <server/cheats.qh>
 #include <server/resources.qh>
 #include <common/t_items.qh>
 #include <common/animdecide.qh>
@@ -49,7 +50,7 @@ bool CL_Weaponentity_CustomizeEntityForClient(entity this, entity client)
 {
        this.viewmodelforclient = this.owner;
        if (IS_SPEC(client) && client.enemy == this.owner) this.viewmodelforclient = client;
-       return true;
+       return false;
 }
 
 vector CL_Weapon_GetShotOrg(int wpn)
@@ -178,6 +179,7 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
        setthink(view, CL_Weaponentity_Think);
        view.nextthink = time;
        view.viewmodelforclient = actor;
+       view.draggable = drag_undraggable;
        setcefc(view, CL_Weaponentity_CustomizeEntityForClient);
 
        wepent_link(view);
@@ -187,6 +189,7 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
                entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
                exterior.solid = SOLID_NOT;
                exterior.owner = actor;
+               exterior.draggable = drag_undraggable;
                exterior.weaponentity_fld = weaponentity;
                setorigin(exterior, '0 0 0');
                setthink(exterior, CL_ExteriorWeaponentity_Think);
@@ -289,9 +292,8 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti
 
        if (attacktime >= 0)
        {
-               int slot = weaponslot(weaponentity);
                // don't fire if previous attack is not finished
-               if (ATTACK_FINISHED(actor, slot) > time + actor.(weaponentity).weapon_frametime * 0.5) return false;
+               if (ATTACK_FINISHED(actor, weaponentity) > time + actor.(weaponentity).weapon_frametime * 0.5) return false;
                entity this = actor.(weaponentity);
                // don't fire while changing weapon
                if (this.state != WS_READY) return false;
@@ -310,16 +312,35 @@ void weapon_prepareattack_do(entity actor, .entity weaponentity, bool secondary,
        // if the weapon hasn't been firing continuously, reset the timer
        if (attacktime >= 0)
        {
-               int slot = weaponslot(weaponentity);
-               if (ATTACK_FINISHED(actor, slot) < time - this.weapon_frametime * 1.5)
+               if (ATTACK_FINISHED(actor, weaponentity) < time - this.weapon_frametime * 1.5)
                {
-                       ATTACK_FINISHED(actor, slot) = time;
+                       ATTACK_FINISHED(actor, weaponentity) = time;
                        // dprint("resetting attack finished to ", ftos(time), "\n");
                }
-               ATTACK_FINISHED(actor, slot) = ATTACK_FINISHED(actor, slot) + attacktime * W_WeaponRateFactor(actor);
+               float arate = W_WeaponRateFactor(actor);
+               ATTACK_FINISHED(actor, weaponentity) = ATTACK_FINISHED(actor, weaponentity) + attacktime * arate;
+
+               if(autocvar_g_weaponswitch_debug_alternate && W_DualWielding(actor))
+               {
+                       int slot = weaponslot(weaponentity);
+                       for(int wepslot = 0; wepslot < MAX_WEAPONSLOTS; ++wepslot)
+                       {
+                               if(slot == wepslot)
+                                       continue;
+                               .entity wepent = weaponentities[wepslot];
+                               if(actor.(wepent) && actor.(wepent).m_weapon != WEP_Null)
+                               {
+                                       if(ATTACK_FINISHED(actor, wepent) > time + actor.(wepent).weapon_frametime * 0.5)
+                                               continue; // still cooling down!
+                                       if (ATTACK_FINISHED(actor, wepent) < time - actor.(wepent).weapon_frametime * 1.5)
+                                               ATTACK_FINISHED(actor, wepent) = time;
+                                       ATTACK_FINISHED(actor, wepent) = ATTACK_FINISHED(actor, wepent) + (attacktime * arate) / MAX_WEAPONSLOTS;
+                               }
+                       }
+               }
        }
        this.bulletcounter += 1;
-       // dprint("attack finished ", ftos(ATTACK_FINISHED(actor, slot)), "\n");
+       // dprint("attack finished ", ftos(ATTACK_FINISHED(actor, weaponentity)), "\n");
 }
 
 bool weapon_prepareattack(Weapon thiswep, entity actor, .entity weaponentity, bool secondary, float attacktime)
@@ -535,7 +556,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                                entity oldwep = this.m_weapon;
 
                                // set up weapon switch think in the future, and start drop anim
-                               if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + this.weapon_frametime * 0.5)
+                               if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponentity) <= time + this.weapon_frametime * 0.5)
                                {
                                        sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
                                        this.state = WS_DROP;
@@ -548,7 +569,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
 
        // LordHavoc: network timing test code
        // if (actor.button0)
-       //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, slot)), " >= ", ftos(this.weapon_nextthink), "\n");
+       //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, weaponentity)), " >= ", ftos(this.weapon_nextthink), "\n");
 
        Weapon w = this.m_weapon;
 
@@ -678,7 +699,7 @@ void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponenti
                {
                        backtrace(sprintf(
                                "W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
-                               "Please notify Samual immediately with a copy of this backtrace!\n",
+                               "Please notify the developers immediately with a copy of this backtrace!\n",
                                ammo_use,
                                wep.netname,
                                GetAmmoPicture(wep.ammo_type),
@@ -724,7 +745,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       // ATTACK_FINISHED(actor, slot) -= w_ent.reload_time - 1;
+       // ATTACK_FINISHED(actor, weaponentity) -= w_ent.reload_time - 1;
 
        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
 }
@@ -797,7 +818,7 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       // ATTACK_FINISHED(actor, slot) = max(time, ATTACK_FINISHED(actor, slot)) + this.reload_time + 1;
+       // ATTACK_FINISHED(actor, weaponentity) = max(time, ATTACK_FINISHED(actor, weaponentity)) + this.reload_time + 1;
 
        weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, this.reload_time, W_ReloadedAndReady);
 
index eb682aa55ce7a2b2fb3880753146d9833e716a27..67589147b634f9968c2b1e6af4b906c37a3af9c1 100644 (file)
@@ -14,6 +14,7 @@ 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
index cc512e0c40dee4247caae0f4dcd920f52c6aa2e7..15086f22a698106da5983dbf0ed02c0865cd0ff4 100644 (file)
@@ -6,6 +6,7 @@ exec xonotic-server.cfg
 exec balance-overkill.cfg
 exec physicsOverkill.cfg
 exec randomitems-overkill.cfg
+if_dedicated exec help-overkill.cfg
 
 // general gameplay
 set g_overkill 1
index 491fd052ea30ef866ad703b80667f5d08648c96d..85f27d5c0b748f7fd6ff26849f253ea68891a50d 100644 (file)
@@ -1,11 +1,3 @@
-electro
-{
-       dpreflectcube cubemaps/default/sky
-       {
-               map textures/electro.tga
-               rgbgen lightingDiffuse
-       }
-}
 nexgun
 {
        dpreflectcube cubemaps/default/sky
diff --git a/vehicles.cfg b/vehicles.cfg
new file mode 100644 (file)
index 0000000..1d2f153
--- /dev/null
@@ -0,0 +1,305 @@
+set g_vehicles 1
+
+set g_vehicles_enter 0 "require pressing use key to enter a vehicle"
+set g_vehicles_enter_radius 250
+set g_vehicles_steal 1 "allow stealing enemy vehicles in teamplay modes"
+set g_vehicles_steal_show_waypoint 1 "show a waypoint above the thief"
+set g_vehicles_delayspawn 1
+set g_vehicles_delayspawn_jitter 10
+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_allow_bots 0
+set g_vehicles_exit_attempts 25
+set g_vehicles_thinkrate 0.1
+
+set g_vehicles_vortex_damagerate 0.75
+set g_vehicles_machinegun_damagerate 0.75
+set g_vehicles_rifle_damagerate 0.75
+set g_vehicles_vaporizer_damagerate 0.5
+set g_vehicles_tag_damagerate 5
+set g_vehicles_weapon_damagerate 2
+
+// {{{ #1: Bumblebee
+set g_vehicle_bumblebee 1
+set g_vehicle_bumblebee_respawntime 60
+
+set g_vehicle_bumblebee_speed_forward 350
+set g_vehicle_bumblebee_speed_strafe 350
+set g_vehicle_bumblebee_speed_up 350
+set g_vehicle_bumblebee_speed_down 350
+set g_vehicle_bumblebee_turnspeed 120
+set g_vehicle_bumblebee_pitchspeed 60
+set g_vehicle_bumblebee_pitchlimit 60
+set g_vehicle_bumblebee_friction 0.5
+set g_vehicle_bumblebee_swim 0
+
+set g_vehicle_bumblebee_energy 500
+set g_vehicle_bumblebee_energy_regen 50
+set g_vehicle_bumblebee_energy_regen_pause 1
+
+set g_vehicle_bumblebee_health 1000
+set g_vehicle_bumblebee_health_regen 65
+set g_vehicle_bumblebee_health_regen_pause 10
+
+set g_vehicle_bumblebee_shield 400
+set g_vehicle_bumblebee_shield_regen 150
+set g_vehicle_bumblebee_shield_regen_pause 0.75
+
+set g_vehicle_bumblebee_cannon_ammo 100
+set g_vehicle_bumblebee_cannon_ammo_regen 100
+set g_vehicle_bumblebee_cannon_ammo_regen_pause 1
+
+set g_vehicle_bumblebee_cannon_lock 1
+
+set g_vehicle_bumblebee_cannon_turnspeed 260
+set g_vehicle_bumblebee_cannon_pitchlimit_down 60
+set g_vehicle_bumblebee_cannon_pitchlimit_up 60
+set g_vehicle_bumblebee_cannon_turnlimit_in 20
+set g_vehicle_bumblebee_cannon_turnlimit_out 80
+
+
+set g_vehicle_bumblebee_raygun_turnspeed 180
+set g_vehicle_bumblebee_raygun_pitchlimit_down 20
+set g_vehicle_bumblebee_raygun_pitchlimit_up 5
+set g_vehicle_bumblebee_raygun_turnlimit_sides 35
+
+set g_vehicle_bumblebee_raygun 0
+set g_vehicle_bumblebee_raygun_range 2048
+set g_vehicle_bumblebee_raygun_dps 250
+set g_vehicle_bumblebee_raygun_aps 100
+set g_vehicle_bumblebee_raygun_fps 100
+
+set g_vehicle_bumblebee_healgun_hps 150
+set g_vehicle_bumblebee_healgun_hmax 100
+set g_vehicle_bumblebee_healgun_aps 75
+set g_vehicle_bumblebee_healgun_amax 100
+set g_vehicle_bumblebee_healgun_sps 100
+set g_vehicle_bumblebee_healgun_locktime 2.5
+
+set g_vehicle_bumblebee_blowup_radius 500
+set g_vehicle_bumblebee_blowup_coredamage 500
+set g_vehicle_bumblebee_blowup_edgedamage 100
+set g_vehicle_bumblebee_blowup_forceintensity 600
+set g_vehicle_bumblebee_bouncepain "1 100 200"
+
+set g_vehicle_bumblebee_cannon_cost 2
+set g_vehicle_bumblebee_cannon_damage 60
+set g_vehicle_bumblebee_cannon_radius 225
+set g_vehicle_bumblebee_cannon_refire 0.2
+set g_vehicle_bumblebee_cannon_speed 20000
+set g_vehicle_bumblebee_cannon_spread 0
+set g_vehicle_bumblebee_cannon_force -35
+// }}}
+// {{{ #2: Racer
+set g_vehicle_racer 1
+set g_vehicle_racer_respawntime 35
+
+set g_vehicle_racer_thinkrate 0.05 // TODO: any higher causes it to sink in liquids
+
+set g_vehicle_racer_speed_afterburn 3000
+set g_vehicle_racer_afterburn_cost 130 "energy consumed per second"
+
+set g_vehicle_racer_waterburn_cost 5
+set g_vehicle_racer_waterburn_speed 750
+
+set g_vehicle_racer_water_speed_forward 600
+set g_vehicle_racer_water_speed_strafe 600
+
+set g_vehicle_racer_pitchlimit 30
+
+set g_vehicle_racer_water_downforce 0.03
+set g_vehicle_racer_water_upforcedamper 15
+
+set g_vehicle_racer_anglestabilizer 1.75
+set g_vehicle_racer_downforce 0.01
+
+set g_vehicle_racer_speed_forward 650
+set g_vehicle_racer_speed_strafe 650
+set g_vehicle_racer_springlength 90
+set g_vehicle_racer_upforcedamper 2
+set g_vehicle_racer_friction 0.45
+
+set g_vehicle_racer_water_time 5
+
+set g_vehicle_racer_hovertype 0 "0 = hover, otherwise = maglev"
+set g_vehicle_racer_hoverpower 8000 "this is multiplied by 4 for the 4 engines"
+
+set g_vehicle_racer_turnroll 30
+set g_vehicle_racer_turnspeed 220
+set g_vehicle_racer_pitchspeed 125
+
+set g_vehicle_racer_energy 100
+set g_vehicle_racer_energy_regen 90
+set g_vehicle_racer_energy_regen_pause 0.35
+
+set g_vehicle_racer_health 200
+set g_vehicle_racer_health_regen 0
+set g_vehicle_racer_health_regen_pause 0
+
+set g_vehicle_racer_shield 100
+set g_vehicle_racer_shield_regen 30
+set g_vehicle_racer_shield_regen_pause 1
+
+set g_vehicle_racer_rocket_locktarget 1
+set g_vehicle_racer_rocket_locking_time 0.35
+set g_vehicle_racer_rocket_locking_releasetime 0.5
+set g_vehicle_racer_rocket_locked_time 4
+
+set g_vehicle_racer_blowup_radius 250
+set g_vehicle_racer_blowup_coredamage 250
+set g_vehicle_racer_blowup_edgedamage 15
+set g_vehicle_racer_blowup_forceintensity 250
+
+set g_vehicle_racer_bouncefactor 0.25 "factor of old velocity to keep after collision"
+set g_vehicle_racer_bouncestop 0 "if not 0, new velocity after bounce is 0 if new velocity is smaller than this"
+set g_vehicle_racer_bouncepain "200 0.15 150" "minspeed_for_pain speedchange_to_pain_factor max_damage"
+
+set g_vehicle_racer_cannon_cost 1.5
+set g_vehicle_racer_cannon_damage 15
+set g_vehicle_racer_cannon_radius 100
+set g_vehicle_racer_cannon_refire 0.05
+set g_vehicle_racer_cannon_speed 15000
+set g_vehicle_racer_cannon_spread 0.0125
+set g_vehicle_racer_cannon_force 50
+
+set g_vehicle_racer_rocket_accel 1600
+set g_vehicle_racer_rocket_damage 100
+set g_vehicle_racer_rocket_radius 125
+set g_vehicle_racer_rocket_force 350
+set g_vehicle_racer_rocket_speed 900
+set g_vehicle_racer_rocket_turnrate 0.2
+set g_vehicle_racer_rocket_refire 3
+
+set g_vehicle_racer_rocket_climbspeed 1600
+set g_vehicle_racer_rocket_locked_maxangle 1.8
+// }}}
+// {{{ #3: Raptor
+set g_vehicle_raptor 1
+set g_vehicle_raptor_respawntime 40
+
+set g_vehicle_raptor_takeofftime 1.5
+
+set g_vehicle_raptor_movestyle 1 "0: move relative to player angles, 1: ignore aiming for up/down movement"
+set g_vehicle_raptor_turnspeed 200
+set g_vehicle_raptor_pitchspeed 50
+set g_vehicle_raptor_pitchlimit 45
+
+set g_vehicle_raptor_speed_forward 1700
+set g_vehicle_raptor_speed_strafe 2200
+set g_vehicle_raptor_speed_up 2300
+set g_vehicle_raptor_speed_down 2000
+set g_vehicle_raptor_friction 2
+
+set g_vehicle_raptor_swim 0
+
+set g_vehicle_raptor_cannon_turnspeed 120
+set g_vehicle_raptor_cannon_turnlimit 20
+set g_vehicle_raptor_cannon_pitchlimit_up 12
+set g_vehicle_raptor_cannon_pitchlimit_down 32
+
+set g_vehicle_raptor_cannon_locktarget 1
+set g_vehicle_raptor_cannon_locking_time 0.2
+set g_vehicle_raptor_cannon_locking_releasetime 0.45
+set g_vehicle_raptor_cannon_locked_time 1
+set g_vehicle_raptor_cannon_predicttarget 1
+
+set g_vehicle_raptor_energy 100
+set g_vehicle_raptor_energy_regen 25
+set g_vehicle_raptor_energy_regen_pause 0.25
+
+set g_vehicle_raptor_health 250
+set g_vehicle_raptor_health_regen 0
+set g_vehicle_raptor_health_regen_pause 0
+
+set g_vehicle_raptor_shield 200
+set g_vehicle_raptor_shield_regen 25
+set g_vehicle_raptor_shield_regen_pause 1.5
+
+set g_vehicle_raptor_bouncefactor 0.2
+set g_vehicle_raptor_bouncestop 0
+set g_vehicle_raptor_bouncepain "1 4 1000"
+
+set g_vehicle_raptor_cannon_cost 1
+set g_vehicle_raptor_cannon_damage 10
+set g_vehicle_raptor_cannon_radius 60
+set g_vehicle_raptor_cannon_refire 0.03
+set g_vehicle_raptor_cannon_speed 24000
+set g_vehicle_raptor_cannon_spread 0.01
+set g_vehicle_raptor_cannon_force 25
+
+set g_vehicle_raptor_bomblets 8
+set g_vehicle_raptor_bomblet_alt 750
+set g_vehicle_raptor_bomblet_time 0.5
+set g_vehicle_raptor_bomblet_damage 55
+set g_vehicle_raptor_bomblet_spread 0.4
+set g_vehicle_raptor_bomblet_edgedamage 25
+set g_vehicle_raptor_bomblet_radius 350
+set g_vehicle_raptor_bomblet_force 150
+set g_vehicle_raptor_bomblet_explode_delay 0.4
+
+set g_vehicle_raptor_bombs_refire 5
+
+set g_vehicle_raptor_flare_refire 5
+set g_vehicle_raptor_flare_lifetime 10
+set g_vehicle_raptor_flare_chase 0.9
+set g_vehicle_raptor_flare_range 2000
+// }}}
+// {{{ #4: Spiderbot
+set g_vehicle_spiderbot 1
+set g_vehicle_spiderbot_respawntime 45
+
+set g_vehicle_spiderbot_speed_stop 50
+set g_vehicle_spiderbot_speed_strafe 400
+set g_vehicle_spiderbot_speed_walk 500
+set g_vehicle_spiderbot_speed_run 700
+set g_vehicle_spiderbot_turnspeed 90
+set g_vehicle_spiderbot_turnspeed_strafe 300
+set g_vehicle_spiderbot_movement_inertia 0.15
+
+set g_vehicle_spiderbot_springlength 150
+set g_vehicle_spiderbot_springup 20
+set g_vehicle_spiderbot_springblend 0.1
+set g_vehicle_spiderbot_tiltlimit 90
+
+set g_vehicle_spiderbot_head_pitchlimit_down -20
+set g_vehicle_spiderbot_head_pitchlimit_up 30
+set g_vehicle_spiderbot_head_turnlimit 90
+set g_vehicle_spiderbot_head_turnspeed 110
+
+set g_vehicle_spiderbot_health 800
+set g_vehicle_spiderbot_health_regen 10
+set g_vehicle_spiderbot_health_regen_pause 5
+
+set g_vehicle_spiderbot_shield 200
+set g_vehicle_spiderbot_shield_regen 25
+set g_vehicle_spiderbot_shield_regen_pause 0.35
+
+set g_vehicle_spiderbot_bouncepain "0 0 0" "minspeed_for_pain speedchange_to_pain_factor max_damage"
+
+set g_vehicle_spiderbot_minigun_damage 16
+set g_vehicle_spiderbot_minigun_refire 0.06
+set g_vehicle_spiderbot_minigun_spread 0.012
+set g_vehicle_spiderbot_minigun_ammo_cost 1
+set g_vehicle_spiderbot_minigun_ammo_max 100
+set g_vehicle_spiderbot_minigun_ammo_regen 40
+set g_vehicle_spiderbot_minigun_ammo_regen_pause 1
+set g_vehicle_spiderbot_minigun_force 9
+set g_vehicle_spiderbot_minigun_solidpenetration 32
+
+set g_vehicle_spiderbot_rocket_damage 50
+set g_vehicle_spiderbot_rocket_force 150
+set g_vehicle_spiderbot_rocket_radius 250
+set g_vehicle_spiderbot_rocket_speed 3500
+set g_vehicle_spiderbot_rocket_spread 0.05
+set g_vehicle_spiderbot_rocket_refire 0.1
+// volley
+set g_vehicle_spiderbot_rocket_refire2 0.025
+set g_vehicle_spiderbot_rocket_reload 4
+set g_vehicle_spiderbot_rocket_health 100
+set g_vehicle_spiderbot_rocket_noise 0.2
+set g_vehicle_spiderbot_rocket_turnrate 0.25
+set g_vehicle_spiderbot_rocket_lifetime 20
+// }}}
index 32f08fc948bbdf7852ab7ba17f18fca721cd5522..3f9baf571bb2f56366bbeb2c511110ec486a1042 100644 (file)
@@ -197,6 +197,8 @@ seta cl_hitsound_min_pitch 0.75 "minimum pitch of hit sound"
 seta cl_hitsound_max_pitch 1.5 "maximum pitch of hit sound"
 seta cl_hitsound_nom_damage 25 "damage amount at which hitsound bases pitch off"
 
+seta cl_eventchase_spectated_change 1 "camera goes into 3rd person mode for a moment when changing spectated player"
+seta cl_eventchase_spectated_change_time 1 "how much time the effect lasts when changing spectated player"
 seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead; set to 2 to active the effect only when the corpse doesn't move anymore"
 seta cl_eventchase_frozen 0 "camera goes into 3rd person mode when the player is frozen"
 seta cl_eventchase_nexball 1 "camera goes into 3rd person mode when in nexball game-mode"
@@ -603,11 +605,12 @@ makesaved music_playlist_random0
 
 cl_netfps 60 // should match or be a multiple of sys_ticrate
 
-seta gl_texturecompression 0
+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
 gl_texturecompression_color 1
 gl_texturecompression_gloss 1
 gl_texturecompression_glow 1
-gl_texturecompression_lightcubemaps 1
+gl_texturecompression_lightcubemaps 0
 gl_texturecompression_q3bsplightmaps 0
 gl_texturecompression_sky 1
 
@@ -649,6 +652,8 @@ seta cl_jetpack_jump 1 "Activate jetpack by pressing jump in the air. 0 = Disabl
 seta cl_race_cptimes_showself 1 "Always show your own times as well as the current best on checkpoints in Race/CTS"
 seta cl_race_cptimes_onlyself 0 "Only show your own times on checkpoints in Race/CTS"
 
+seta cl_cts_noautoswitch 0 "Prevent forced switching to new weapons in CTS"
+
 set cl_stripcolorcodes 0       "experimental feature (notes: strips ALL color codes from messages!)"
 
 // Demo camera
@@ -722,6 +727,8 @@ seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_c
 seta cl_movement_errorcompensation 1 "try to compensate for prediction errors and reduce perceived lag"
 seta cl_movement_intermissionrunning 0 "keep velocity after the match ends, players may appear to continue running while stationary"
 
+seta cl_viewmodel_alpha 0 "Maximum transparency of the view model, set to 0 to disable"
+
 set debugdraw 0
 set debugdraw_filter ""
 set debugdraw_filterout ""
index 078fbed74c0bc58f76fb6ac4200b4b5de61406e7..3a01784c7c5d4bf6c5451fbda664ad0d44f83799 100644 (file)
@@ -145,3 +145,6 @@ exec commands.cfg
 // Change g_start_delay based upon if the server is local or not.
 if_client set g_start_delay 0  "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server"
 if_dedicated set g_start_delay 15      "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server"
+
+// this should be execed only once even on ruleset-votable servers, otherwise the tips would always start from 0
+if_dedicated exec help.cfg
index 7ad3ced27c0a8c4a82354ac67b92bb9f243f1364..e25ae7faca9b4d78250766ef4020dbdd4439e4ba 100644 (file)
@@ -10,7 +10,7 @@ set sv_autotaunt 1 "allow autotaunts on the server"
 // server settings
 hostname "Xonotic $g_xonoticversion Server"
 set sv_mapchange_delay 5
-set minplayers 0 "number of players playing at the same time (if not enough real players are there the remaining slots are filled with bots)"
+set minplayers 0 "fill server with bots to reach this number of players (if bot_number is not enough)"
 
 // restart server if all players hit "ready"-button
 set sv_ready_restart 0 "allow a map to be restarted once all players pressed the \"ready\" button"
@@ -25,7 +25,7 @@ set g_maxplayers_spectator_blocktime 5        "if the players voted for the \"nospectat
 
 // tournament mod
 set g_warmup 0 "split the game into a warmup- and match-stage"
-set g_warmup_limit 0   "limit warmup-stage to this time (in seconds); if set to -1 the warmup-stage is not affected by any timelimit, if set to 0 the usual timelimit also affects warmup-stage"
+set g_warmup_limit 180 "limit warmup-stage to this time (in seconds); if set to -1 the warmup-stage is not affected by any timelimit, if set to 0 the usual timelimit also affects warmup-stage"
 set g_warmup_allow_timeout 0   "allow calling timeouts in the warmup-stage (if sv_timeout is set to 1)"
 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"
@@ -80,8 +80,6 @@ set sv_track_canjump 0 "track if the player released the jump key between 2 jump
 set sv_jumpvelocity_crouch 0 "jump height while crouching, set to 0 to use regular jump height"
 
 set sv_precacheplayermodels 1
-set sv_precacheweapons 0
-set sv_precacheitems 0
 set sv_spectator_speed_multiplier 1.5
 set sv_spectator_speed_multiplier_min 1
 set sv_spectator_speed_multiplier_max 5
@@ -243,8 +241,6 @@ set timelimit_overtimes 0 "how many overtimes to add at max"
 set timelimit_suddendeath 5 "number of minutes suddendeath mode lasts after all overtimes were added and still no winner was found"
 
 // common team values
-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 teamplay_mode 4 "default teamplay setting in team games. 1 = no friendly fire, self damage. 2 = friendly fire and self damage enabled. 3 = no friendly fire, but self damage enabled. 4 = obey the cvars g_mirrordamage*, g_friendlyfire* and g_teamdamage*"
 set g_mirrordamage 0.7              "for teamplay_mode 4: mirror damage factor"
@@ -372,6 +368,7 @@ set sv_itemstime 1 "enable networking of time left until respawn for items such
 
 set g_ban_default_bantime 5400 "90 minutes"
 set g_ban_default_masksize 3   "masksize 0 means banning by UID only, 1 means banning by /8 (IPv6: /32) network, 2 means banning by /16 (IPv6: /48) network, 3 means banning by /24 (IPv6: /56) network, 4 means banning by single IP (IPv6: /64 network)"
+set g_ban_telluser 1 "notify the banned player about it when they try to join"
 set g_banned_list ""   "format: IP remainingtime IP remainingtime ..."
 set g_banned_list_idmode "1"   "when set, the IP banning system always uses the ID over the IP address (so a user in a banned IP range can connect if they have a valid signed ID)"
 
@@ -384,6 +381,7 @@ set timelimit_max 60
 sv_gameplayfix_delayprojectiles 0
 sv_gameplayfix_q2airaccelerate 1
 sv_gameplayfix_stepmultipletimes 1
+sv_gameplayfix_stepdown 2
 
 // delay for "kill" to prevent abuse
 set g_balance_kill_delay 2
@@ -482,6 +480,7 @@ sv_gameplayfix_gravityunaffectedbyticrate 1
 sv_gameplayfix_nogravityonground 1
 
 set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
+set sv_vq3compat 0 "toggle for some compatibility hacks (for VQ3 and CPM map compatibility in mapinfo files)"
 
 set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"
 
@@ -542,11 +541,13 @@ set g_mod_config  "" "Current config mod name"
 exec balance-xonotic.cfg
 exec physicsX.cfg
 exec turrets.cfg
+exec vehicles.cfg
 exec gamemodes-server.cfg
 exec mutators.cfg
 exec monsters.cfg
 exec minigames.cfg
 exec physics.cfg
+if_dedicated exec help-xonotic.cfg
 
 set sv_join_notices ""
 set sv_join_notices_time 15