- wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
- wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
- make
- - EXPECT=6535600492e1cb63af8e449570bffe4a
+ - EXPECT=a98e5e5ee0cc3d2e80ee0ad812786703
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
-Wed Jan 15 07:24:54 CET 2020
+Mon Mar 30 07:24:48 CEST 2020
seta hud_progressbar_health_color "" "R G B vector of the progress bar background color"
seta hud_progressbar_armor_color "" "R G B vector of the progress bar background color"
seta hud_progressbar_fuel_color "" "R G B vector of the progress bar background color"
+seta hud_progressbar_oxygen_color "" "R G B vector of the progress bar background color"
seta hud_progressbar_nexball_color "" "R G B vector of the progress bar background color"
seta hud_progressbar_speed_color "" "R G B vector of the progress bar background color"
seta hud_progressbar_acceleration_color "" "R G B vector of the progress bar background color"
+++ /dev/null
-// This config file is for overkill weapons that were nerfed to have the same
-// stats as vanilla weapons, secondary attack uses stats of vanilla blaster.
-// Secondary is actually inconsistent, see https://gitlab.com/xonotic/xonotic-data.pk3dir/issues/2258
-
-// {{{ Overkill Shotgun
-set g_balance_okshotgun_primary_ammo 1
-set g_balance_okshotgun_primary_animtime 0.2
-set g_balance_okshotgun_primary_bot_range 512
-set g_balance_okshotgun_primary_bullets 12
-set g_balance_okshotgun_primary_damage 4
-set g_balance_okshotgun_primary_force 15
-set g_balance_okshotgun_primary_refire 0.75
-set g_balance_okshotgun_primary_solidpenetration 3.8
-set g_balance_okshotgun_primary_spread 0.12
-set g_balance_okshotgun_reload_ammo 0
-set g_balance_okshotgun_reload_time 2
-set g_balance_okshotgun_secondary_animtime 0.2
-set g_balance_okshotgun_secondary_damage 20
-set g_balance_okshotgun_secondary_delay 0
-set g_balance_okshotgun_secondary_edgedamage 10
-set g_balance_okshotgun_secondary_force 300
-set g_balance_okshotgun_secondary_force_zscale 1
-set g_balance_okshotgun_secondary_lifetime 5
-set g_balance_okshotgun_secondary_radius 60
-set g_balance_okshotgun_secondary_refire 0.7
-set g_balance_okshotgun_secondary_refire_type 0
-set g_balance_okshotgun_secondary_shotangle 0
-set g_balance_okshotgun_secondary_speed 6000
-set g_balance_okshotgun_secondary_spread 0
-set g_balance_okshotgun_switchdelay_drop 0.2
-set g_balance_okshotgun_switchdelay_raise 0.2
-set g_balance_okshotgun_weaponreplace ""
-set g_balance_okshotgun_weaponstart 0
-set g_balance_okshotgun_weaponstartoverride -1
-set g_balance_okshotgun_weaponthrowable 1
-// }}}
-// {{{ Overkill Machine Gun
-set g_balance_okmachinegun_primary_ammo 1
-set g_balance_okmachinegun_primary_damage 10
-set g_balance_okmachinegun_primary_force 3
-set g_balance_okmachinegun_primary_refire 0.1
-set g_balance_okmachinegun_primary_solidpenetration 13.1
-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.02
-set g_balance_okmachinegun_reload_ammo 60
-set g_balance_okmachinegun_reload_time 2
-set g_balance_okmachinegun_secondary_animtime 0.2
-set g_balance_okmachinegun_secondary_damage 20
-set g_balance_okmachinegun_secondary_delay 0
-set g_balance_okmachinegun_secondary_edgedamage 10
-set g_balance_okmachinegun_secondary_force 300
-set g_balance_okmachinegun_secondary_force_zscale 1
-set g_balance_okmachinegun_secondary_lifetime 5
-set g_balance_okmachinegun_secondary_radius 60
-set g_balance_okmachinegun_secondary_refire 0.7
-set g_balance_okmachinegun_secondary_refire_type 0
-set g_balance_okmachinegun_secondary_shotangle 0
-set g_balance_okmachinegun_secondary_speed 6000
-set g_balance_okmachinegun_secondary_spread 0
-set g_balance_okmachinegun_switchdelay_drop 0.2
-set g_balance_okmachinegun_switchdelay_raise 0.2
-set g_balance_okmachinegun_weaponreplace ""
-set g_balance_okmachinegun_weaponstart 0
-set g_balance_okmachinegun_weaponstartoverride -1
-set g_balance_okmachinegun_weaponthrowable 1
-// }}}
-// {{{ Overkill Nex
-set g_balance_oknex_charge 1
-set g_balance_oknex_charge_animlimit 0.5
-set g_balance_oknex_charge_limit 1
-set g_balance_oknex_charge_maxspeed 800
-set g_balance_oknex_charge_mindmg 40
-set g_balance_oknex_charge_minspeed 400
-set g_balance_oknex_charge_rate 0.6
-set g_balance_oknex_charge_rot_pause 0
-set g_balance_oknex_charge_rot_rate 0
-set g_balance_oknex_charge_shot_multiplier 0
-set g_balance_oknex_charge_start 0.5
-set g_balance_oknex_charge_velocity_rate 0
-set g_balance_oknex_primary_ammo 6
-set g_balance_oknex_primary_animtime 0.4
-set g_balance_oknex_primary_damage 80
-set g_balance_oknex_primary_damagefalloff_forcehalflife 0
-set g_balance_oknex_primary_damagefalloff_halflife 0
-set g_balance_oknex_primary_damagefalloff_maxdist 0
-set g_balance_oknex_primary_damagefalloff_mindist 0
-set g_balance_oknex_primary_force 400
-set g_balance_oknex_primary_refire 1.5
-set g_balance_oknex_reload_ammo 0
-set g_balance_oknex_reload_time 2
-set g_balance_oknex_secondary 0
-set g_balance_oknex_secondary_ammo 2
-set g_balance_oknex_secondary_animtime 0
-set g_balance_oknex_secondary_chargepool 0
-set g_balance_oknex_secondary_chargepool_pause_regen 1
-set g_balance_oknex_secondary_chargepool_regen 0.15
-set g_balance_oknex_secondary_damage 0
-set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
-set g_balance_oknex_secondary_damagefalloff_halflife 0
-set g_balance_oknex_secondary_damagefalloff_maxdist 0
-set g_balance_oknex_secondary_damagefalloff_mindist 0
-set g_balance_oknex_secondary_force 0
-set g_balance_oknex_secondary_force_zscale 1
-set g_balance_oknex_secondary_refire 0
-set g_balance_oknex_secondary_refire_type 0
-set g_balance_oknex_secondary_delay 0
-set g_balance_oknex_secondary_edgedamage 10
-set g_balance_oknex_secondary_lifetime 5
-set g_balance_oknex_secondary_radius 60
-set g_balance_oknex_secondary_shotangle 0
-set g_balance_oknex_secondary_speed 6000
-set g_balance_oknex_secondary_spread 0
-set g_balance_oknex_switchdelay_drop 0.2
-set g_balance_oknex_switchdelay_raise 0.2
-set g_balance_oknex_weaponreplace ""
-set g_balance_oknex_weaponstart 0
-set g_balance_oknex_weaponstartoverride -1
-set g_balance_oknex_weaponthrowable 1
-// }}}
}
check_files "balance-xonotic.cfg" "balance-*.cfg" "/^seta? g_/"
+check_files "bal-wep-xonotic.cfg" "bal-wep-*.cfg" "/^seta? g_/"
check_files "_hud_descriptions.cfg" "hud_*.cfg" "/^seta? hud_/"
if $errord; then
// =================================
set sv_vote_call 1 "Allow users to call a vote for the commands in sv_vote_commands"
set sv_vote_change 1 "Allow voters to change their mind after already voting"
-set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams bots nobots" "these commands can be voted by players or used directly by masters (vdo) in addition to sv_vote_master_commands"
+set sv_vote_commands "restart fraglimit gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams bots nobots" "these commands can be voted by players or used directly by masters (vdo) in addition to sv_vote_master_commands"
set sv_vote_only_commands ""
set sv_vote_limit 160 "Maximum allowed length of a vote command"
set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink movetospec" "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0)
#
# Translators:
# Ximielga <dorian@openmailbox.org>, 2014-2015
-# Ḷḷumex03 <tornes@opmbx.org>, 2014
-# Ḷḷumex03 <tornes@opmbx.org>, 2014-2015
+# Ḷḷumex03, 2014
+# Ḷḷumex03, 2014
+# Ḷḷumex03, 2014-2015
# Tornes Ḷḷume <tornes.llume@openmailbox.org>, 2015-2017
# Ximielga <dorian@openmailbox.org>, 2014
msgid ""
#
# Translators:
# nad le <nadavlevi726@gmail.com>, 2018
+# Roi Asher Gerszkoviez <gerszkoviez@gmail.com>, 2020
# Tal Leibman <leibman2@gmail.com>, 2019
msgid ""
msgstr ""
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-05-19 07:23+0200\n"
-"PO-Revision-Date: 2019-05-19 05:23+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2020-03-05 22:01+0000\n"
+"Last-Translator: Roi Asher Gerszkoviez <gerszkoviez@gmail.com>\n"
"Language-Team: Hebrew (http://www.transifex.com/team-xonotic/xonotic/"
"language/he/)\n"
"Language: he\n"
#: qcsrc/client/hud/panel/centerprint.qc:144
#, c-format
msgid "Message at time %s"
-msgstr ""
+msgstr "הודעה בזמן %s"
#: qcsrc/client/hud/panel/centerprint.qc:149
msgid "Generic message"
-msgstr ""
+msgstr "הודעה גנרית"
#: qcsrc/client/hud/panel/chat.qc:84
msgid "^3Player^7: This is the chat area."
-msgstr ""
+msgstr "^3שחקן^7: זהו אזור הצ'אט."
#: qcsrc/client/hud/panel/engineinfo.qc:72
#, c-format
msgid "FPS: %.*f"
-msgstr ""
+msgstr "FPS: %.*f"
#: qcsrc/client/hud/panel/infomessages.qc:89
msgid "^1Observing"
-msgstr ""
+msgstr "^1משקיף"
#: qcsrc/client/hud/panel/infomessages.qc:91
#, c-format
#: qcsrc/client/hud/panel/infomessages.qc:102
#, c-format
msgid "^1Press ^3%s^1 to spectate"
-msgstr ""
+msgstr "^1לחץ ^3%s^1 כדי להשקיף"
#: qcsrc/client/hud/panel/infomessages.qc:102
#: qcsrc/menu/xonotic/keybinder.qc:47
#: qcsrc/client/hud/panel/infomessages.qc:104
#: qcsrc/client/hud/panel/infomessages.qc:108
msgid "next weapon"
-msgstr "נשק הבא"
+msgstr "×\94× ×©×§ ×\94×\91×\90"
#: qcsrc/client/hud/panel/infomessages.qc:104
#: qcsrc/client/hud/panel/infomessages.qc:108
msgid "previous weapon"
-msgstr "× ×©×§ קודם"
+msgstr "×\94× ×©×§ ×\94קודם"
#: qcsrc/client/hud/panel/infomessages.qc:108
#, c-format
#: qcsrc/client/hud/panel/infomessages.qc:110
#: qcsrc/common/vehicles/cl_vehicles.qc:190
msgid "drop weapon"
-msgstr ""
+msgstr "זרוק נשק"
#: qcsrc/client/hud/panel/infomessages.qc:110
#: qcsrc/menu/xonotic/keybinder.qc:48
#: qcsrc/client/hud/panel/score.qc:63
#, c-format
msgid "Player %d"
-msgstr ""
+msgstr "שחקן %d"
#: qcsrc/client/hud/panel/quickmenu.qc:591
#: qcsrc/client/hud/panel/quickmenu.qc:593
#, c-format
msgid "Submenu%d"
-msgstr ""
+msgstr "תת-תפריט%d"
#: qcsrc/client/hud/panel/quickmenu.qc:598
#, c-format
msgid "Command%d"
-msgstr ""
+msgstr "פקודה%d"
#: qcsrc/client/hud/panel/quickmenu.qc:624
msgid "Continue..."
#: qcsrc/client/hud/panel/quickmenu.qc:781
#: qcsrc/client/hud/panel/quickmenu.qc:788
msgid "Chat"
-msgstr ""
+msgstr "צ'אט"
#: qcsrc/client/hud/panel/quickmenu.qc:782
msgid "QMCMD^Send public message to"
-msgstr ""
+msgstr "QMCMD^שלח הודעה פומבית אל"
#: qcsrc/client/hud/panel/quickmenu.qc:783
msgid "QMCMD^:-) / nice one"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:52
msgid "m/s"
-msgstr ""
+msgstr "מ\"ש"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:53
msgid "km/h"
-msgstr ""
+msgstr "קמ\"ש"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:54
msgid "mph"
-msgstr ""
+msgstr "מייל לשעה"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:55
msgid "knots"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60
msgid "Top speed"
-msgstr ""
+msgstr "מהירות מקסימלית"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:66
msgid "Acceleration:"
-msgstr ""
+msgstr "האצה:"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:67
msgid "Include vertical acceleration"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:44
msgid "Zoom mode:"
-msgstr ""
+msgstr "מצב זום:"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:46
msgid "Zoomed in"
-msgstr ""
+msgstr "זום אין"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:47
msgid "Zoomed out"
-msgstr ""
+msgstr "זום אאוט"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:48
msgid "Always zoomed"
-msgstr ""
+msgstr "תמיד בזום"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:49
msgid "Never zoomed"
-msgstr ""
+msgstr "לעולם לא בזום"
#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qh:6
msgid "Radar Panel"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:34
msgid "Alpha"
-msgstr ""
+msgstr "אלפא"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:35
msgid "Slide"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:66
msgid "Show Accuracy"
-msgstr ""
+msgstr "הצג דיוק"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:67
msgid "Show Ammo"
-msgstr ""
+msgstr "הצג תחמושת"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:70
msgid "Ammo bar alpha:"
-msgstr ""
+msgstr "אלפא של סרגל התחמושת:"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:76
msgid "Ammo bar color:"
-msgstr ""
+msgstr "צבע סרגל התחמושת:"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qh:6
msgid "Weapons Panel"
-msgstr ""
+msgstr "פאנל הנשקים"
#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:19
msgid "HUD skins"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:40
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:64
msgid "Unlimited"
-msgstr "×\9c×\90 מוגבל"
+msgstr "×\91×\9cת×\99 מוגבל"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:74
msgid "Gametype"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:94
msgid "Pressing \"enter console\" key also closes it"
-msgstr ""
+msgstr "כפתור \"כניסה לקונסול\" גם סוגר אותו"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:95
msgid "Allow the console toggling bind to also close the console"
-msgstr ""
+msgstr "אפשר לכפתור שפותח את הקונסול גם לסגור אותו"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:97
msgid "Automatically repeat jumping if holding jump"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:100
msgid "Jetpack on jump:"
-msgstr ""
+msgstr "תיק סילון בקפיצה:"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:102
msgid "JPJUMP^Disabled"
-msgstr ""
+msgstr "JPJUMP^מבוטל"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:103
msgid "Air only"
-msgstr ""
+msgstr "אוויר בלבד"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:104
msgid "JPJUMP^All"
-msgstr ""
+msgstr "JPJUMP^הכל"
#: qcsrc/menu/xonotic/dialog_settings_input.qc:110
#: qcsrc/menu/xonotic/dialog_settings_input.qc:115
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
msgid "Client UDP port:"
-msgstr ""
+msgstr "פתחת UDP של לקוח:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:31
msgid "Force client to use chosen port unless it is set to 0"
-msgstr ""
+msgstr "הכרח את הלקוח להשתמש בפורט הנבחר, אלא אם הערך הוא 0"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:34
msgid "Bandwidth:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:37
msgid "56k"
-msgstr ""
+msgstr "56k"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:38
msgid "ISDN"
-msgstr ""
+msgstr "ISDN"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:39
msgid "Slow ADSL"
-msgstr ""
+msgstr "ADSL איטי"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:40
msgid "Fast ADSL"
-msgstr ""
+msgstr "ADSL מהיר"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:41
msgid "Broadband"
-msgstr ""
+msgstr "פס רחב"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:44
msgid "Input packets/s:"
-msgstr ""
+msgstr "פאקטות קלט/שנייה:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:46
msgid "How many input packets to send to the server each second"
-msgstr ""
+msgstr "כמה פאקטות קלט לשלוח לשרת בכל שנייה"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
msgid "Server queries/s:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:73
msgid "Show netgraph"
-msgstr ""
+msgstr "הצג גרף רשת"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:74
msgid "Show a graph of packet sizes and other information"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:76
msgid "Client-side movement prediction"
-msgstr ""
+msgstr "חיזוי תנועה בצד-לקוח"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:78
msgid "Movement error compensation"
-msgstr ""
+msgstr "פיצוי על שגיאות תנועה"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:82
msgid "Use encryption (AES) when available"
-msgstr ""
+msgstr "השתמש בהצפנה (AES) כשזה אפשרי"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:85
msgid "Framerate"
-msgstr ""
+msgstr "קצב פריימים"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:87
msgid "Maximum:"
-msgstr ""
+msgstr "מקסימום:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:99
msgid "MAXFPS^Unlimited"
-msgstr ""
+msgstr "MAXFPS^בלתי מוגבל"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:102
msgid "Target:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:104
msgid "TRGT^Disabled"
-msgstr ""
+msgstr "TRGT^מבוטל"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:116
msgid "Idle limit:"
-msgstr ""
+msgstr "מגבלה בזמן idle:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:122
msgid "IDLFPS^Unlimited"
-msgstr ""
+msgstr "IDLFPS^בלתי מוגבל"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:126
msgid "Save processing time for other apps"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:157
#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qh:6
msgid "Factory reset"
-msgstr ""
+msgstr "איפוס להגדרות מקוריות"
#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:31
msgid "Cvar filter:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:121
msgid "Brightness of black"
-msgstr ""
+msgstr "בהירות הצבע השחור:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:123
msgid "Contrast:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:125
msgid "Brightness of white"
-msgstr ""
+msgstr "בהירות הצבע הלבן:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:127
msgid "Gamma:"
-msgstr ""
+msgstr "גמא:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:130
msgid ""
#: qcsrc/menu/xonotic/dialog_settings_video.qc:155
msgid "Wait for GPU to finish each frame"
-msgstr ""
+msgstr "חכה עד שהמעבד הגרפי יסיים כל פריים"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:156
msgid ""
"Make the CPU wait for the GPU to finish each frame, can help with some "
"strange input or video lag on some machines"
msgstr ""
+"גרום למעבד להמתין שהמעבד הגרפי יסיים כל פריים. זה יכול לעזור במקרים של לאגים "
+"מוזרים בקלט או בוידאו במחשבים מסויימים."
#: qcsrc/menu/xonotic/dialog_settings_video.qc:158
msgid "Use OpenGL 2.0 shaders (GLSL)"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:110
msgid "Instant action! (random map with bots)"
-msgstr ""
+msgstr "פעולה מיידית! (מפה אקראית עם בוטים)"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:117
msgid "???"
-msgstr ""
+msgstr "???"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:130
msgid "Campaign Difficulty:"
-msgstr ""
+msgstr "דרגת קושי של הקמפיין:"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:131
msgid "CSKL^Easy"
-msgstr ""
+msgstr "CSKL^קל"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:132
msgid "CSKL^Medium"
-msgstr ""
+msgstr "CSKL^בינוני"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:133
msgid "CSKL^Hard"
-msgstr ""
+msgstr "CSKL^קשה"
#: qcsrc/menu/xonotic/dialog_singleplayer.qc:135
msgid "Start Singleplayer!"
-msgstr ""
+msgstr "התחל במצב שחקן יחיד!"
#: qcsrc/menu/xonotic/dialog_singleplayer.qh:6
msgid "Singleplayer"
-msgstr ""
+msgstr "שחקן יחיד"
#: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
msgid "Play the singleplayer campaign or instant action matches against bots"
-msgstr ""
+msgstr "שחק בקמפיין לשחקן יחיד או במשחקי פעולה מיידית נגד בוטים"
#: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
msgid "Winner"
#: qcsrc/menu/xonotic/dialog_teamselect.qc:32
msgid "join 'best' team (auto-select)"
-msgstr ""
+msgstr "הצטרף לקבוצה הטובה ביותר (בחירה אוטומטית)"
#: qcsrc/menu/xonotic/dialog_teamselect.qc:33
msgid "Autoselect team (recommended)"
-msgstr ""
+msgstr "בחר קבוצה אוטומטית (מומלץ)"
#: qcsrc/menu/xonotic/dialog_teamselect.qc:37
msgid "red"
#: qcsrc/menu/xonotic/dialog_uid2name.qc:10
msgid "Allow player statistics to use your nickname?"
-msgstr ""
+msgstr "האם להרשות לסטטיסטיקות השחקן להשתמש בכינוי שלך?"
#: qcsrc/menu/xonotic/dialog_uid2name.qc:12
msgid "Answering \"No\" you will appear as \"Anonymous player\""
-msgstr ""
+msgstr "אם תענה \"לא\" אתה תופיע בתור \"שחקן אנונימי\""
#: qcsrc/menu/xonotic/gametypelist.qc:87
msgid "teamplay"
#: qcsrc/menu/xonotic/keybinder.qc:43
msgid "jetpack"
-msgstr ""
+msgstr "תיק סילון"
#: qcsrc/menu/xonotic/keybinder.qc:46
msgid "Attacking"
#: qcsrc/menu/xonotic/keybinder.qc:52
msgid "WEAPON^previous"
-msgstr ""
+msgstr "WEAPON^הקודם"
#: qcsrc/menu/xonotic/keybinder.qc:53
msgid "WEAPON^next"
-msgstr ""
+msgstr "WEAPON^הבא"
#: qcsrc/menu/xonotic/keybinder.qc:54
msgid "WEAPON^previously used"
-msgstr ""
+msgstr "WEAPON^האחרון שהיה בשימוש"
#: qcsrc/menu/xonotic/keybinder.qc:55
msgid "WEAPON^best"
-msgstr ""
+msgstr "WEAPON^הטוב ביותר"
#: qcsrc/menu/xonotic/keybinder.qc:56
msgid "reload"
#: qcsrc/menu/xonotic/mainwindow.qc:65 qcsrc/menu/xonotic/mainwindow.qc:68
msgid "Do not press this button again!"
-msgstr ""
+msgstr "אל תלחץ על כפתור זה שוב!"
#: qcsrc/menu/xonotic/maplist.qc:288
msgid ""
"Huh? Can't play this (m is NULL). Refiltering so this won't happen again."
-msgstr ""
+msgstr "מה? אי אפשר לשחק בזה (m הוא NULL). מסנן מחדש כדי שזה לא יקרה שוב."
#: qcsrc/menu/xonotic/maplist.qc:296
#, c-format
msgid "%s's Xonotic Server"
-msgstr ""
+msgstr "שרת ה-Xonotic של %s"
#: qcsrc/menu/xonotic/maplist.qc:301
msgid ""
"Huh? Can't play this (invalid game type). Refiltering so this won't happen "
"again."
-msgstr ""
+msgstr "מה? אי אפשר לשחק בזה (סוג המשחק שגוי). מסנן מחדש כדי שזה לא יקרה שוב."
#: qcsrc/menu/xonotic/playerlist.qc:102 qcsrc/menu/xonotic/playerlist.qc:112
msgid "spectator"
-msgstr ""
+msgstr "צופה"
#: qcsrc/menu/xonotic/playermodel.qc:161
msgid "<no model found>"
-msgstr ""
+msgstr "<no model found>"
#: qcsrc/menu/xonotic/serverlist.qc:267
msgid "Favorite"
-msgstr ""
+msgstr "מועדף"
#: qcsrc/menu/xonotic/serverlist.qc:268
msgid ""
"Bookmark the currently highlighted server so that it's faster to find in the "
"future"
-msgstr ""
+msgstr "הוסף סימניה עבור השרת המודגש כרגע כדי שיהיה קל למצוא אותו שוב בעתיד"
#: qcsrc/menu/xonotic/serverlist.qc:747
msgid "Ping"
#: qcsrc/menu/xonotic/serverlist.qc:748
msgid "Hostname"
-msgstr ""
+msgstr "שם השרת"
#: qcsrc/menu/xonotic/serverlist.qc:749
msgid "Map"
#: qcsrc/menu/xonotic/serverlist.qc:1043
#, c-format
msgid "AES level %d"
-msgstr ""
+msgstr "רמת AES %d"
#: qcsrc/menu/xonotic/serverlist.qc:1043
msgid "ENC^none"
#: qcsrc/menu/xonotic/serverlist.qc:1043
msgid "encryption:"
-msgstr ""
+msgstr "הצפנה:"
#: qcsrc/menu/xonotic/serverlist.qc:1044
#, c-format
msgid "mod: %s"
-msgstr ""
+msgstr "מוד: %s"
#: qcsrc/menu/xonotic/serverlist.qc:1046
#, c-format
msgid "modified settings"
-msgstr ""
+msgstr "הגדרות שנערכו"
#: qcsrc/menu/xonotic/serverlist.qc:1046
#, c-format
msgid "official settings"
-msgstr ""
+msgstr "הגדרות רשמיות"
#: qcsrc/menu/xonotic/serverlist.qc:1048
msgid "stats disabled"
-msgstr ""
+msgstr "סטטיסטיקות מכובות"
#: qcsrc/menu/xonotic/serverlist.qc:1048
msgid "stats enabled"
-msgstr ""
+msgstr "סטטיסטיקות מופעלות"
#: qcsrc/menu/xonotic/serverlist.qh:152
msgid "SLCAT^Favorites"
"Change the sharpness of the textures. Lowering it will effectively reduce "
"texture memory usage, but make the textures appear very blurry."
msgstr ""
+"שנה את החדות של טקסטורות. הנמכה תגרום לצמצום יעיל של זיכרון שמשומש על ידי "
+"טקסטורות, אבל יגרום לטקסטורות להראות מאוד מטושטשות."
#: qcsrc/menu/xonotic/slider_resolution.qc:115
msgid "Screen resolution"
#: qcsrc/menu/xonotic/statslist.qc:110
msgid "Time played:"
-msgstr ""
+msgstr "זמן ששוחק:"
#: qcsrc/menu/xonotic/statslist.qc:117 qcsrc/menu/xonotic/statslist.qc:230
msgid "Favorite map:"
#: qcsrc/menu/xonotic/statslist.qc:244
#, c-format
msgid "Matches:"
-msgstr ""
+msgstr "משחקים:"
#: qcsrc/menu/xonotic/statslist.qc:154
#, c-format
#: qcsrc/menu/xonotic/statslist.qc:166
#, c-format
msgid "Kills/Deaths:"
-msgstr ""
+msgstr "הריגות/מיתות:"
#: qcsrc/menu/xonotic/statslist.qc:172
#, c-format
#: qcsrc/menu/xonotic/statslist.qc:207
msgid "ELO:"
-msgstr ""
+msgstr "דירוג ELO:"
#: qcsrc/menu/xonotic/statslist.qc:214
msgid "Rank:"
#: qcsrc/menu/xonotic/util.qc:417
msgid "Update can be downloaded at:"
-msgstr ""
+msgstr "ניתן להוריד עדכון ב:"
#: qcsrc/menu/xonotic/util.qc:525
msgid "Autogenerating mapinfo for newly added maps..."
#: qcsrc/menu/xonotic/util.qc:574
#, c-format
msgid "Update to %s now!"
-msgstr ""
+msgstr "עדכן לגרסה %s עכשיו!"
#: qcsrc/menu/xonotic/util.qc:658
msgid ""
# Jakub P. <pedziszewski@gmail.com>, 2015
# Jakub P. <pedziszewski@gmail.com>, 2015
# John Smith <myrangd@gmail.com>, 2016
+# karol kosek <transifex@krkk.ct8.pl>, 2020
+# karol kosek <transifex@krkk.ct8.pl>, 2020
+# karol kosek <transifex@krkk.ct8.pl>, 2020
+# karol kosek <transifex@krkk.ct8.pl>, 2020
# Kriss Chr <kriss7475@gmail.com>, 2017
# Piotr Kozica <koza91@gmail.com>, 2016
# Rafał Szymański <okavasly@gmail.com>, 2017
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-05-19 07:23+0200\n"
-"PO-Revision-Date: 2019-05-19 05:23+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2020-02-08 12:09+0000\n"
+"Last-Translator: karol kosek <transifex@krkk.ct8.pl>\n"
"Language-Team: Polish (http://www.transifex.com/team-xonotic/xonotic/"
"language/pl/)\n"
"Language: pl\n"
#: qcsrc/client/hud/hud_config.qc:243
#, c-format
msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)"
-msgstr ""
+msgstr "^2Wyeksportowano do %s! (Uwaga: Zapisano w data/data/)"
#: qcsrc/client/hud/hud_config.qc:247
#, c-format
msgid "^1Couldn't write to %s"
-msgstr ""
+msgstr "^1Nie można zapisać do %s"
#: qcsrc/client/hud/panel/centerprint.qc:140
#, c-format
#: qcsrc/client/hud/panel/centerprint.qc:149
msgid "Generic message"
-msgstr ""
+msgstr "Ogólna wiadomość"
#: qcsrc/client/hud/panel/chat.qc:84
msgid "^3Player^7: This is the chat area."
#: qcsrc/client/hud/panel/quickmenu.qc:781
#: qcsrc/client/hud/panel/quickmenu.qc:788
msgid "Chat"
-msgstr ""
+msgstr "Czat"
#: qcsrc/client/hud/panel/quickmenu.qc:782
msgid "QMCMD^Send public message to"
#: qcsrc/client/hud/panel/scoreboard.qc:91
msgid "Number of deaths"
-msgstr ""
+msgstr "Liczba zgonów"
#: qcsrc/client/hud/panel/scoreboard.qc:91
msgid "SCO^deaths"
#: qcsrc/client/hud/panel/scoreboard.qc:95
msgid "Number of flag drops"
-msgstr ""
+msgstr "Liczba upuszczeń flagi"
#: qcsrc/client/hud/panel/scoreboard.qc:95
msgid "SCO^drops"
#: qcsrc/client/hud/panel/scoreboard.qc:100
msgid "FPS"
-msgstr ""
+msgstr "FPS"
#: qcsrc/client/hud/panel/scoreboard.qc:100
msgid "SCO^fps"
-msgstr ""
+msgstr "fps"
#: qcsrc/client/hud/panel/scoreboard.qc:101
msgid "Number of kills minus suicides"
#: qcsrc/client/hud/panel/scoreboard.qc:111
#: qcsrc/client/hud/panel/scoreboard.qc:112
msgid "Player name"
-msgstr ""
+msgstr "Nazwa gracza"
#: qcsrc/client/hud/panel/scoreboard.qc:111
msgid "SCO^name"
#: qcsrc/client/hud/panel/scoreboard.qc:116
msgid "Packet loss"
-msgstr ""
+msgstr "Utrata pakietu"
#: qcsrc/client/hud/panel/scoreboard.qc:116
msgid "SCO^pl"
#: qcsrc/client/hud/panel/scoreboard.qc:123
msgid "Number of suicides"
-msgstr ""
+msgstr "Liczba samobójstw"
#: qcsrc/client/hud/panel/scoreboard.qc:123
msgid "SCO^suicides"
#: qcsrc/client/hud/panel/scoreboard.qc:128
msgid "SCO^time"
-msgstr ""
+msgstr "czas"
#: qcsrc/client/hud/panel/scoreboard.qc:128
msgid "Total time raced (Race/CTS)"
#: qcsrc/client/hud/panel/scoreboard.qc:313
msgid "Usage:"
-msgstr ""
+msgstr "Użycie:"
#: qcsrc/client/hud/panel/scoreboard.qc:315
msgid "^2scoreboard_columns_set ^3field1 field2 ..."
-msgstr ""
+msgstr "^2scoreboard_columns_set ^3pole1 pole2 …"
#: qcsrc/client/hud/panel/scoreboard.qc:316
msgid ""
#: qcsrc/client/hud/panel/scoreboard.qc:320
msgid "The following field names are recognized (case insensitive):"
msgstr ""
+"Następujące nazwy pól są rozpoznawane (wielkość liter nie ma znaczenia)"
#: qcsrc/client/hud/panel/scoreboard.qc:326
msgid ""
#: qcsrc/client/hud/panel/scoreboard.qc:336
msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
msgstr ""
+"Na przykład: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
#: qcsrc/client/hud/panel/scoreboard.qc:337
msgid ""
#: qcsrc/client/hud/panel/scoreboard.qc:1613
#, c-format
msgid "^3%1.0f minutes"
-msgstr ""
+msgstr "^3%1.0f minut"
#: qcsrc/client/hud/panel/scoreboard.qc:1622
#: qcsrc/client/hud/panel/scoreboard.qc:1629
#, c-format
msgid "^5%s %s"
-msgstr ""
+msgstr "^5%s %s"
#: qcsrc/client/hud/panel/scoreboard.qc:1623
#: qcsrc/client/hud/panel/scoreboard.qc:1630
#: qcsrc/client/hud/panel/timer.qc:67
msgid "WARMUP"
-msgstr ""
+msgstr "ROZGRZEWKA"
#: qcsrc/client/hud/panel/vote.qc:27
msgid "^1You must answer before entering hud configure mode"
#: qcsrc/client/mapvoting.qc:515
msgid "^1Error:^7 Couldn't find pak index."
-msgstr ""
+msgstr "^1Błąd:^7 Nie można znaleźć indeksu pak."
#: qcsrc/client/mapvoting.qc:524
msgid "Requesting preview..."
-msgstr ""
+msgstr "Oczekiwanie podglądu…"
#: qcsrc/client/miscfunctions.qc:111
msgid "Trying to remove a team which is not in the teamlist!"
#: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:333
#: qcsrc/common/mapinfo.qh:528
msgid "The amount of frags needed before the match will end"
-msgstr ""
+msgstr "Ilość zabójstw potrzebnych przed końcem meczu"
#: qcsrc/common/mapinfo.qh:114
msgid "Deathmatch"
#: qcsrc/common/mapinfo.qh:114
msgid "Score as many frags as you can"
-msgstr "Zdobądź jak najwięcej frag"
+msgstr "Zdobądź jak najwięcej zabójstw"
#: qcsrc/common/mapinfo.qh:127
msgid "Last Man Standing"
#: qcsrc/common/minigames/minigame/ttt.qc:2
msgid "Tic Tac Toe"
-msgstr ""
+msgstr "Kółko i krzyżyk"
#: qcsrc/common/minigames/minigame/ttt.qc:665
msgid "Single Player"
#: qcsrc/common/notifications/all.inc:336
#, c-format
msgid "^BG%s^K1 ran into a turret%s%s"
-msgstr ""
+msgstr "^BG%s^K1 wbiegł w wieżyczkę%s%s"
#: qcsrc/common/notifications/all.inc:337
#, c-format
#: qcsrc/common/notifications/all.inc:587
msgid "^BGEnemies can now see you on radar!"
-msgstr ""
+msgstr "^BGPrzeciwnicy mogą teraz Cię widzieć na radarze!"
#: qcsrc/common/notifications/all.inc:588
msgid "^BGYou returned the ^TC^TT^BG flag!"
#: qcsrc/common/notifications/all.inc:589
msgid "^BGStalemate! Enemies can now see you on radar!"
-msgstr ""
+msgstr "^BGMartwy punkt! Przeciwnicy mogą teraz Cię widzieć na radarze!"
#: qcsrc/common/notifications/all.inc:590
msgid "^BGStalemate! Flag carriers can now be seen by enemies on radar!"
#: qcsrc/common/notifications/all.inc:788
#, c-format
msgid "^BGPress ^F2%s^BG to enter/exit the vehicle"
-msgstr ""
+msgstr "^BGWciśnij ^F2%s^BG aby wejść/wyjść z pojazdu"
#: qcsrc/common/notifications/all.inc:789
#, c-format
#: qcsrc/common/notifications/all.inc:790
#, c-format
msgid "^BGPress ^F2%s^BG to steal this vehicle"
-msgstr ""
+msgstr "^BGWciśnij ^F2%s^BG aby ukraść pojazd"
#: qcsrc/common/notifications/all.inc:791
msgid ""
#: qcsrc/menu/command/menu_cmd.qc:48
msgid "Usage: menu_cmd command..., where possible commands are:"
-msgstr ""
+msgstr "Użycie: menu_cmd polecenie…, gdzie dostępnymi poleceniami są:"
#: qcsrc/menu/command/menu_cmd.qc:49
msgid " sync - reloads all cvars on the current menu page"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:33
msgid "EF^None"
-msgstr ""
+msgstr "EF^Brak"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:34
msgid "Alpha"
#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:124
msgid "Snap panels to grid"
-msgstr ""
+msgstr "Przyciągaj panele do siatki"
#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:127
msgid "Grid size:"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:81
msgid "Timelimit in minutes that when hit, will end the match"
-msgstr ""
+msgstr "Limit czasowy w minutach, który po trafieniu zakończy mecz"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:82
#, c-format
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:67
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:217
msgid "Invincible Projectiles"
-msgstr "Niezniszczalne Pociski"
+msgstr "Niezniszczalne pociski"
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:71
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:293
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:246
msgid "Custom weapons"
-msgstr ""
+msgstr "Niestandardowe bronie"
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:268
msgid "Most weapons"
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:153
msgid "Select language..."
-msgstr ""
+msgstr "Wybierz język…"
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:169
msgid "Gender:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:116
msgid "Idle limit:"
-msgstr "Brak limitu:"
+msgstr "Limit w trybie nieaktywnym:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:122
msgid "IDLFPS^Unlimited"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:121
msgid "Brightness of black"
-msgstr ""
+msgstr "Jasność czerni"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:123
msgid "Contrast:"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:125
msgid "Brightness of white"
-msgstr ""
+msgstr "Jasność bieli"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:127
msgid "Gamma:"
#: qcsrc/menu/xonotic/statslist.qc:103
msgid "Last match:"
-msgstr ""
+msgstr "Ostatni mecz:"
#: qcsrc/menu/xonotic/statslist.qc:110
msgid "Time played:"
#: qcsrc/menu/xonotic/statslist.qc:117 qcsrc/menu/xonotic/statslist.qc:230
msgid "Favorite map:"
-msgstr ""
+msgstr "Ulubiona mapa:"
#: qcsrc/menu/xonotic/statslist.qc:149 qcsrc/menu/xonotic/statslist.qc:201
#: qcsrc/menu/xonotic/statslist.qc:244
#
# Translators:
# Ivan Paulos Tomé <greylica@gmail.com>, 2016
-# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2018-2019
+# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2015,2018-2020
# Mirio <opivy@hotmail.de>, 2017
# NotThatPrivate Yes <henriqueferreira2009@gmail.com>, 2015
# Ricardo Manuel da Cruz Coelho da Silva <ricardo.mccs@gmail.com>, 2015
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-05-19 07:23+0200\n"
-"PO-Revision-Date: 2019-07-07 02:23+0000\n"
+"PO-Revision-Date: 2020-01-27 18:03+0000\n"
"Last-Translator: Jean Trindade Pereira <jean_trindade2@hotmail.com>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/team-xonotic/"
"xonotic/language/pt_BR/)\n"
sizeincrease -6
size 10 10
trailspacing 40
+effect TE_TEI_G3_HIT
+ type beam
+ alpha 128 128 256
+ color 0xFFFFFF 0xFFFFFF
+ countabsolute 1
+ size 8 8
+ tex 200 200
+effect TE_TEI_G3_HIT
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease -2
+ size 2 2
+ trailspacing 20
+ velocityjitter 2 2 2
+effect TE_TEI_G3_HIT
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease -6
+ size 10 10
+ trailspacing 40
effect particlegibs_damage_hit
type blood
airfriction 3
// ===========
// this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
set leadlimit 0
-set leadlimit_and_fraglimit 0 "if set, leadlimit is ANDed with fraglimit (otherwise ORed)"
+set leadlimit_and_fraglimit 0 "both leadlimit AND fraglimit must be reached"
set timelimit_override -1 "Time limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set fraglimit_override -1 "Frag limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set leadlimit_override -1 "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
seta hud_progressbar_health_color "0.83 0.12 0"
seta hud_progressbar_armor_color "0.28 0.8 0"
seta hud_progressbar_fuel_color "0.77 0.67 0"
+seta hud_progressbar_oxygen_color "0.1 1 1"
seta hud_progressbar_nexball_color "0.2 0.65 0.93"
seta hud_progressbar_speed_color "0.77 0.67 0"
seta hud_progressbar_acceleration_color "0.2 0.65 0.93"
seta hud_progressbar_health_color "0.6 0 0"
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_oxygen_color "0 1 1"
seta hud_progressbar_nexball_color "0.7 0.1 0"
seta hud_progressbar_speed_color "1 0.75 0"
seta hud_progressbar_acceleration_color "0.5 0.75 1"
seta hud_progressbar_health_color "0.6 0 0"
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_oxygen_color "0 1 1"
seta hud_progressbar_nexball_color "0.7 0.1 0"
seta hud_progressbar_speed_color "1 0.75 0"
seta hud_progressbar_acceleration_color "0.5 0.75 1"
seta hud_progressbar_health_color "0.6 0 0"
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_oxygen_color "0 1 1"
seta hud_progressbar_nexball_color "0.7 0.1 0"
seta hud_progressbar_speed_color "1 0.75 0"
seta hud_progressbar_acceleration_color "0.5 0.75 1"
seta hud_progressbar_health_color "0.6 0 0"
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_oxygen_color "0 1 1"
seta hud_progressbar_nexball_color "0.7 0.1 0"
seta hud_progressbar_speed_color "1 0.75 0"
seta hud_progressbar_acceleration_color "0.5 0.75 1"
seta hud_progressbar_health_color "0.6 0 0"
seta hud_progressbar_armor_color "0 0.6 0"
seta hud_progressbar_fuel_color "0.6 0.6 0"
+seta hud_progressbar_oxygen_color "0 1 1"
seta hud_progressbar_nexball_color "0.7 0.1 0"
seta hud_progressbar_speed_color "1 0.75 0"
seta hud_progressbar_acceleration_color "0.5 0.75 1"
it "Italian" "Italiano" 100%
hu "Hungarian" "Magyar" 48%
nl "Dutch" "Nederlands" 63%
-pl "Polish" "Polski" 72%
+pl "Polish" "Polski" 74%
pt "Portuguese" "Português" 86%
pt_BR "Portuguese (Brazil)" "Português (Brasil)" 100%
ro "Romanian" "Romana" 75%
set g_dodging 0 "set to 1 to enable dodging (quick acceleration in a given direction)"
seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable"
+seta cl_dodging 0 "enable dodging, requires sv_dodging_clientselect to be enabled on the server"
set sv_dodging_air_dodging 0
set sv_dodging_wall_dodging 0 "allow dodging off walls"
set sv_dodging_frozen_doubletap 0
set sv_dodging_maxspeed 350 "maximum speed a player can be moving at to use the standard dodging from an (almost) standstill"
set sv_dodging_air_maxspeed 450 "maximum speed a player can be moving at before they dodge again when air dodging is enabled"
+set sv_dodging_clientselect 0 "allow clients to opt-in to dodging movement with the cl_dodging cvar, dodging will be off for clients by default with this enabled"
// ===========
set g_campcheck_interval 10
set g_campcheck_damage 100
set g_campcheck_distance 1800
+set g_campcheck_typecheck 0 "damage campers who are typing"
// ==========
// ===========
// multijump
// ===========
-seta cl_multijump 1 "allow multijump mutator"
+seta cl_multijump -1 "allow multijump mutator, set to -1 for the server to decide whether it's enabled"
set g_multijump 0 "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
+set g_multijump_client 1 "If the client sets cl_multijump to -1, this setting is used for them as a default"
set g_multijump_add 0 "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
set g_multijump_speed -999999 "Minimum vertical speed a player must have in order to jump again"
set g_multijump_maxspeed 0
set g_random_items 0 "Whether to enable random items."
set g_random_loot 0 "Whether to enable random loot."
exec randomitems-xonotic.cfg
+
+// ===============
+// pinata
+// ===============
+set g_pinata 0 "if set to 1 you will not only drop your current weapon when you are killed, but you will drop all weapons that you possessed"
+set g_pinata_offhand 0 "if enabled, the second weapon will drop as well while dual wielding"
seta notification_INFO_WEAPON_VAPORIZER_MURDER "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_WEAPON_VORTEX_MURDER "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-// MSG_CENTER notifications (count = 239):
+// MSG_CENTER notifications (count = 240):
seta notification_CENTER_ALONE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ASSAULT_ATTACKING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ASSAULT_DEFENDING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ASSAULT_OBJ_DESTROYED "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_CAMPAIGN_MESSAGE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_CAMPCHECK "1" "0 = off, 1 = centerprint"
seta notification_CENTER_COINTOSS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_COUNTDOWN_BEGIN "1" "0 = off, 1 = centerprint"
seta notification_show_sprees_info_newline "1" "Show attacker spree information for MSG_INFO messages on a separate line than the death notification itself"
seta notification_show_sprees_info_specialonly "1" "Don't show attacker spree information in MSG_INFO messages if it isn't an achievement"
-// Notification counts (total = 846): MSG_ANNCE = 89, MSG_INFO = 334, MSG_CENTER = 239, MSG_MULTI = 156, MSG_CHOICE = 28
+// Notification counts (total = 847): MSG_ANNCE = 89, MSG_INFO = 334, MSG_CENTER = 240, MSG_MULTI = 156, MSG_CHOICE = 28
float autocvar_hud_progressbar_alpha;
vector autocvar_hud_progressbar_armor_color;
vector autocvar_hud_progressbar_fuel_color;
+vector autocvar_hud_progressbar_oxygen_color = '0.1 1 1';
vector autocvar_hud_progressbar_health_color;
vector autocvar_hud_progressbar_nexball_color;
vector autocvar_hud_progressbar_shield_color;
float autocvar_cl_hitsound_antispam_time;
bool autocvar_cl_eventchase_spectated_change = false;
float autocvar_cl_eventchase_spectated_change_time = 1;
-int autocvar_cl_eventchase_death = 1;
+int autocvar_cl_eventchase_death = 2;
float autocvar_cl_eventchase_distance = 140;
bool autocvar_cl_eventchase_frozen = false;
float autocvar_cl_eventchase_speed = 1.3;
HUD_Write_Cvar("hud_progressbar_health_color");
HUD_Write_Cvar("hud_progressbar_armor_color");
HUD_Write_Cvar("hud_progressbar_fuel_color");
+ HUD_Write_Cvar("hud_progressbar_oxygen_color");
HUD_Write_Cvar("hud_progressbar_nexball_color");
HUD_Write_Cvar("hud_progressbar_speed_color");
HUD_Write_Cvar("hud_progressbar_acceleration_color");
void HUD_HealthArmor()
{
- int armor, health, fuel;
+ int armor, health, fuel, air_time;
if(!autocvar__hud_configure)
{
if((!autocvar_hud_panel_healtharmor) || (spectatee_status == -1))
prev_armor = 0;
}
fuel = STAT(FUEL);
+ air_time = bound(0, STAT(AIR_FINISHED) - time, 10);
}
else
{
health = 150;
armor = 75;
fuel = 20;
+ air_time = 6;
}
HUD_Panel_LoadCvars();
mySize -= '2 2 0' * panel_bg_padding;
}
+ float air_alpha = 1;
+ if (STAT(AIR_FINISHED) && time > STAT(AIR_FINISHED))
+ {
+ air_alpha = blink_synced(0.5, 0.5, 7, STAT(AIR_FINISHED), -1);
+ air_time = 10;
+ }
+
int baralign = autocvar_hud_panel_healtharmor_baralign;
int iconalign = autocvar_hud_panel_healtharmor_iconalign;
if(fuel)
HUD_Panel_DrawProgressBar(pos, vec2(mySize.x, 0.2 * mySize.y), "progressbar", fuel/100, 0, (baralign == 1 || baralign == 3), autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
+ if(air_time)
+ HUD_Panel_DrawProgressBar(pos + eY * 0.8 * mySize.y, vec2(mySize.x, 0.2 * mySize.y), "progressbar", air_time / 10, 0, (baralign == 1 || baralign == 3), autocvar_hud_progressbar_oxygen_color, air_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
}
else
{
armor_offset.y = mySize.y;
}
- bool health_baralign, armor_baralign, fuel_baralign;
+ bool health_baralign, armor_baralign, fuel_baralign, air_align;
bool health_iconalign, armor_iconalign;
if (autocvar_hud_panel_healtharmor_flip)
{
armor_baralign = (autocvar_hud_panel_healtharmor_baralign == 2 || autocvar_hud_panel_healtharmor_baralign == 1);
health_baralign = (autocvar_hud_panel_healtharmor_baralign == 3 || autocvar_hud_panel_healtharmor_baralign == 1);
- fuel_baralign = health_baralign;
+ air_align = fuel_baralign = health_baralign;
armor_iconalign = (autocvar_hud_panel_healtharmor_iconalign == 2 || autocvar_hud_panel_healtharmor_iconalign == 1);
health_iconalign = (autocvar_hud_panel_healtharmor_iconalign == 3 || autocvar_hud_panel_healtharmor_iconalign == 1);
}
{
health_baralign = (autocvar_hud_panel_healtharmor_baralign == 2 || autocvar_hud_panel_healtharmor_baralign == 1);
armor_baralign = (autocvar_hud_panel_healtharmor_baralign == 3 || autocvar_hud_panel_healtharmor_baralign == 1);
- fuel_baralign = armor_baralign;
+ air_align = fuel_baralign = armor_baralign;
health_iconalign = (autocvar_hud_panel_healtharmor_iconalign == 2 || autocvar_hud_panel_healtharmor_iconalign == 1);
armor_iconalign = (autocvar_hud_panel_healtharmor_iconalign == 3 || autocvar_hud_panel_healtharmor_iconalign == 1);
}
if (health <= autocvar_hud_panel_healtharmor_progressbar_gfx_lowhealth)
{
- float BLINK_FACTOR = 0.15;
- float BLINK_BASE = 0.85;
- float BLINK_FREQ = 9;
- pain_health_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
+ pain_health_alpha = blink(0.85, 0.15, 9);
}
}
HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, p_health/maxhealth, is_vertical, health_baralign, autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * pain_health_alpha, DRAWFLAG_NORMAL);
DrawNumIcon(pos + armor_offset, mySize, armor, "armor", is_vertical, armor_iconalign, HUD_Get_Num_Color(armor, maxarmor), 1);
}
- if(fuel)
+ vector cell_size = mySize;
+ if (fuel || air_time)
{
if (is_vertical)
mySize.x *= 0.2 / 2; //if vertical always halve x to not cover too much numbers with 3 digits
mySize.x *= 2; //restore full panel size
else if (panel_ar < 1/4)
mySize.y *= 2; //restore full panel size
- HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
+ if (fuel)
+ HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
+ if (air_time)
+ {
+ if (panel_ar > 1 && panel_ar < 4)
+ pos.y += cell_size.y;
+ else if (panel_ar > 1/4 && panel_ar <= 1)
+ pos.x += cell_size.x;
+ if (is_vertical)
+ pos.x += cell_size.x - mySize.x;
+ else
+ pos.y += cell_size.y - mySize.y;
+ HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", air_time / 10, is_vertical, air_align, autocvar_hud_progressbar_oxygen_color, air_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
+ }
}
}
{
if(!autocvar__hud_configure)
{
- if(!autocvar_hud_panel_pressedkeys) return;
+ if(!autocvar_hud_panel_pressedkeys || spectatee_status < 0) return;
if(spectatee_status <= 0 && autocvar_hud_panel_pressedkeys < 2) return;
}
draw_endBoldFont();
// Game Info: Game Detail
- float tl, fl, ll;
- str = ""; // optionally "^7Limits: "
- tl = STAT(TIMELIMIT);
- fl = STAT(FRAGLIMIT);
- ll = STAT(LEADLIMIT);
+ float tl = STAT(TIMELIMIT);
+ float fl = STAT(FRAGLIMIT);
+ float ll = STAT(LEADLIMIT);
+ float ll_and_fl = STAT(LEADLIMIT_AND_FRAGLIMIT);
+ str = "";
if(tl > 0)
str = strcat(str, sprintf(_("^3%1.0f minutes"), tl));
if(!ISGAMETYPE(LMS))
if(ll > 0)
{
if(tl > 0 || fl > 0)
- str = strcat(str, "^7 / "); // delimiter
+ {
+ // delimiter
+ if (ll_and_fl && fl > 0)
+ str = strcat(str, "^7 & ");
+ else
+ str = strcat(str, "^7 / ");
+ }
+
if(teamplay)
{
str = strcat(str, sprintf(_("^2+%s %s"), ScoreString(teamscores_flags(ts_primary), ll),
registercvar("cl_shootfromfixedorigin", "");
- registercvar("cl_multijump", "1");
+ registercvar("cl_multijump", "-1");
registercvar("cl_spawn_near_teammate", "1");
return boxsize * (0.5 * (1 - sz));
}
+// NOTE base is the central value
+// freq: circle frequency, = 2*pi*frequency in hertz
+// start_pos:
+// -1 start from the lower value
+// 0 start from the base value
+// 1 start from the higher value
+float blink_synced(float base, float range, float freq, float start_time, int start_pos)
+{
+ // note:
+ // RMS = sqrt(base^2 + 0.5 * range^2)
+ // thus
+ // base = sqrt(RMS^2 - 0.5 * range^2)
+ // ensure RMS == 1
+
+ return base + range * sin((time - start_time - (M_PI / 2) * start_pos) * freq);
+}
+
+float blink(float base, float range, float freq)
+{
+ return blink_synced(base, range, freq, 0, 0);
+}
+
void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag)
{
vector line_dim = '0 0 0';
vector expandingbox_resize_centered_box_offset(float sz, vector boxsize, float boxxsizefactor);
+float blink_synced(float base, float range, float freq, float start_time, int start_blink);
+float blink(float base, float range, float freq);
+
void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag);
void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, float theAlpha, float drawflag);
}
if (autocvar_crosshair_ring_inner && ring_inner_value) // lets draw a ring inside a ring so you can ring while you ring
- DrawCircleClippedPic(wcross_origin, wcross_size.x * ring_scale, ring_inner_image, ring_inner_value, ring_inner_rgb, wcross_alpha * ring_inner_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(wcross_origin, wcross_size.x * wcross_resolution * ring_scale, ring_inner_image, ring_inner_value, ring_inner_rgb, wcross_alpha * ring_inner_alpha, DRAWFLAG_ADDITIVE);
if (ring_value)
- DrawCircleClippedPic(wcross_origin, wcross_size.x * ring_scale, ring_image, ring_value, ring_rgb, wcross_alpha * ring_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(wcross_origin, wcross_size.x * wcross_resolution * ring_scale, ring_image, ring_value, ring_rgb, wcross_alpha * ring_alpha, DRAWFLAG_ADDITIVE);
}
#define CROSSHAIR_DO_BLUR(M,sz,wcross_name,wcross_alpha) \
* 6: on (.solid != 0)
*/
bool autocvar_debugdraw;
-#endif
+#endif // GAMEQC
#ifdef CSQC
string autocvar_debugdraw_filter, autocvar_debugdraw_filterout;
});
});
}
-#endif
-
+#endif // CSQC
#ifdef SVQC
COMMON_COMMAND(debugdraw_sv, "Dump all server entities")
}
}
}
-#endif
-#endif
+#endif // SVQC
+#endif // ENABLE_DEBUGDRAW
GENERIC_COMMAND(bufstr_get, "Examine a string buffer object", false)
{
case CMD_REQUEST_COMMAND:
{
- LOG_INFO(WATERMARK);
+ LOG_INFO(PROGNAME, " version: ", WATERMARK);
return;
}
default:
#ifdef CSQC
void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
#endif
+
GENERIC_COMMAND(cvar_localchanges, "Print locally changed cvars", false)
{
switch (request)
#if ENABLE_DEBUGTRACE
REGISTER_STAT(TRACE_ENT, int)
+
#ifdef SVQC
bool autocvar_debugtrace;
stuffcmd(it, sprintf("prvm_edict server %d\n", i));
});
}
-#endif
+#endif // SVQC
+
#ifdef CSQC
entity TRACE_ENT;
void Trace_draw2d(entity this)
e.draw2d = Trace_draw2d;
IL_PUSH(g_drawables_2d, e);
}
-#endif
+#endif // CSQC
+
#endif
ATTRIB(DebugText3d, message, string); // the text (i wanted to use the .text field but then this whole macro-based-inheritance thing shat itself)
ATTRIB(DebugText3d, health, float); // text alignment (recycled field)
ATTRIB(DebugText3d, hit_time, float); // when it was created
- ATTRIB(DebugText3d, fade_rate, float); // how fast is should disappear
+ ATTRIB(DebugText3d, fade_rate, float); // how fast it should disappear
ATTRIB(DebugText3d, velocity, vector);
CONSTRUCTOR(DebugText3d, vector pos, string msg, float align, float fade_rate_, vector vel) {
TE_TEI_G3(PINK, "0xFF00FF", "0xFF11FF", "0x200020", "0x400040")
#undef TE_TEI_G3
+// Vaporizer hit effect
+DEF(TE_TEI_G3_HIT);
+SUB(TE_TEI_G3_HIT) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xFFFFFF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+SUB(TE_TEI_G3_HIT) /* rings */ {
+ MY(airfriction) = -4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xFFFFFF";
+ MY(sizeincrease) = -2;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(trailspacing) = 20;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '2.0 2.0 2.0';
+}
+SUB(TE_TEI_G3_HIT) {
+ MY(airfriction) = -4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xFFFFFF";
+ MY(sizeincrease) = -6;
+ MY(size_min) = 10;
+ MY(size_max) = 10;
+ MY(trailspacing) = 40;
+ MY(type) = "smoke";
+}
+
#include "effectinfo_gentle_particlegibs.inc"
#include "effectinfo_onslaught.inc"
X(neutral);
#undef X
- const float BLINK_FACTOR = 0.15;
- const float BLINK_BASE = 0.85;
- // note:
- // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
- // thus
- // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
- // ensure RMS == 1
- const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
-
#define X(team, cond) \
string team##_icon = string_null, team##_icon_prevstatus = string_null; \
int team##_alpha, team##_alpha_prevstatus; \
switch (team##flag) { \
case 1: team##_icon = "flag_" #team "_taken"; break; \
case 2: team##_icon = "flag_" #team "_lost"; break; \
- case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+ case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = blink(0.85, 0.15, 5); break; \
default: \
if ((stat_items & CTF_SHIELDED) && (cond)) { \
team##_icon = "flag_" #team "_shielded"; \
switch (team##flag_prevstatus) { \
case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
- case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+ case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = blink(0.85, 0.15, 5); break; \
default: \
if (team##flag == 3) { \
team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
if(!flag) { return; }
if((droptype == DROP_PASS) && !receiver) { return; }
- if(flag.speedrunning) { ctf_RespawnFlag(flag); return; }
+ if(flag.speedrunning)
+ {
+ // ensure old waypoints are removed before resetting the flag
+ WaypointSprite_Kill(player.wps_flagcarrier);
+
+ if(player.wps_enemyflagcarrier)
+ WaypointSprite_Kill(player.wps_enemyflagcarrier);
+
+ if(player.wps_flagreturn)
+ WaypointSprite_Kill(player.wps_flagreturn);
+ ctf_RespawnFlag(flag);
+ return;
+ }
// reset the flag
setattachment(flag, NULL, "");
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
- TeamScore_AddToTeam(winner_team, ST_SCORE, +1);
+ TeamScore_AddToTeam(winner_team, ST_FT_ROUNDS, +1);
}
else if(winner_team == -1)
{
return false;
}
+MUTATOR_HOOKFUNCTION(ft, Scores_CountFragsRemaining)
+{
+ // announce remaining frags
+ return true;
+}
+
void freezetag_Initialize()
{
freezetag_teams = autocvar_g_freezetag_teams_override;
freezetag_teams = BITS(bound(2, freezetag_teams, 4));
GameRules_scoring(freezetag_teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {
+ field_team(ST_FT_ROUNDS, "rounds", SFL_SORT_PRIO_PRIMARY);
field(SP_FREEZETAG_REVIVALS, "revivals", 0);
});
bool autocvar_g_freezetag_team_spawns;
string autocvar_g_freezetag_weaponarena = "most_available";
+const int ST_FT_ROUNDS = 1;
+
void freezetag_Initialize();
REGISTER_MUTATOR(ft, false)
{
mod_active = 1; // keepaway should always show the mod HUD
- float BLINK_FACTOR = 0.15;
- float BLINK_BASE = 0.85;
- float BLINK_FREQ = 5;
- float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
+ float kaball_alpha = blink(0.85, 0.15, 5);
int stat_items = STAT(ITEMS);
int kaball = (stat_items/IT_KEY1) & 1;
midpoint += thisorigin;
if(!first)
- te_lightning2(NULL, lastorigin, thisorigin);
+ {
+ // TODO: this effect has been replaced due to a possible crash it causes
+ // see https://gitlab.com/xonotic/darkplaces/issues/123
+ //te_lightning2(NULL, lastorigin, thisorigin);
+ Send_Effect(EFFECT_TR_NEXUIZPLASMA, lastorigin, thisorigin, 1);
+ }
lastorigin = thisorigin;
if(first)
firstorigin = thisorigin;
}
if(NumTeams(kh_teams) > 2)
{
- te_lightning2(NULL, lastorigin, firstorigin);
+ //te_lightning2(NULL, lastorigin, firstorigin); // TODO see above
+ Send_Effect(EFFECT_TR_NEXUIZPLASMA, lastorigin, firstorigin, 1);
}
midpoint = midpoint * (1 / NumTeams(kh_teams));
te_customflash(midpoint, 1000, 1, Team_ColorRGB(winner_team) * 0.5 + '0.5 0.5 0.5'); // make the color >=0.5 in each component
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
sound(toucher, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM);
STAT(BUFFS, toucher) |= (STAT(BUFFS, this));
+ STAT(LAST_PICKUP, toucher) = time;
float bufftime = ((this.count) ? this.count : thebuff.m_time(thebuff));
if(bufftime)
STAT(BUFF_TIME, toucher) = min(time + bufftime, max(STAT(BUFF_TIME, toucher), time) + bufftime);
#ifdef SVQC
entity player = M_ARGV(0, entity);
player.bugrigs_prevangles = player.angles;
+
+ player.disableclientprediction = 2;
#endif
}
float autocvar_g_campcheck_damage;
float autocvar_g_campcheck_distance;
float autocvar_g_campcheck_interval;
+bool autocvar_g_campcheck_typecheck;
REGISTER_MUTATOR(campcheck, expr_evaluate(autocvar_g_campcheck));
entity frag_attacker = M_ARGV(1, entity);
entity frag_target = M_ARGV(2, entity);
- if(IS_PLAYER(frag_target))
- if(IS_PLAYER(frag_attacker))
- if(frag_attacker != frag_target)
+ if(frag_attacker != frag_target && IS_PLAYER(frag_target) && IS_PLAYER(frag_attacker))
{
frag_target.campcheck_traveled_distance = autocvar_g_campcheck_distance;
frag_attacker.campcheck_traveled_distance = autocvar_g_campcheck_distance;
if(autocvar_g_campcheck_interval)
if(!game_stopped && !warmup_stage && time >= game_starttime)
- if(IS_PLAYER(player))
- if(!IS_DEAD(player))
- if(!STAT(FROZEN, player))
- if(!PHYS_INPUT_BUTTON_CHAT(player))
- if(IS_REAL_CLIENT(player)) // bots may camp, but that's no reason to constantly kill them
+ if(IS_PLAYER(player) && !IS_DEAD(player) && !STAT(FROZEN, player))
+ if(autocvar_g_campcheck_typecheck || !PHYS_INPUT_BUTTON_CHAT(player))
+ if(IS_REAL_CLIENT(player)) // only apply to real clients (bots may "camp" due to missing waypoints in the map, but that's no reason to constantly kill them, clones can't move)
if(!weaponLocked(player))
{
// calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement)
float cvar_cl_dodging_timeout;
REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+
+float cvar_cl_dodging;
+REPLICATE(cvar_cl_dodging, float, "cl_dodging");
#define PHYS_DODGING_AIR autocvar_sv_dodging_air_dodging
#define PHYS_DODGING_MAXSPEED autocvar_sv_dodging_maxspeed
#define PHYS_DODGING_AIR_MAXSPEED autocvar_sv_dodging_air_maxspeed
+#define PHYS_DODGING_CLIENTSELECT autocvar_sv_dodging_clientselect
// we ran out of stats slots! TODO: re-enable this when prediction is available for dodging
#if 0
#define PHYS_DODGING_AIR STAT(DODGING_AIR, this)
#define PHYS_DODGING_MAXSPEED STAT(DODGING_MAXSPEED, this)
#define PHYS_DODGING_AIR_MAXSPEED STAT(DODGING_AIR_MAXSPEED, this)
+#define PHYS_DODGING_CLIENTSELECT STAT(DODGING_CLIENTSELECT, this)
#endif
#ifdef CSQC
float cvar_cl_dodging_timeout;
+ bool cvar_cl_dodging;
+ bool autocvar_cl_dodging;
#define PHYS_DODGING_FRAMETIME (1 / (frametime <= 0 ? 60 : frametime))
#define PHYS_DODGING_TIMEOUT(s) STAT(DODGING_TIMEOUT)
#define PHYS_DODGING_PRESSED_KEYS(s) (s).pressedkeys
+ #define PHYS_DODGING_ENABLED(s) autocvar_cl_dodging
#elif defined(SVQC)
.float cvar_cl_dodging_timeout;
+ .bool cvar_cl_dodging;
#define PHYS_DODGING_FRAMETIME sys_frametime
#define PHYS_DODGING_TIMEOUT(s) CS(s).cvar_cl_dodging_timeout
#define PHYS_DODGING_PRESSED_KEYS(s) CS(s).pressedkeys
+ #define PHYS_DODGING_ENABLED(s) CS(s).cvar_cl_dodging
#endif
#ifdef SVQC
if (!this.dodging_action) return;
// when swimming or dead, no dodging allowed..
- if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this))
+ if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this) || (PHYS_DODGING_CLIENTSELECT && !PHYS_DODGING_ENABLED(this)))
{
this.dodging_action = 0;
this.dodging_direction.x = 0;
#ifdef SVQC
REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+REPLICATE(cvar_cl_dodging, bool, "cl_dodging");
MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
{
if (autocvar_hud_panel_itemstime_hidespawned == 2)
picalpha = 1;
else if (item_available)
- {
- float BLINK_FACTOR = 0.15;
- float BLINK_BASE = 0.85;
- float BLINK_FREQ = 5;
- picalpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
- }
+ picalpha = blink(0.85, 0.15, 5);
else
picalpha = 0.5;
t = floor(item_time - time + 0.999);
#define PHYS_MULTIJUMP_MAXSPEED(s) STAT(MULTIJUMP_MAXSPEED, s)
#define PHYS_MULTIJUMP_DODGING(s) STAT(MULTIJUMP_DODGING, s)
#define PHYS_MULTIJUMP_COUNT(s) STAT(MULTIJUMP_COUNT, s)
+#define PHYS_MULTIJUMP_CLIENTDEFAULT(s) STAT(MULTIJUMP_CLIENT, s)
.bool multijump_ready;
#ifdef CSQC
-bool cvar_cl_multijump;
-bool autocvar_cl_multijump = true;
+int cvar_cl_multijump;
+int autocvar_cl_multijump = -1;
#define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
#elif defined(SVQC)
-.bool cvar_cl_multijump;
+.int cvar_cl_multijump;
#define PHYS_MULTIJUMP_CLIENT(s) CS(s).cvar_cl_multijump
#endif
if(!PHYS_MULTIJUMP(player)) { return; }
int client_multijump = PHYS_MULTIJUMP_CLIENT(player);
+ if(client_multijump == -1)
+ client_multijump = PHYS_MULTIJUMP_CLIENTDEFAULT(player);
if(client_multijump > 1)
return; // nope
}
}
-REPLICATE(cvar_cl_multijump, bool, "cl_multijump");
+REPLICATE(cvar_cl_multijump, int, "cl_multijump");
#ifdef SVQC
METHOD(OverkillHeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
- if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
- PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
- else
- PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+ if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
+ PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
}
METHOD(OverkillHeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
- else
- PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
}
METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
#include "sv_pinata.qh"
string autocvar_g_pinata;
+bool autocvar_g_pinata_offhand;
REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !MUTATOR_IS_ENABLED(mutator_instagib) && !MUTATOR_IS_ENABLED(ok));
MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
if(frag_target.(weaponentity).m_weapon == WEP_Null)
continue;
+ if(slot > 0 && !autocvar_g_pinata_offhand)
+ break;
+
FOREACH(Weapons, it != WEP_Null, {
if(STAT(WEAPONS, frag_target) & WepSet_FromWeapon(it))
if(frag_target.(weaponentity).m_weapon != it)
MSG_CENTER_NOTIF(INSTAGIB_FINDAMMO_FIRST, N_ENABLE, 0, 0, "", CPID_INSTAGIB_FINDAMMO, "1 10", _("^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"), _("^BGGet some ammo! ^F4^COUNT^BG left!"))
MSG_CENTER_NOTIF(INSTAGIB_LIVES_REMAINING, N_ENABLE, 0, 1, "f1", CPID_Null, "0 0", _("^F2Extra lives remaining: ^K1%s"), "")
- MSG_CENTER_NOTIF(MOTD, N_ENABLE, 1, 0, "s1", CPID_MOTD, "-1 0", "^BG%s", "")
+ MSG_CENTER_NOTIF(CAMPAIGN_MESSAGE, N_ENABLE, 1, 1, "f1 s1 join_key", CPID_CAMPAIGN_MESSAGE, "-1 0", strcat(_("Level %s: "), "^BG%s\n^3\n", _("^BGPress ^F2%s^BG to enter the game")), "")
+ MSG_CENTER_NOTIF(MOTD, N_ENABLE, 1, 0, "s1 join_key", CPID_MOTD, "-1 0", strcat("^BG%s\n^3\n", _("^BGPress ^F2%s^BG to enter the game")), "")
MSG_CENTER_NOTIF(NIX_COUNTDOWN, N_ENABLE, 0, 2, "item_wepname", CPID_NIX, "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "")
MSG_CENTER_NOTIF(NIX_NEWWEAPON, N_ENABLE, 0, 1, "item_wepname", CPID_NIX, "0 0", _("^F2Active weapon: ^F1%s"), "")
CASE(CPID, MISSING_TEAMS)
CASE(CPID, MISSING_PLAYERS)
CASE(CPID, INSTAGIB_FINDAMMO)
+ CASE(CPID, CAMPAIGN_MESSAGE)
CASE(CPID, MOTD)
CASE(CPID, NIX)
CASE(CPID, ONSLAUGHT)
ARG_CASE(ARG_CS, "missing_teams", notif_arg_missing_teams(f1)) \
ARG_CASE(ARG_CS, "pass_key", getcommandkey(_("drop flag"), "+use")) \
ARG_CASE(ARG_CS, "nade_key", getcommandkey(_("throw nade"), "dropweapon")) \
+ ARG_CASE(ARG_CS, "join_key", getcommandkey(_("jump"), "+jump")) \
ARG_CASE(ARG_CS, "frag_ping", notif_arg_frag_ping(true, f2)) \
ARG_CASE(ARG_CS, "frag_stats", notif_arg_frag_stats(f2, f3, f4)) \
/*ARG_CASE(ARG_CS, "frag_pos", ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
_Movetype_LinkEdict_TouchAreaGrid(this);
}
+int _Movetype_ContentsMask(entity this) // SV_GenericHitSuperContentsMask
+{
+ if(this)
+ {
+ if(this.dphitcontentsmask)
+ return this.dphitcontentsmask;
+ else if(this.solid == SOLID_SLIDEBOX)
+ {
+ if(this.flags & 32) // TODO: FL_MONSTER
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_MONSTERCLIP;
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+ }
+ else if(this.solid == SOLID_CORPSE)
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY;
+ else if(this.solid == SOLID_TRIGGER)
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY;
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+ }
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+}
+
entity _Movetype_TestEntityPosition_ent;
bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
{
//int cont = this.dphitcontentsmask;
//this.dphitcontentsmask = DPCONTENTS_SOLID;
- tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
+ tracebox(org, this.mins, this.maxs, this.origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
//this.dphitcontentsmask = cont;
-
- if(trace_startsolid)
+ if(trace_dpstartcontents & _Movetype_ContentsMask(this))
return true;
- if(vdist(trace_endpos - this.origin, >, 0.0001))
+ if(vlen2(trace_endpos - this.origin) >= 0.0001)
{
tracebox(trace_endpos, this.mins, this.maxs, trace_endpos, MOVE_NOMONSTERS, this);
if(!trace_startsolid)
return false;
}
+bool _Movetype_TestEntityPosition_Offset(int offset)
+{
+ // NOTE: expects _Movetype_TestEntityPosition_ent to be set to the correct entity
+ // returns true if stuck
+
+ // start at 2, since the first position has already been checked
+ for(int j = 2; j <= offset; ++j)
+ {
+ if(!_Movetype_TestEntityPosition('0 0 -1' * j))
+ return false;
+ if(!_Movetype_TestEntityPosition('0 0 1' * j))
+ return false;
+ }
+
+ return true;
+}
+
int _Movetype_UnstickEntity(entity this) // SV_UnstickEntity
{
_Movetype_TestEntityPosition_ent = this;
X('-1 1 0') X(' 1 1 0')
#undef X
{
- #define X(i) \
- if (_Movetype_TestEntityPosition('0 0 -1' * i)) \
- if (_Movetype_TestEntityPosition('0 0 1' * i))
- X(2) X(3) X(4) X(5) X(6) X(7) X(8)
- X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
- X(17)
- #undef X
+ if(_Movetype_TestEntityPosition_Offset(rint((this.maxs.z - this.mins.z) * 0.36)))
{
LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)",
etof(this), this.classname, vtos(this.origin));
#define GAMEPLAYFIX_DOWNTRACEONGROUND(s) STAT(GAMEPLAYFIX_DOWNTRACEONGROUND)
#define GAMEPLAYFIX_EASIERWATERJUMP(s) STAT(GAMEPLAYFIX_EASIERWATERJUMP)
#define GAMEPLAYFIX_STEPDOWN(s) STAT(GAMEPLAYFIX_STEPDOWN)
+#define GAMEPLAYFIX_STEPDOWN_MAXSPEED(s) STAT(GAMEPLAYFIX_STEPDOWN_MAXSPEED)
#define GAMEPLAYFIX_STEPMULTIPLETIMES(s) STAT(GAMEPLAYFIX_STEPMULTIPLETIMES)
#define GAMEPLAYFIX_UNSTICKPLAYERS(s) STAT(GAMEPLAYFIX_UNSTICKPLAYERS)
#define GAMEPLAYFIX_WATERTRANSITION(s) STAT(GAMEPLAYFIX_WATERTRANSITION)
_Movetype_WallFriction(this, move_stepnormal);
}
// don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
- else if (!GAMEPLAYFIX_STEPDOWN(this) || this.waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || IS_ONGROUND(this))
+ else if (!GAMEPLAYFIX_STEPDOWN(this) || this.waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0)
+ || !oldonground || IS_ONGROUND(this) || (GAMEPLAYFIX_STEPDOWN_MAXSPEED(this) && vdist(start_velocity, >=, GAMEPLAYFIX_STEPDOWN_MAXSPEED(this)) && !IS_ONSLICK(this)))
{
return;
}
}
if (!doublejump)
- if (!IS_ONGROUND(this) && !IS_ONSLICK(this))
+ if (!IS_ONGROUND(this))
return IS_JUMP_HELD(this);
if(PHYS_TRACK_CANJUMP(this))
trace_dphitq3surfaceflags = 0;
tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
- {
- if(PHYS_SLICK_APPLYGRAVITY(this))
- UNSET_ONGROUND(this);
SET_ONSLICK(this);
- }
else
UNSET_ONSLICK(this);
}
void PlayerState_attach(entity this)
{
- if (PS(this))
+ if (PS(this) && PS(this).m_client == this)
return;
this._ps = NEW(PlayerState, this);
/** compressShotOrigin */
REGISTER_STAT(SHOTORG, int)
REGISTER_STAT(LEADLIMIT, float, autocvar_leadlimit)
+REGISTER_STAT(LEADLIMIT_AND_FRAGLIMIT, float, autocvar_leadlimit_and_fraglimit)
REGISTER_STAT(LAST_PICKUP, float)
REGISTER_STAT(HUD, int)
REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
REGISTER_STAT(TYPEHIT_TIME, float)
REGISTER_STAT(SUPERWEAPONS_FINISHED, float)
+REGISTER_STAT(AIR_FINISHED, float)
REGISTER_STAT(VEHICLESTAT_HEALTH, int)
REGISTER_STAT(VEHICLESTAT_SHIELD, int)
REGISTER_STAT(VEHICLESTAT_ENERGY, int)
float autocvar_g_multijump_speed;
float autocvar_g_multijump_maxspeed;
float autocvar_g_multijump_dodging = 1;
+bool autocvar_g_multijump_client = true;
#endif
REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+REGISTER_STAT(MULTIJUMP_CLIENT, bool, autocvar_g_multijump_client)
.int multijump_count;
REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
int autocvar_sv_gameplayfix_downtracesupportsongroundflag = 1;
int autocvar_sv_gameplayfix_easierwaterjump = 1;
int autocvar_sv_gameplayfix_stepdown = 2;
+float autocvar_sv_gameplayfix_stepdown_maxspeed = 0;
int autocvar_sv_gameplayfix_stepmultipletimes = 1;
int autocvar_sv_gameplayfix_unstickplayers = 1;
int autocvar_sv_gameplayfix_fixedcheckwatertransition = 1;
REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag)
REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump)
REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, autocvar_sv_gameplayfix_stepdown)
+REGISTER_STAT(GAMEPLAYFIX_STEPDOWN_MAXSPEED, float, autocvar_sv_gameplayfix_stepdown_maxspeed)
REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, autocvar_sv_gameplayfix_stepmultipletimes)
REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, autocvar_sv_gameplayfix_unstickplayers)
REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
bool autocvar_sv_dodging_air_dodging;
float autocvar_sv_dodging_maxspeed;
float autocvar_sv_dodging_air_maxspeed;
+bool autocvar_sv_dodging_clientselect;
#endif
#if 0
REGISTER_STAT(DODGING_AIR, bool, autocvar_sv_dodging_air_dodging)
REGISTER_STAT(DODGING_MAXSPEED, float, autocvar_sv_dodging_maxspeed)
REGISTER_STAT(DODGING_AIR_MAXSPEED, float, autocvar_sv_dodging_air_maxspeed)
+REGISTER_STAT(DODGING_CLIENTSELECT, bool, autocvar_sv_dodging_clientselect)
#endif
/** cvar loopback */
REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
return false;
}
else if (g_weapon_stay == 2)
+ {
ammomax = min(amount, ammomax);
+ if(player_amount >= ammomax)
+ return false;
+ }
else
return false;
if (amount < 0)
vector a = '0 0 0';
switch(fr)
{
+ default:
case WFRAME_IDLE: a = wepent.anim_idle; break;
case WFRAME_FIRE1: a = wepent.anim_fire1; break;
case WFRAME_FIRE2: a = wepent.anim_fire2; break;
- default:
case WFRAME_RELOAD: a = wepent.anim_reload; break;
}
a.z *= t;
}
.vector vorg1, vorg2;
-.float spawn_time;
void VaporizerBeam_Draw(entity this)
{
//draw either the old v2.3 beam or the new beam
if (IS_SVQC) {
if (this.move_movetype == MOVETYPE_NONE) { return; }
// when we get here, disableclientprediction cannot be 2
- this.disableclientprediction = (this.move_qcphysics) ? -1 : 0;
+ if(this.move_movetype == MOVETYPE_FOLLOW) // not compatible with prediction
+ this.disableclientprediction = 1;
+ else if(this.move_qcphysics)
+ this.disableclientprediction = -1;
+ else
+ this.disableclientprediction = 0;
}
viewloc_PlayerPhysics(this);
this.com_phys_gravity = '0 0 0';
} else if (ITEMS_STAT(this) & IT_USING_JETPACK) {
PM_jetpack(this, maxspeed_mod, dt);
- } else if (IS_ONGROUND(this)) {
+ } else if (IS_ONGROUND(this) && (!IS_ONSLICK(this) || !PHYS_SLICK_APPLYGRAVITY(this))) {
if (!WAS_ONGROUND(this)) {
emit(phys_land, this);
if (this.lastground < time - 0.3) {
{
CSQCPlayer_CalcRefdef(view);
}
-
}
else
{
//const int PMF_DUCKED = 4;
//const int PMF_ONGROUND = 8;
-const int FL_DUCKED = 524288;
+const int FL_DUCKED = BIT(19);
void CSQCPlayer_SetCamera();
float CSQCPlayer_PreUpdate(entity this);
this.iorigin2 = this.origin;
}
- if (this.iflags & IFLAG_AUTOANGLES
+ if ((this.iflags & IFLAG_AUTOANGLES)
&& this.iorigin2
!= this.iorigin1) this.angles = vectoangles(this.iorigin2 - this.iorigin1);
- if (this.iflags & IFLAG_AUTOVELOCITY
+ if ((this.iflags & IFLAG_AUTOVELOCITY)
&& this.itime2
!= this.itime1) this.velocity = (this.iorigin2 - this.iorigin1) * (1.0 / (this.itime2 - this.itime1));
/** color code replace, place inside of sprintf and parse the string */
string CCR(string input)
{
- // See the autocvar declarations in util.qh for default values
-
// foreground/normal colors
input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
return min(max(v.x, -v.x), max(v.y, -v.y));
}
-ERASEABLE
-float dist_point_line(vector p, vector l0, vector ldir)
-{
- ldir = normalize(ldir);
-
- // remove the component in line direction
- p = p - (p * ldir) * ldir;
-
- // vlen of the remaining vector
- return vlen(p);
-}
-
/** requires that m2>m1 in all coordinates, and that m4>m3 */
ERASEABLE
float boxesoverlap(vector m1, vector m2, vector m3, vector m4) { return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z; }
noref vector _yinvert;
#define yinvert(v) (_yinvert = (v), _yinvert.y = 1 - _yinvert.y, _yinvert)
+/// \param[in] p point
+/// \param[in] l0 starting point of ldir
+/// \param[in] ldir line
+/// \return Vector starting from p perpendicular to ldir
+ERASEABLE
+vector point_line_vec(vector p, vector l0, vector ldir)
+{
+ ldir = normalize(ldir);
+ p = l0 - p;
+ // remove the component in line direction from p
+ return p - ((p * ldir) * ldir);
+}
+
/**
* @param dir the directional vector
* @param norm the normalized normal
}
bool isnan(float e)
{
- // the sane way to detect NaN is broken because of a compiler bug
- // (works with constants but breaks when assigned to variables)
- // use conversion to string instead
- //float f = e;
- //return (e != f);
+ // The sane way to detect NaN is this:
+ // float f = e;
+ // return (e != f);
+ // but darkplaces used to be compiled with -ffinite-math-only which broke it.
+ // DP is fixed now but until all clients update (so after 0.8.3) we have to use the following workaround
+ // or they'd have issues when connecting to newer servers.
// Negative NaN ("-nan") is much more common but plain "nan" can be created by negating *some* -nans so we need to check both.
// DP's QCVM and GMQCC's QCVM behave differently - one needs ftos(-(0.0 / 0.0)), the other ftos(-sqrt(-1)).
{
return fabs(e) * ((f>0) ? 1 : -1);
}
-/// Always use `isnan` function to compare because `float x = nan(); x == x;` gives true
+
float nan(string tag)
{
return sqrt(-1);
s = campaign_shortdesc[i]; // fteqcc sucks
else
s = "???";
- s = draw_TextShortenToWidth(sprintf(_("Level %d: %s"), i+1, s), me.columnNameSize, 0, me.realFontSize);
+ // NOTE the following string is equal to the one used in the campaign level notification
+ // (CAMPAIGN_MESSAGE) to avoid adding another duplicate string to translate
+ s = draw_TextShortenToWidth(strcat(sprintf(_("Level %s: "), itos(i+1)), s), me.columnNameSize, 0, me.realFontSize);
draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, theColor, theAlpha, 0);
if(i <= me.campaignIndex)
me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "chase_active", "0", _("1st person perspective")));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_eventchase_death", _("Slide to third person upon death")));
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(2, 0, "cl_eventchase_death", _("Slide to third person upon death")));
setDependent(e, "chase_active", -1, 0);
me.TR(me);
me.TDempty(me, 0.2);
_("Brightness of white")));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Gamma:")));
- setDependentAND(e, "vid_gl20", 1, 1, "v_glslgamma", 1, 1);
+ setDependent(e, "vid_gl20", 1, 1);
me.TD(me, 1, 2, e = makeXonoticSlider_T(0.5, 2.0, 0.05, "v_gamma",
_("Inverse gamma correction value, a brightness effect that does not affect white or black")));
- setDependentAND(e, "vid_gl20", 1, 1, "v_glslgamma", 1, 1);
+ setDependent(e, "vid_gl20", 1, 1);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Contrast boost:")));
- setDependentAND(e, "vid_gl20", 1, 1, "v_glslgamma", 1, 1);
+ setDependent(e, "vid_gl20", 1, 1);
me.TD(me, 1, 2, e = makeXonoticSlider_T(1.0, 5.0, 0.1, "v_contrastboost",
_("By how much to multiply the contrast in dark areas")));
- setDependentAND(e, "vid_gl20", 1, 1, "v_glslgamma", 1, 1);
+ setDependent(e, "vid_gl20", 1, 1);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Saturation:")));
setDependent(e, "vid_gl20", 1, 1);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_gl20", _("Use OpenGL 2.0 shaders (GLSL)")));
e.applyButton = videoApplyButton;
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox_T(0, "v_glslgamma", _("Use GLSL to handle color control"),
- _("Enable use of GLSL to apply gamma correction, note that it might decrease performance by a lot")));
- setDependent(e, "vid_gl20", 1, 1);
if(cvar("developer") > 0)
{
me.TR(me);
// clear buttons
PHYS_INPUT_BUTTON_ATCK(this) = false;
- PHYS_INPUT_BUTTON_JUMP(this) = false;
+ // keep jump button pressed for a short while, useful with ramp jumps
+ PHYS_INPUT_BUTTON_JUMP(this) = (!IS_DEAD(this) && time < this.bot_jump_time + 0.2);
PHYS_INPUT_BUTTON_ATCK2(this) = false;
PHYS_INPUT_BUTTON_ZOOM(this) = false;
PHYS_INPUT_BUTTON_CROUCH(this) = false;
void bot_setnameandstuff(entity this)
{
string readfile, s;
- float file, tokens, prio;
-
- string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
- string name, prefix, suffix;
-
- if(autocvar_g_campaign)
- {
- prefix = "";
- suffix = "";
- }
- else
- {
- prefix = autocvar_bot_prefix;
- suffix = autocvar_bot_suffix;
- }
+ int file, tokens, prio;
file = fopen(autocvar_bot_config_file, FILE_READ);
fclose(file);
}
+ string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
+
tokens = tokenizebyseparator(readfile, "\t");
if(argv(0) != "") bot_name = argv(0);
else bot_name = "Bot";
setcolor(this, stof(bot_shirt) * 16 + stof(bot_pants));
this.bot_preferredcolors = this.clientcolors;
- // pick the name
- if (autocvar_bot_usemodelnames)
- name = bot_model;
- else
- name = bot_name;
+ string prefix = (autocvar_g_campaign ? "" : autocvar_bot_prefix);
+ string suffix = (autocvar_g_campaign ? "" : autocvar_bot_suffix);
+ string name = (autocvar_bot_usemodelnames ? bot_model : bot_name);
- // number bots with identical names
if (name == "")
{
name = ftos(etof(this));
}
else
{
+ // number bots with identical names
int j = 0;
FOREACH_CLIENT(IS_BOT_CLIENT(it), {
if(it.cleanname == name)
void bot_custom_weapon_priority_setup()
{
+ static string bot_priority_far_prev;
+ static string bot_priority_mid_prev;
+ static string bot_priority_close_prev;
+ static string bot_priority_distances_prev;
float tokens, i, w;
bot_custom_weapon = false;
if( autocvar_bot_ai_custom_weapon_priority_far == "" ||
autocvar_bot_ai_custom_weapon_priority_mid == "" ||
autocvar_bot_ai_custom_weapon_priority_close == "" ||
- autocvar_bot_ai_custom_weapon_priority_distances == ""
+ autocvar_bot_ai_custom_weapon_priority_distances == ""
)
return;
- // Parse distances
- tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
-
- if (tokens!=2)
- return;
-
- bot_distance_far = stof(argv(0));
- bot_distance_close = stof(argv(1));
-
- if(bot_distance_far < bot_distance_close){
- bot_distance_far = stof(argv(1));
- bot_distance_close = stof(argv(0));
- }
+ if (bot_priority_distances_prev != autocvar_bot_ai_custom_weapon_priority_distances)
+ {
+ strcpy(bot_priority_distances_prev, autocvar_bot_ai_custom_weapon_priority_distances);
+ tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
- // Initialize list of weapons
- bot_weapons_far[0] = -1;
- bot_weapons_mid[0] = -1;
- bot_weapons_close[0] = -1;
+ if (tokens!=2)
+ return;
- // Parse far distance weapon priorities
- tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
+ bot_distance_far = stof(argv(0));
+ bot_distance_close = stof(argv(1));
- int c = 0;
- for(i=0; i < tokens && c < Weapons_COUNT; ++i){
- w = stof(argv(i));
- if ( w >= WEP_FIRST && w <= WEP_LAST) {
- bot_weapons_far[c] = w;
- ++c;
+ if(bot_distance_far < bot_distance_close){
+ bot_distance_far = stof(argv(1));
+ bot_distance_close = stof(argv(0));
}
}
- if(c < Weapons_COUNT)
- bot_weapons_far[c] = -1;
- // Parse mid distance weapon priorities
- tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_mid)," ");
-
- c = 0;
- for(i=0; i < tokens && c < Weapons_COUNT; ++i){
- w = stof(argv(i));
- if ( w >= WEP_FIRST && w <= WEP_LAST) {
- bot_weapons_mid[c] = w;
- ++c;
- }
- }
- if(c < Weapons_COUNT)
- bot_weapons_mid[c] = -1;
-
- // Parse close distance weapon priorities
- tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_close)," ");
+ int c;
+
+ #define PARSE_WEAPON_PRIORITIES(dist) MACRO_BEGIN \
+ if (bot_priority_##dist##_prev != autocvar_bot_ai_custom_weapon_priority_##dist) { \
+ strcpy(bot_priority_##dist##_prev, autocvar_bot_ai_custom_weapon_priority_##dist); \
+ tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_##dist)," "); \
+ bot_weapons_##dist[0] = -1; \
+ c = 0; \
+ for(i = 0; i < tokens && c < Weapons_COUNT; ++i) { \
+ w = stof(argv(i)); \
+ if (w >= WEP_FIRST && w <= WEP_LAST) { \
+ bot_weapons_##dist[c] = w; \
+ ++c; \
+ } \
+ } \
+ if (c < Weapons_COUNT) \
+ bot_weapons_##dist[c] = -1; \
+ } \
+ MACRO_END
- c = 0;
- for(i=0; i < tokens && i < Weapons_COUNT; ++i){
- w = stof(argv(i));
- if ( w >= WEP_FIRST && w <= WEP_LAST) {
- bot_weapons_close[c] = w;
- ++c;
- }
- }
- if(c < Weapons_COUNT)
- bot_weapons_close[c] = -1;
+ PARSE_WEAPON_PRIORITIES(far);
+ PARSE_WEAPON_PRIORITIES(mid);
+ PARSE_WEAPON_PRIORITIES(close);
bot_custom_weapon = true;
}
if (autocvar_g_waypointeditor_auto)
botframe_autowaypoints();
- if(time > bot_cvar_nextthink)
- {
- if(currentbots>0)
- bot_custom_weapon_priority_setup();
- bot_cvar_nextthink = time + 5;
- }
+ if (currentbots > 0)
+ bot_custom_weapon_priority_setup();
}
.bool bot_pickup_respawning;
.float bot_canfire;
.float bot_strategytime;
+.float bot_jump_time;
.float bot_forced_team;
.float bot_config_loaded;
float botframe_spawnedwaypoints;
float botframe_nextthink;
float botframe_nextdangertime;
-float bot_cvar_nextthink;
int _content_type;
#define IN_LAVA(pos) (_content_type = pointcontents(pos), (_content_type == CONTENT_LAVA || _content_type == CONTENT_SLIME))
float autocvar_bot_ai_aimskill_order_mix_4th;
float autocvar_bot_ai_aimskill_order_mix_5th;
float autocvar_bot_ai_aimskill_think;
-float autocvar_bot_ai_bunnyhop_firstjumpdelay;
float autocvar_bot_ai_bunnyhop_skilloffset;
-float autocvar_bot_ai_bunnyhop_startdistance;
-float autocvar_bot_ai_bunnyhop_stopdistance;
+float autocvar_bot_ai_bunnyhop_dir_deviation_max;
+float autocvar_bot_ai_bunnyhop_downward_pitch_max;
+float autocvar_bot_ai_bunnyhop_turn_angle_min;
+float autocvar_bot_ai_bunnyhop_turn_angle_max;
+float autocvar_bot_ai_bunnyhop_turn_angle_reduction;
float autocvar_bot_ai_chooseweaponinterval;
string autocvar_bot_ai_custom_weapon_priority_close;
string autocvar_bot_ai_custom_weapon_priority_distances;
float autocvar_bot_ai_dangerdetectioninterval;
float autocvar_bot_ai_dangerdetectionupdates;
float autocvar_bot_ai_enemydetectioninterval;
+float autocvar_bot_ai_enemydetectioninterval_stickingtoenemy;
float autocvar_bot_ai_enemydetectionradius;
float autocvar_bot_ai_friends_aware_pickup_radius;
float autocvar_bot_ai_ignoregoal_timeout;
}
else
{
- if (!this.jumppadcount && !STAT(FROZEN, this))
+ if (!this.jumppadcount && !STAT(FROZEN, this)
+ && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
+ {
+ // find a new goal
this.havocbot_role(this); // little too far down the rabbit hole
+ }
}
// if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
{
if (this.goalcurrent)
navigation_clearroute(this);
+ this.enemy = NULL;
+ this.bot_aimtarg = NULL;
return;
}
}
}
+void havocbot_bunnyhop(entity this, vector dir)
+{
+ bool can_run = false;
+ if (!(this.aistatus & AI_STATUS_ATTACKING) && this.goalcurrent && !IS_PLAYER(this.goalcurrent)
+ && vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed) && !(this.aistatus & AI_STATUS_DANGER_AHEAD)
+ && this.waterlevel <= WATERLEVEL_WETFEET && !IS_DUCKED(this)
+ && IS_ONGROUND(this) && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
+ {
+ vector vel_angles = vectoangles(this.velocity);
+ vector deviation = vel_angles - vectoangles(dir);
+ while (deviation.y < -180) deviation.y = deviation.y + 360;
+ while (deviation.y > 180) deviation.y = deviation.y - 360;
+ if (fabs(deviation.y) < autocvar_bot_ai_bunnyhop_dir_deviation_max)
+ {
+ vector gco = get_closer_dest(this.goalcurrent, this.origin);
+ float vel = vlen(vec2(this.velocity));
+
+ // with the current physics, jump distance grows linearly with the speed
+ float jump_distance = 52.661 + 0.606 * vel;
+ jump_distance += this.origin.z - gco.z; // roughly take into account vertical distance too
+ if (vdist(vec2(gco - this.origin), >, max(0, jump_distance)))
+ can_run = true;
+ else if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP)
+ && !(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+ && this.goalstack01 && !wasfreed(this.goalstack01) && !(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP)
+ && vdist(vec2(gco - this.goalstack01.origin), >, 70))
+ {
+ vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+ vector ang = vectoangles(gco - this.origin);
+ deviation = vectoangles(gno - gco) - vel_angles;
+ while (deviation.y < -180) deviation.y = deviation.y + 360;
+ while (deviation.y > 180) deviation.y = deviation.y - 360;
+
+ float max_turn_angle = autocvar_bot_ai_bunnyhop_turn_angle_max;
+ max_turn_angle -= autocvar_bot_ai_bunnyhop_turn_angle_reduction * ((vel - autocvar_sv_maxspeed) / autocvar_sv_maxspeed);
+ if ((ang.x < 90 || ang.x > 360 - autocvar_bot_ai_bunnyhop_downward_pitch_max)
+ && fabs(deviation.y) < max(autocvar_bot_ai_bunnyhop_turn_angle_min, max_turn_angle))
+ {
+ can_run = true;
+ }
+ }
+ }
+ }
+
+ if (can_run)
+ {
+ PHYS_INPUT_BUTTON_JUMP(this) = true;
+ this.bot_jump_time = time;
+ this.aistatus |= AI_STATUS_RUNNING;
+ }
+ else
+ {
+ if (IS_ONGROUND(this) || this.waterlevel > WATERLEVEL_WETFEET)
+ this.aistatus &= ~AI_STATUS_RUNNING;
+ }
+}
+
void havocbot_keyboard_movement(entity this, vector destorg)
{
if(time <= this.havocbot_keyboardtime)
CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
}
-void havocbot_bunnyhop(entity this, vector dir)
-{
- // Don't jump when attacking
- if(this.aistatus & AI_STATUS_ATTACKING)
- return;
-
- if (!this.goalcurrent || IS_PLAYER(this.goalcurrent))
- return;
-
- if((this.aistatus & AI_STATUS_RUNNING) && vdist(this.velocity, <, autocvar_sv_maxspeed * 0.75)
- || (this.aistatus & AI_STATUS_DANGER_AHEAD))
- {
- this.aistatus &= ~AI_STATUS_RUNNING;
- PHYS_INPUT_BUTTON_JUMP(this) = false;
- this.bot_canruntogoal = 0;
- this.bot_timelastseengoal = 0;
- return;
- }
-
- if(this.waterlevel > WATERLEVEL_WETFEET || IS_DUCKED(this))
- {
- this.aistatus &= ~AI_STATUS_RUNNING;
- return;
- }
-
- if(this.bot_lastseengoal != this.goalcurrent && !(this.aistatus & AI_STATUS_RUNNING))
- {
- this.bot_canruntogoal = 0;
- this.bot_timelastseengoal = 0;
- }
-
- // Run only to visible goals
- if(IS_ONGROUND(this))
- if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
- if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
- {
- this.bot_lastseengoal = this.goalcurrent;
-
- // seen it before
- if(this.bot_timelastseengoal)
- {
- vector gco = get_closer_dest(this.goalcurrent, this.origin);
- // for a period of time
- if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
- {
- bool checkdistance = true;
-
- // don't run if it is too close
- if(this.bot_canruntogoal==0)
- {
- if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_startdistance))
- this.bot_canruntogoal = 1;
- else
- this.bot_canruntogoal = -1;
- }
-
- if(this.bot_canruntogoal != 1)
- return;
-
- if(this.aistatus & AI_STATUS_ROAMING)
- if(this.goalcurrent.classname == "waypoint")
- if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
- if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
- if (this.goalstack01 && !wasfreed(this.goalstack01))
- if (!(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP))
- {
- vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
- vector deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
- while (deviation.y < -180) deviation.y = deviation.y + 360;
- while (deviation.y > 180) deviation.y = deviation.y - 360;
-
- if(fabs(deviation.y) < 20)
- if(vlen2(this.origin - gco) < vlen2(this.origin - gno))
- if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
- {
- if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
- if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
- {
- checkdistance = false;
- }
- }
- }
-
- if(checkdistance)
- {
- this.aistatus &= ~AI_STATUS_RUNNING;
- // increase stop distance in case the goal is on a slope or a lower platform
- if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_stopdistance + (this.origin.z - gco.z)))
- PHYS_INPUT_BUTTON_JUMP(this) = true;
- }
- else
- {
- this.aistatus |= AI_STATUS_RUNNING;
- PHYS_INPUT_BUTTON_JUMP(this) = true;
- }
- }
- }
- else
- {
- this.bot_timelastseengoal = time;
- }
- }
- else
- {
- this.bot_timelastseengoal = 0;
- }
-}
-
// return true when bot isn't getting closer to the current goal
bool havocbot_checkgoaldistance(entity this, vector gco)
{
vector diff;
vector dir;
vector flatdir;
- vector evadeobstacle;
- vector evadelava;
float dodge_enemy_factor = 1;
float maxspeed;
//float dist;
* ((this.strength_finished > time) ? autocvar_g_balance_powerup_strength_selfdamage : 1) \
* ((this.invincible_finished > time) ? autocvar_g_balance_powerup_invincible_takedamage : 1)
- tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
- if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos ))
- if(this.items & IT_JETPACK)
+ // save some CPU cycles by checking trigger_hurt after checking
+ // that something can be done to evade it (cheaper checks)
+ int action_for_trigger_hurt = 0;
+ if (this.items & IT_JETPACK)
+ action_for_trigger_hurt = 1;
+ else if (!this.jumppadcount && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
+ && !(this.goalcurrent_prev && this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)
+ && GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR) > ROCKETJUMP_DAMAGE())
+ {
+ action_for_trigger_hurt = 2;
+ }
+ else if (!this.goalcurrent)
+ action_for_trigger_hurt = 3;
+
+ if (action_for_trigger_hurt)
+ {
+ tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
+ if(!tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos))
+ action_for_trigger_hurt = 0;
+ }
+
+ if(action_for_trigger_hurt == 1) // jetpack
{
tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 65536', MOVE_NOMONSTERS, this);
if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos + '0 0 1' ))
return;
}
- else if(!this.jumppadcount && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
- && !(this.goalcurrent_prev && this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)
- && GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR) > ROCKETJUMP_DAMAGE())
+ else if(action_for_trigger_hurt == 2) // rocketjump
{
if(this.velocity.z < 0)
{
}
}
}
- else
+ else if(action_for_trigger_hurt == 3) // no goal
{
// If there is no goal try to move forward
- if(this.goalcurrent==NULL)
- CS(this).movement_x = maxspeed;
+ CS(this).movement_x = maxspeed;
}
}
dir.z = 1;
else if(this.velocity.z >= 0 && !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER))
PHYS_INPUT_BUTTON_JUMP(this) = true;
- else
- PHYS_INPUT_BUTTON_JUMP(this) = false;
makevectors(this.v_angle.y * '0 1 0');
vector v = dir * maxspeed;
CS(this).movement.x = v * v_forward;
dir = normalize(diff);
flatdir = (diff.z == 0) ? dir : normalize(vec2(diff));
+ bool danger_detected = false;
+ vector do_break = '0 0 0';
+
//if (this.bot_dodgevector_time < time)
{
//this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
//this.bot_dodgevector_jumpbutton = 1;
- evadeobstacle = '0 0 0';
- evadelava = '0 0 0';
this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
makevectors(this.v_angle.y * '0 1 0');
}
else
{
- PHYS_INPUT_BUTTON_JUMP(this) = false;
if (destorg.z > this.origin.z)
dir = flatdir;
}
)
{
PHYS_INPUT_BUTTON_JUMP(this) = true;
- // avoid changing route while bot is jumping a gap
- navigation_goalrating_timeout_extend_if_needed(this, 1.5);
+ this.bot_jump_time = time;
}
}
else if (!this.goalstack01 || (this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER)))
vector jump_height = (IS_ONGROUND(this)) ? stepheightvec + jumpheight_vec : jumpstepheightvec;
tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
if (trace_fraction > s)
+ {
PHYS_INPUT_BUTTON_JUMP(this) = true;
+ this.bot_jump_time = time;
+ }
else
{
jump_height = stepheightvec + jumpheight_vec / 2;
tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
if (trace_fraction > s)
+ {
PHYS_INPUT_BUTTON_JUMP(this) = true;
+ this.bot_jump_time = time;
+ }
}
}
}
this.goalcurrent_distance_time = -time; // mark second try
}
- // Check for water/slime/lava and dangerous edges
- // (only when the bot is on the ground or jumping intentionally)
-
if (skill + this.bot_moveskill <= 3 && time > this.bot_stop_moving_timeout
&& current_speed > maxspeed * 0.9 && fabs(deviation.y) > 70)
{
this.bot_stop_moving_timeout = time + 0.4 + random() * 0.2;
}
+ // Check for water/slime/lava and dangerous edges
+ // (only when the bot is on the ground or jumping intentionally)
+
offset = (vdist(this.velocity, >, 32) ? this.velocity * 0.2 : flatdir * 32);
vector dst_ahead = this.origin + this.view_ofs + offset;
vector dst_down = dst_ahead - '0 0 3000';
//te_lightning2(NULL, dst_ahead, trace_endpos); // Draw "downwards" look
if(trace_endpos.z < this.origin.z + this.mins.z)
{
- s = pointcontents(trace_endpos + '0 0 1');
- if (s != CONTENT_SOLID)
- if (s == CONTENT_LAVA || s == CONTENT_SLIME)
- evadelava = normalize(this.velocity) * -1;
- else if (s == CONTENT_SKY)
- evadeobstacle = normalize(this.velocity) * -1;
- else if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ danger_detected = true;
+ else if (trace_endpos.z < min(this.origin.z + this.mins.z, this.goalcurrent.origin.z) - 100)
+ danger_detected = true;
+ else
{
- // the traceline check isn't enough but is good as optimization,
- // when not true (most of the time) this tracebox call is avoided
- tracebox(dst_ahead, this.mins, this.maxs, dst_down, true, this);
- if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+ s = pointcontents(trace_endpos + '0 0 1');
+ if (s != CONTENT_SOLID)
{
- if (destorg.z > this.origin.z + jumpstepheightvec.z)
+ if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+ danger_detected = true;
+ else if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
{
- // the goal is probably on an upper platform, assume bot can't get there
- unreachable = true;
+ // the traceline check isn't enough but is good as optimization,
+ // when not true (most of the time) this tracebox call is avoided
+ tracebox(dst_ahead, this.mins, this.maxs, dst_down, true, this);
+ if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+ {
+ if (destorg.z > this.origin.z + jumpstepheightvec.z)
+ {
+ // the goal is probably on an upper platform, assume bot can't get there
+ unreachable = true;
+ }
+ else
+ danger_detected = true;
+ }
}
- else
- evadelava = normalize(this.velocity) * -1;
}
}
}
}
dir = flatdir;
- evadeobstacle.z = 0;
- evadelava.z = 0;
makevectors(this.v_angle.y * '0 1 0');
- if(evadeobstacle || evadelava || (s == CONTENT_WATER))
+ if (danger_detected || (s == CONTENT_WATER))
{
this.aistatus |= AI_STATUS_DANGER_AHEAD;
if(IS_PLAYER(this.goalcurrent))
// tracebox wouldn't work when bot is still on the ledge
traceline(this.origin, this.origin - '0 0 200', true, this);
if (this.origin.z - trace_endpos.z > 120)
- evadeobstacle = normalize(this.velocity) * -1;
+ do_break = normalize(this.velocity) * -1;
}
if(unreachable)
dodge = havocbot_dodge(this);
if (dodge)
dodge *= bound(0, 0.5 + (skill + this.bot_dodgeskill) * 0.1, 1);
- dodge += evadeobstacle + evadelava;
- evadelava = evadelava * bound(1,3-(skill+this.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it
if (this.enemy)
{
traceline(this.origin, (this.enemy.absmin + this.enemy.absmax) * 0.5, true, NULL);
bot_aimdir(this, dir, 0);
}
+ vector evadedanger = '0 0 0';
if (!ladder_zdir)
{
dir *= dodge_enemy_factor;
- dir = normalize(dir + dodge);
+ if (danger_detected && vdist(this.velocity, >, maxspeed * 0.8) && this.goalcurrent_prev
+ && this.goalcurrent.classname == "waypoint")
+ {
+ vector p = this.origin + this.velocity * 0.2;
+ vector evadedanger = point_line_vec(p, vec2(this.goalcurrent_prev.origin) + eZ * p.z,
+ vec2(destorg - this.goalcurrent_prev.origin));
+ if (vdist(evadedanger, >, 20))
+ {
+ if (vdist(evadedanger, >, 40))
+ do_break = normalize(this.velocity) * -1;
+ evadedanger = normalize(evadedanger);
+ evadedanger *= bound(1, 3 - (skill + this.bot_dodgeskill), 3); // Noobs fear dangers a lot and take more distance from them
+ }
+ else
+ evadedanger = '0 0 0';
+ }
+ dir = normalize(dir + dodge + do_break + evadedanger);
}
makevectors(this.v_angle);
havocbot_keyboard_movement(this, destorg);
// Bunnyhop!
- if (!bunnyhop_forbidden && skill + this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
+ if (!bunnyhop_forbidden && !evadedanger && !do_break && skill + this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
havocbot_bunnyhop(this, dir);
if (dir * v_up >= autocvar_sv_jumpvelocity * 0.5 && IS_ONGROUND(this))
this.enemy = NULL;
return;
}
+
if (this.enemy)
{
if (!bot_shouldattack(this, this.enemy))
this.enemy = NULL;
this.havocbot_chooseenemy_finished = time;
}
- else if (this.havocbot_stickenemy)
+ else if (this.havocbot_stickenemy_time && time < this.havocbot_stickenemy_time)
{
// tracking last chosen enemy
- // if enemy is visible
- // and not really really far away
- // and we're not severely injured
- // then keep tracking for a half second into the future
- traceline(this.origin+this.view_ofs, ( this.enemy.absmin + this.enemy.absmax ) * 0.5,false,NULL);
+ vector targ_pos = (this.enemy.absmin + this.enemy.absmax) * 0.5;
+ traceline(this.origin + this.view_ofs, targ_pos, false, NULL);
if (trace_ent == this.enemy || trace_fraction == 1)
- if (vdist(((this.enemy.absmin + this.enemy.absmax) * 0.5) - this.origin, <, 1000))
- if (GetResource(this, RES_HEALTH) > 30)
+ if (vdist(targ_pos - this.origin, <, 1000))
{
// remain tracking him for a shot while (case he went after a small corner or pilar
this.havocbot_chooseenemy_finished = time + 0.5;
return;
}
- // enemy isn't visible, or is far away, or we're injured severely
- // so stop preferring this enemy
- // (it will still take a half second until a new one is chosen)
- this.havocbot_stickenemy = 0;
+
+ // stop preferring this enemy
+ this.havocbot_stickenemy_time = 0;
}
}
if (time < this.havocbot_chooseenemy_finished)
this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
vector eye = this.origin + this.view_ofs;
entity best = NULL;
- float bestrating = 100000000;
+ float bestrating = autocvar_bot_ai_enemydetectionradius ** 2;
// Backup hit flags
int hf = this.dphitcontentsmask;
vector v = (it.absmin + it.absmax) * 0.5;
float rating = vlen2(v - eye);
- if (vdist(v - eye, <, autocvar_bot_ai_enemydetectionradius))
- if (bestrating > rating)
- if (bot_shouldattack(this, it))
+ if (rating < bestrating && bot_shouldattack(this, it))
{
traceline(eye, v, true, this);
if (trace_ent == it || trace_fraction >= 1)
{
scan_secondary_targets = true;
// restart the loop
- bestrating = 100000000;
+ bestrating = autocvar_bot_ai_enemydetectionradius ** 2;
goto scan_targets;
}
this.dphitcontentsmask = hf;
this.enemy = best;
- this.havocbot_stickenemy = true;
+ this.havocbot_stickenemy_time = time + autocvar_bot_ai_enemydetectioninterval_stickingtoenemy;
if(best && best.classname == "misc_breakablemodel")
- this.havocbot_stickenemy = false;
+ this.havocbot_stickenemy_time = 0;
}
float havocbot_chooseweapon_checkreload(entity this, .entity weaponentity, int new_weapon)
.float havocbot_keyboardtime;
.float havocbot_ducktime;
-.float bot_timelastseengoal;
-.float bot_canruntogoal;
.float bot_chooseweapontime;
.float rocketjumptime;
.float nextaim;
.float havocbot_personal_waypoint_searchtime;
.float havocbot_personal_waypoint_failcounter;
.float havocbot_chooseenemy_finished;
-.float havocbot_stickenemy;
+.float havocbot_stickenemy_time;
.float havocbot_role_timeout;
.float bot_stop_moving_timeout;
return this.bot_strategytime < time;
}
+ERASEABLE
void navigation_goalrating_timeout_extend_if_needed(entity this, float seconds)
{
this.bot_strategytime = max(this.bot_strategytime, time + seconds);
if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
{
if(walkfromwp && !ent.navigation_dynamicgoal)
- {
waypoint_clearlinks(ent); // initialize wpXXmincost fields
- navigation_item_addlink(it, ent);
- }
return it;
}
});
org.z = ent.origin.z + ent.mins.z - PL_MIN_CONST.z; // player height
}
- if(!autocvar_g_waypointeditor && walkfromwp && !ent.navigation_dynamicgoal)
- {
- waypoint_clearlinks(ent); // initialize wpXXmincost fields
- IL_EACH(g_waypoints, it != ent,
- {
- if (walkfromwp && (it.wpflags & WPFLAGMASK_NORELINK))
- continue;
-
- set_tracewalk_dest(ent, it.origin, false);
- if (vdist(tracewalk_dest - it.origin, <, 1050)
- && tracewalk(ent, it.origin, PL_MIN_CONST, PL_MAX_CONST,
- tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
- {
- navigation_item_addlink(it, ent);
- }
- });
- }
-
// box check failed, try walk
IL_EACH(g_waypoints, it != ent,
{
if(e == NULL)
return false;
- if(nearest_wp && nearest_wp.enemy)
+ if(nearest_wp && nearest_wp.enemy && !(nearest_wp.enemy.wpflags & WPFLAGMASK_NORELINK))
{
// often path can be optimized by not adding the nearest waypoint
if (this.goalentity.navigation_dynamicgoal || autocvar_g_waypointeditor)
}
}
}
- else if(navigation_item_islinked(nearest_wp.enemy, this.goalentity))
- e = nearest_wp.enemy;
+ else
+ {
+ // NOTE unlike waypoints, items hold incoming links
+ navigation_item_initlinks_ifneeded(this.goalentity);
+ int link_num = navigation_item_getlinknum(this.goalentity, nearest_wp.enemy);
+ if (link_num >= 0)
+ {
+ if (navigation_item_iswalkablelink(this.goalentity, link_num))
+ e = nearest_wp.enemy;
+ }
+ else // untested link
+ {
+ entity wp = nearest_wp.enemy;
+ entity goal = this.goalentity;
+ bool walkable = false;
+ if (checkpvs(wp.origin, goal))
+ {
+ set_tracewalk_dest(goal, wp.origin, false);
+ if (vdist(tracewalk_dest - wp.origin, <, 1050)
+ && tracewalk(goal, wp.origin, PL_MIN_CONST, PL_MAX_CONST,
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+ {
+ walkable = true;
+ e = nearest_wp.enemy;
+ }
+ }
+ navigation_item_add_link(wp, goal, walkable);
+ }
+ }
}
for (;;)
}
// Loose goal touching check when running
- if(this.aistatus & AI_STATUS_RUNNING)
- if(this.goalcurrent.classname=="waypoint")
- if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running
- {
- if(vdist(this.origin - this.goalcurrent.origin, <, 150))
+ // check goalstack01 to make sure waypoint isn't the final goal
+ if(this.aistatus & AI_STATUS_RUNNING && this.goalcurrent.classname == "waypoint" && !(this.goalcurrent.wpflags & WAYPOINTFLAG_JUMP)
+ && this.goalstack01 && !wasfreed(this.goalstack01) && vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
+ {
+ vector gco = this.goalcurrent.origin;
+ float min_dist = BOT_BUNNYHOP_WP_DETECTION_RANGE;
+ // also detect waypoints when bot is way above them but with a narrower horizontal range
+ // so to increase chances bot ends up in the standard range (optimizes nearest waypoint finding)
+ if(vdist(this.origin - gco, <, min_dist)
+ || (vdist(vec2(this.origin - gco), <, min_dist * 0.5) && vdist(this.origin - eZ * 1.5 * min_dist - gco, <, min_dist)))
{
traceline(this.origin + this.view_ofs , this.goalcurrent.origin, true, NULL);
if(trace_fraction==1)
if(this.goalcurrent.classname == "waypoint" && !this.goalcurrent.wpisbox)
{
gc_min = this.goalcurrent.origin - '1 1 1' * 12;
- gc_max = this.goalcurrent.origin + '1 1 1' * 12;
+ gc_max = this.goalcurrent.origin + '1 1 1' * 12 + eZ * (jumpheight_vec.z + STAT(PL_MIN, this).z);
}
if (time < this.ladder_time)
{
wp = this.goalcurrent_prev;
if(!wp)
return NULL;
- if(wp != this.goalcurrent_prev && vdist(wp.origin - this.origin, >, 50))
+ float min_dist = ((this.aistatus & AI_STATUS_RUNNING) ? BOT_BUNNYHOP_WP_DETECTION_RANGE : 50);
+ if(wp != this.goalcurrent_prev && vdist(wp.origin - this.origin, >, min_dist))
{
wp = this.goalcurrent_prev;
if(!wp)
if(!wp)
return NULL;
}
- if(vdist(wp.origin - this.origin, >, 50))
+ if(vdist(wp.origin - this.origin, >, min_dist))
{
wp = NULL;
IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_JUMP)),
{
- if(vdist(it.origin - this.origin, <, 50))
+ if(vdist(it.origin - this.origin, <, min_dist))
{
wp = it;
break;
/*
// item it is linked from waypoint it.wpXX (INCOMING link)
// links are sorted by their cost (wpXXmincost)
+// one of these links is added in game every time a bot heads to an item
+// even links that are not walkable are added (marked with a high cost)
+// so that bots next time know if they can walk it or not saving a tracewalk call
.entity wp00, wp01, wp02, wp03, wp04, wp05, wp06, wp07, wp08, wp09, wp10, wp11, wp12, wp13, wp14, wp15;
.entity wp16, wp17, wp18, wp19, wp20, wp21, wp22, wp23, wp24, wp25, wp26, wp27, wp28, wp29, wp30, wp31;
.float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
*/
-#define navigation_item_islinked(from_wp, to_item) waypoint_islinked(to_item, from_wp)
-#define navigation_item_addlink(from_wp, to_item) \
- waypoint_addlink_customcost(to_item, from_wp, waypoint_getlinkcost(from_wp, to_item))
+#define navigation_item_initlinks_ifneeded(e) MACRO_BEGIN if (!e.wp00) waypoint_clearlinks(e); MACRO_END // initialize wpXXmincost fields
+#define navigation_item_getlinknum(to_item, from_wp) waypoint_getlinknum(to_item, from_wp)
+#define navigation_item_iswalkablelink(to_item, from_wp) (waypoint_get_assigned_link_cost(to_item, from_wp) < 999)
+
+#define navigation_item_add_link(from_wp, to_item, walkable) \
+ waypoint_addlink_customcost(to_item, from_wp, (walkable ? waypoint_getlinkcost(from_wp, to_item) : 999))
#define TELEPORT_USED(pl, tele_wp) \
boxesoverlap(tele_wp.absmin, tele_wp.absmax, pl.lastteleport_origin + STAT(PL_MIN, pl), pl.lastteleport_origin + STAT(PL_MAX, pl))
entity bot_waypoint_queue_bestgoal;
float bot_waypoint_queue_bestgoalrating;
+const float BOT_BUNNYHOP_WP_DETECTION_RANGE = 100;
+
.entity bot_basewaypoint;
.bool navigation_dynamicgoal;
void navigation_dynamicgoal_init(entity this, bool initially_static);
LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired");
}
+float waypoint_get_assigned_link_cost(entity w, float i)
+{
+ switch(i)
+ {
+ case 0: return w.wp00mincost;
+ case 1: return w.wp01mincost;
+ case 2: return w.wp02mincost;
+ case 3: return w.wp03mincost;
+ case 4: return w.wp04mincost;
+ case 5: return w.wp05mincost;
+ case 6: return w.wp06mincost;
+ case 7: return w.wp07mincost;
+ case 8: return w.wp08mincost;
+ case 9: return w.wp09mincost;
+ case 10: return w.wp10mincost;
+ case 11: return w.wp11mincost;
+ case 12: return w.wp12mincost;
+ case 13: return w.wp13mincost;
+ case 14: return w.wp14mincost;
+ case 15: return w.wp15mincost;
+ case 16: return w.wp16mincost;
+ case 17: return w.wp17mincost;
+ case 18: return w.wp18mincost;
+ case 19: return w.wp19mincost;
+ case 20: return w.wp20mincost;
+ case 21: return w.wp21mincost;
+ case 22: return w.wp22mincost;
+ case 23: return w.wp23mincost;
+ case 24: return w.wp24mincost;
+ case 25: return w.wp25mincost;
+ case 26: return w.wp26mincost;
+ case 27: return w.wp27mincost;
+ case 28: return w.wp28mincost;
+ case 29: return w.wp29mincost;
+ case 30: return w.wp30mincost;
+ case 31: return w.wp31mincost;
+ default: return -1;
+ }
+}
+
entity waypoint_get_link(entity w, float i)
{
switch(i)
void waypoint_clearlinks(entity wp);
void waypoint_schedulerelink(entity wp);
+float waypoint_get_assigned_link_cost(entity w, float i);
+
float waypoint_getlinkcost(entity from, entity to);
float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent);
float waypoint_getlinearcost(float dist);
return 0;
}
+int Campaign_GetLevelNum()
+{
+ return campaign_level + 1;
+}
+
+string Campaign_GetMessage()
+{
+ return strcat(campaign_shortdesc[0], "\n^3\n", campaign_longdesc[0]);
+}
+
void CampaignPreInit()
{
float baseskill;
- string title;
campaign_level = autocvar__campaign_index;
campaign_name = strzone(autocvar__campaign_name);
campaign_index_var = strzone(strcat("g_campaign", campaign_name, "_index"));
if(Campaign_Invalid())
return;
-
- title = campaign_shortdesc[0];
- title = strzone(strcat("Level ", ftos(campaign_level + 1), ": ", title));
- campaign_message = strzone(strcat(title, "\n^3\n", campaign_longdesc[0], "\n\n^1press jump to enter the game"));
- strunzone(title);
}
void CampaignPostInit()
CampaignSetup(campaign_won);
CampaignFile_Unload();
- strunzone(campaign_message);
strunzone(campaign_index_var);
strunzone(campaign_name);
campaign_name = "";
// this must be included BEFORE campaign_common.h to make this a memory saving
#define CAMPAIGN_MAX_ENTRIES 2
-string campaign_message;
+int Campaign_GetLevelNum();
+string Campaign_GetMessage();
void CampaignPreInit();
void CampaignPostInit();
this.strength_finished = 0;
this.invincible_finished = 0;
this.superweapons_finished = 0;
+ this.air_finished_stat = 0;
//this.dphitcontentsmask = 0;
this.dphitcontentsmask = DPCONTENTS_SOLID;
if (autocvar_g_playerclip_collisions)
STAT(BUFFS, this) = 0;
STAT(BUFF_TIME, this) = 0;
- this.air_finished = time + 12;
+ this.air_finished = time + autocvar_g_balance_contents_drowndelay;
this.waterlevel = WATERLEVEL_NONE;
this.watertype = CONTENT_EMPTY;
return max(stable, current + (stable - current) * rotfactor * rotframetime);
}
-float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit)
+void RotRegen(entity this, int res, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod)
{
+ float old = GetResource(this, res);
+ float current = old;
if(current > rotstable)
{
if(rotframetime > 0)
}
}
+ float limit = GetResourceLimit(this, res) * limit_mod;
if(current > limit)
current = limit;
- return current;
+ if (current != old)
+ SetResource(this, res, current);
}
void player_regen(entity this)
if(!mutator_returnvalue)
if(!STAT(FROZEN, this))
{
- float mina, maxa, limith, limita;
- maxa = autocvar_g_balance_armor_rotstable;
- mina = autocvar_g_balance_armor_regenstable;
- limith = GetResourceLimit(this, RES_HEALTH);
- limita = GetResourceLimit(this, RES_ARMOR);
+ float maxa = autocvar_g_balance_armor_rotstable;
+ float mina = autocvar_g_balance_armor_regenstable;
- regen_health_rotstable = regen_health_rotstable * max_mod;
- regen_health_stable = regen_health_stable * max_mod;
- limith = limith * limit_mod;
- limita = limita * limit_mod;
+ RotRegen(this, RES_ARMOR, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
+ regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
+ rot_mod * frametime * (time > this.pauserotarmor_finished), limit_mod);
- SetResource(this, RES_ARMOR, CalcRotRegen(GetResource(this, RES_ARMOR), mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
- regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
- rot_mod * frametime * (time > this.pauserotarmor_finished), limita));
- SetResource(this, RES_HEALTH, CalcRotRegen(GetResource(this, RES_HEALTH), regen_health_stable, regen_health, regen_health_linear,
- regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable, regen_health_rot, regen_health_rotlinear,
- rot_mod * frametime * (time > this.pauserothealth_finished), limith));
+ RotRegen(this, RES_HEALTH, regen_health_stable * max_mod, regen_health, regen_health_linear,
+ regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable * max_mod, regen_health_rot, regen_health_rotlinear,
+ rot_mod * frametime * (time > this.pauserothealth_finished), limit_mod);
}
// if player rotted to death... die!
if (!(this.items & IT_UNLIMITED_AMMO))
{
- float minf, maxf, limitf;
+ float maxf = autocvar_g_balance_fuel_rotstable;
+ float minf = autocvar_g_balance_fuel_regenstable;
- maxf = autocvar_g_balance_fuel_rotstable;
- minf = autocvar_g_balance_fuel_regenstable;
- limitf = GetResourceLimit(this, RES_FUEL);
-
- SetResource(this, RES_FUEL, CalcRotRegen(GetResource(this, RES_FUEL), minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
- frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
- maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), limitf));
+ RotRegen(this, RES_FUEL, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
+ frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
+ maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), 1);
}
}
this.strength_finished = spectatee.strength_finished;
this.invincible_finished = spectatee.invincible_finished;
this.superweapons_finished = spectatee.superweapons_finished;
+ this.air_finished_stat = spectatee.air_finished_stat;
STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee);
STAT(WEAPONS, this) = STAT(WEAPONS, spectatee);
this.punchangle = spectatee.punchangle;
if (CS(this).spectatee_status != oldspectatee_status)
{
+ if (STAT(PRESSED_KEYS, this))
+ {
+ CS(this).pressedkeys = 0;
+ STAT(PRESSED_KEYS, this) = 0;
+ }
ClientData_Touch(this);
if (g_race || g_cts) race_InitSpectator();
}
if (autocvar_g_campaign) {
if ((IS_PLAYER(this) && PHYS_INPUT_BUTTON_INFO(this)) || (!IS_PLAYER(this))) {
CS(this).motd_actived_time = time;
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, campaign_message);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_CAMPAIGN_MESSAGE, Campaign_GetMessage(), Campaign_GetLevelNum());
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this)) {
CS(this).motd_actived_time = time;
else if ((time - CS(this).motd_actived_time > 2) && IS_PLAYER(this)) { // hide it some seconds after BUTTON_INFO has been released
CS(this).motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this))
{
// instantly hide MOTD
CS(this).motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
+ if (autocvar_g_campaign)
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
+ else
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
else if (IS_PLAYER(this) || IS_SPEC(this))
{
if(this.air_finished < time)
PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+ this.air_finished_stat = 0;
}
else if (this.air_finished < time)
{ // drown!
Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
this.pain_finished = time + 0.5;
}
+ this.air_finished_stat = this.air_finished;
}
+ else
+ this.air_finished_stat = this.air_finished;
}
.bool move_qcphysics;
}
GetPressedKeys(this);
}
+ else if (IS_OBSERVER(this) && STAT(PRESSED_KEYS, this))
+ {
+ CS(this).pressedkeys = 0;
+ STAT(PRESSED_KEYS, this) = 0;
+ }
if (this.waypointsprite_attachedforcarrier) {
float hp = healtharmor_maxdamage(GetResource(this, RES_HEALTH), GetResource(this, RES_ARMOR), autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id).x;
ATTRIB(Client, autoswitch, bool, this.autoswitch);
ATTRIB(Client, cvar_cl_casings, bool, this.cvar_cl_casings);
ATTRIB(Client, cvar_cl_dodging_timeout, float, this.cvar_cl_dodging_timeout);
+ ATTRIB(Client, cvar_cl_dodging, float, this.cvar_cl_dodging);
ATTRIB(Client, cvar_cl_multijump, bool, this.cvar_cl_multijump);
ATTRIB(Client, cvar_cl_accuracy_data_share, bool, this.cvar_cl_accuracy_data_share);
ATTRIB(Client, cvar_cl_accuracy_data_receive, bool, this.cvar_cl_accuracy_data_receive);
void play_countdown(entity this, float finished, Sound samp);
-float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit);
+void RotRegen(entity this, float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod);
bool Spectate(entity this, entity pl);
return true;
}
+// NOTE: requires input to be surrounded by spaces
+string VoteCommand_checkreplacements(string input)
+{
+ string output = input;
+ // allow gotomap replacements
+ output = strreplace(" map ", " gotomap ", output);
+ output = strreplace(" chmap ", " gotomap ", output);
+ return output;
+}
+
float VoteCommand_checkinlist(string vote_command, string list)
{
- string l = strcat(" ", list, " ");
+ string l = VoteCommand_checkreplacements(strcat(" ", list, " "));
- if (strstrofs(l, strcat(" ", vote_command, " "), 0) >= 0) return true;
+ if (strstrofs(l, VoteCommand_checkreplacements(strcat(" ", vote_command, " ")), 0) >= 0) return true;
return false;
}
.float crouch; // Crouching or not?
const .float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
+const .float air_finished_stat = _STAT(AIR_FINISHED);
.float cnt; // used in too many places
.float count;
.float spectatortime; //point in time since the client is spectating or observing
void checkSpectatorBlock(entity this);
-float game_completion_ratio; // 0 at start, 1 near end
.float winning;
.float jointime; // time of connecting
.float startplaytime; // time of switching from spectator to player
break;
}
}
-
+
if (i == Map_Count)
{
bprint( "Maplist contains no usable maps! Resetting it to default map list.\n" );
cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
}
-float leaderfrags;
+int fragsleft_last;
float WinningCondition_Scores(float limit, float leadlimit)
{
- float limitreached;
-
// TODO make everything use THIS winning condition (except LMS)
WinningConditionHelper(NULL);
leadlimit = 0; // not supported in this mode
if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
- // these modes always score in increments of 1, thus this makes sense
{
- if(leaderfrags != WinningConditionHelper_topscore)
- {
- leaderfrags = WinningConditionHelper_topscore;
+ float fragsleft = FLOAT_MAX, leadingfragsleft = FLOAT_MAX;
+ if (limit)
+ fragsleft = limit - WinningConditionHelper_topscore;
+ if (leadlimit)
+ leadingfragsleft = WinningConditionHelper_secondscore + leadlimit - WinningConditionHelper_topscore;
- if (limit)
- {
- if (leaderfrags == limit - 1)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
- else if (leaderfrags == limit - 2)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
- else if (leaderfrags == limit - 3)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
- }
+ if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+ fragsleft = max(fragsleft, leadingfragsleft);
+ else
+ fragsleft = min(fragsleft, leadingfragsleft);
+
+ if (fragsleft_last != fragsleft) // do not announce same remaining frags multiple times
+ {
+ if (fragsleft == 1)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
+ else if (fragsleft == 2)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
+ else if (fragsleft == 3)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
+
+ fragsleft_last = fragsleft;
}
}
- limitreached = false;
- if (limit && WinningConditionHelper_topscore >= limit)
- limitreached = true;
- if(leadlimit)
- {
- float leadlimitreached;
- leadlimitreached = (WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
- if(autocvar_leadlimit_and_fraglimit)
- limitreached = (limitreached && leadlimitreached);
- else
- limitreached = (limitreached || leadlimitreached);
- }
+ bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
+ bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
- if(limit)
- game_completion_ratio = max(game_completion_ratio, bound(0, WinningConditionHelper_topscore / limit, 1));
+ bool limit_reached;
+ // only respect leadlimit_and_fraglimit when both limits are set or the game will never end
+ if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+ limit_reached = (fraglimit_reached && leadlimit_reached);
+ else
+ limit_reached = (fraglimit_reached || leadlimit_reached);
return GetWinningCode(
- WinningConditionHelper_topscore && limitreached,
+ WinningConditionHelper_topscore && limit_reached,
WinningConditionHelper_equality
);
}
*/
void CheckRules_World()
{
- float timelimit;
- float fraglimit;
- float leadlimit;
-
VoteThink();
MapVote_Think();
return;
}
- timelimit = autocvar_timelimit * 60;
- fraglimit = autocvar_fraglimit;
- leadlimit = autocvar_leadlimit;
+ float timelimit = autocvar_timelimit * 60;
+ float fraglimit = autocvar_fraglimit;
+ float leadlimit = autocvar_leadlimit;
+ if (leadlimit < 0) leadlimit = 0;
if(warmup_stage || time <= game_starttime) // NOTE: this is <= to prevent problems in the very tic where the game starts
{
float wantovertime;
wantovertime = 0;
- if(timelimit > game_starttime)
- game_completion_ratio = (time - game_starttime) / (timelimit - game_starttime);
- else
- game_completion_ratio = 0;
-
if(checkrules_suddendeathend)
{
if(!checkrules_suddendeathwarning)
{
if (Ban_IsClientBanned(client, -1))
{
- string s = sprintf("^1NOTE:^7 banned client %s just tried to enter\n", client.netaddress);
+ if (!client.crypto_idfp)
+ LOG_INFOF("^1NOTE:^7 banned client %s just tried to enter\n",
+ client.netaddress);
+ else
+ LOG_INFOF("^1NOTE:^7 banned client %s (%s) just tried to enter\n",
+ client.netaddress, client.crypto_idfp);
+
if(autocvar_g_ban_telluser)
sprint(client, "You are banned from this server.\n");
dropclient(client);
- bprint(s);
return true;
}
return false;
reason = strcat(reason, ", ");
reason = strcat(reason, it.netname);
}
- s = strcat(s, "^1NOTE:^7 banned client ", it.netaddress, "^7 has to go\n");
+ s = strcat(s, "^1NOTE:^7 banned client ", it.netname, "^7 has to go\n");
dropclient(it);
}
});
}
}
firstPlaceVotes = RandomSelection_best_priority;
- if ( autocvar_sv_vote_gametype_default_current && currentVotes == firstPlaceVotes )
+ if ( autocvar_sv_vote_gametype_default_current && firstPlaceVotes == 0 )
firstPlace = currentPlace;
else
firstPlace = RandomSelection_chosen_float;
float Cosine_Interpolate(float a, float b, float c)
{
- float ft = c * 3.1415927;
+ float ft = c * M_PI;
float f = (1 - cos(ft)) * 0.5;
return a*(1-f) + b*f;
this.flags &= ~FL_INWATER;
this.dmgtime = 0;
}
- this.air_finished = time + 12;
+ this.air_finished = time + autocvar_g_balance_contents_drowndelay;
}
}
bool restartanim;
if (fr == WFRAME_DONTCHANGE)
{
+ // this can happen when the weapon entity is newly spawned, since it has a clear state and no previous weapon frame
+ if (this.wframe == WFRAME_DONTCHANGE)
+ this.wframe = WFRAME_IDLE;
fr = this.wframe;
restartanim = false;
}
seta cl_eventchase_spectated_change 0 "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_death 2 "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"
seta cl_eventchase_distance 140 "final camera distance"
set bot_ai_thinkinterval 0.05 "Frame rate at which bots update their navigation and aiming, scales by skill"
set bot_ai_strategyinterval 7 "How often a new objective is chosen"
set bot_ai_strategyinterval_movingtarget 5.5 "How often a new objective is chosen when current objective can move"
-set bot_ai_enemydetectioninterval 2 "How often bots pick a new target"
+set bot_ai_enemydetectioninterval 2 "How often bots try to pick a new target if no suitable target is found"
+set bot_ai_enemydetectioninterval_stickingtoenemy 4 "How often bots try to pick a new target while targetting an enemy"
set bot_ai_enemydetectionradius 10000 "How far bots can see enemies"
set bot_ai_dodgeupdateinterval 0.2 "How often scan for items to dodge. Currently not in use."
set bot_ai_chooseweaponinterval 0.5 "How often the best weapon according to the situation will be chosen"
set bot_ai_friends_aware_pickup_radius "500" "Bots will not pickup items if a team mate is this distance near the item"
set bot_ai_ignoregoal_timeout 3 "Ignore goals making bots to get stuck in front of a wall for N seconds"
set bot_ai_bunnyhop_skilloffset 7 "Bots with skill equal or greater than this value will perform the \"bunnyhop\" technique"
-set bot_ai_bunnyhop_startdistance 200 "Run to goals located further than this distance"
-set bot_ai_bunnyhop_stopdistance 300 "Stop jumping after reaching this distance to the goal"
-set bot_ai_bunnyhop_firstjumpdelay 0.2 "Start running to the goal only if it was seen for more than N seconds"
+set bot_ai_bunnyhop_dir_deviation_max 20 "bunnyhop if speed - direction deviation is <= this amount"
+set bot_ai_bunnyhop_downward_pitch_max 30 "bunnyhop if downard pitch towards the next waypoint is <= this amount"
+set bot_ai_bunnyhop_turn_angle_max 80 "bunnyhop if next turn angle is <= this amount at walk speed (sv_maxspeed)"
+set bot_ai_bunnyhop_turn_angle_min 4 "bunnyhop regardless of speed if next turn angle is <= this amount"
+set bot_ai_bunnyhop_turn_angle_reduction 40 "linearly reduce max turn angle by this amount when speed increases by sv_maxspeed"
set bot_god 0 "god mode for bots"
set bot_ai_navigation_jetpack 0 "Enable bots to navigate maps using the jetpack"
set bot_ai_navigation_jetpack_mindistance 3500 "Bots will try fly to objects located farther than this distance"
set g_shootfromeye 0 "shots are fired from your eye/crosshair; visual gun position can still be influenced by cl_gunalign 1 and 2"
set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"
set g_shootfromfixedorigin "" "if set to a string like 0 y z, the gun is moved to the given y and z coordinates. If set to a string like x y z, the whole shot origin is used"
-set g_pinata 0 "if set to 1 you will not only drop your current weapon when you are killed, but you will drop all weapons that you possessed"
set g_weapon_stay 0 "1: ghost weapons can be picked up but give no ammo, thrown guns have ammo 2: ghost weapons can be picked up and refill ammo to one pickup size, thrown guns have no ammo (to prevent infinite ammo abuse)"
set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default"
sv_gameplayfix_q2airaccelerate 1
sv_gameplayfix_stepmultipletimes 1
sv_gameplayfix_stepdown 2
+// only available in qc physics
+set sv_gameplayfix_stepdown_maxspeed 0 "maximum speed walking entities can be moving for stepping down to apply - requires sv_qcphysics 1"
// delay for "kill" to prevent abuse
set g_balance_kill_delay 2 "timer before death when using the kill command"